package com.udapsoft.waf.common.util;

import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.Key;
import java.util.ArrayList;
import java.util.List;

import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.DESedeKeySpec;

import kr.co.hsnc.common.base.WAFLogger;
import kr.co.hsnc.common.config.WAFConfig;
import kr.co.hsnc.common.util.StringUtil;

public class StringUtils extends kr.co.hsnc.common.util.StringUtil {

	/**
	 * Source String을 delimeter로 분리해서 String Array로 리턴한다.
	 * 
	 * @param src
	 * @param delimeter
	 * @return
	 * @see kr.co.hsnc.common.util.StringUtil#split(java.lang.String,
	 *      java.lang.String)
	 */
	public static String[] split(String src, String delimeter) {

		return splitStr(src, delimeter);
	}

	/**
	 * Source String의 특정문자를 특정문자로 치환하여 리턴한다
	 * 
	 * @param src
	 * @param str1
	 * @param str2
	 * @return
	 * @see kr.co.hsnc.common.util.StringUtil#split(java.lang.String,
	 *      java.lang.String)
	 */
	public static String replace(String src, String str1, String str2) {

		return StringUtil.replace(src, str1, str2);
	}

	/**
	 * src1 이 src2 와 같은 문자열일 경우 str1를 리턴, 다를경우 str2를 리턴.
	 * 
	 * @param src1
	 * @param src2
	 * @param str1
	 * @param str2
	 * @return
	 */
	public static String decode(String src1, String src2, String str1,
			String str2) {
		if (src1.equals(src2)) {
			return str1;
		} else {
			return str2;
		}
	}

	/**
	 * Null값이 들어 있는 String을 ""으로 리턴한다.
	 * 
	 * @param src
	 * @return
	 */
	public static String nvl(String src) {
		if (src == null)
			return "";
		if ("null".equalsIgnoreCase(src))
			return "";
		return src;
	}

	/**
	 * Null값이 들어 있는 String을 ""으로 리턴한다.
	 * 
	 * @param src
	 * @return
	 */
	public static String nvl(String src, String s) {
		src = nvl(src);
		if ("".equals(src))
			return s;
		return src;
	}

	/**
	 * Null값이 들어 있는 String을 "0"으로 리턴한다.
	 * 
	 * @param src
	 * @return
	 */
	public static String nvl0(String src) {
		if (src == null)
			return "0";
		if ("null".equalsIgnoreCase(src))
			return "0";
		if ("".equals(src))
			return "0";
		return src;
	}

	/**
	 * @param srcs
	 * @param delimeter
	 * @return
	 */
	public static String merge(String[] srcs, String delimeter) {

		if (srcs == null)
			return "";

		String returnValue = "";
		int cnt = srcs.length;
		if (cnt == 1)
			return nvl(srcs[0]);

		for (int i = 0; i < cnt; i++) {
			if (i == 0) {
				returnValue = nvl(srcs[0]);
			} else {
				returnValue += delimeter + nvl(srcs[i]);
			}
		}
		return returnValue;
	}

	/**
	 * Source String을 delimeter로 분리해서 String Array로 리턴한다.
	 * 
	 * @param src
	 * @param delimeter
	 * @return
	 */
	public static String[] splitStr(String src, String delimeter) {

		String[] r = new String[countStr(src, delimeter) + 1];
		if (src == null) {
			r[0] = "";
			return r;
		}
		if (src.indexOf(delimeter) != -1) {
			int pos = 0;
			int j = 0;
			int cnt = src.length();
			for (int i = 0; i < cnt; i++) {
				if (src.charAt(i) == delimeter.charAt(0)) {
					r[j++] = src.substring(pos, i);
					pos = i + 1;
				}
			}
			r[j++] = src.substring(pos, src.length());
		} else {
			r[0] = src;
		}
		return r;
	}

	/**
	 * Source String에 delimeter가 존재하는 갯수를 리턴한다.
	 * 
	 * @param src
	 * @param delimeter
	 * @return
	 */
	public static int countStr(String src, String delimeter) {

		if (src == null)
			return -1;
		int count = 0;
		if (src.indexOf(delimeter) != -1) {
			int cnt = src.length();
			for (int i = 0; i < cnt; i++) {
				if (src.charAt(i) == delimeter.charAt(0)) {
					count = count + 1;
				}
			}
		}
		return count;
	}

	/**
	 * 8자리(예 : 20020626)의 날짜를 2002-06-26 처럼 변환.
	 * 
	 * @param date
	 * @return Format date
	 */
	public static String getDateFormat(String date) {
		if (date.length() < 8)
			return "";
		return date.substring(0, 4) + "-" + date.substring(4, 6) + "-"
				+ date.substring(6, 8);
	}

	/**
	 * 8자리(예 : 20020626)의 날짜를 2002년06월26일 처럼 변환.
	 * 
	 * @param date
	 * @return Format date
	 */
	public static String getDateHanFormat(String date) {
		if (date.length() < 8)
			return "";
		return date.substring(0, 4) + "년 " + date.substring(4, 6) + "월 "
				+ date.substring(6, 8) + "일 ";
	}

	/**
	 * 10자리(예 : 1234567890)의 사업자번호를 123-45-67890 처럼 변환.
	 * 
	 * @param String
	 * @return Format String
	 */
	public static String getBizNo(String bizno) {
		if (bizno.length() < 10)
			return "";
		return bizno.substring(0, 3) + "-" + bizno.substring(3, 5) + "-"
				+ bizno.substring(5, 10);
	}

	/**
	 * 13자리(예 : 1234567890123)의 주민등록번호를 123456-7890123 처럼 변환.
	 * 
	 * @param String
	 * @return Format String
	 */
	public static String getResidNo(String residno) {
		if (residno.length() < 13)
			return "";
		return residno.substring(0, 6) + "-" + residno.substring(6, 13);
	}

	/**
	 * 오른쪽 패딩
	 * 
	 * @param s
	 *            - 문자열
	 * @param size
	 *            - 크기
	 * @param padStr
	 *            - 채울문자
	 * @return
	 */
	public static String rightPad(String s, int size, String padStr) {
		if (s.length() > size)
			return s.substring(0, size);
		while (s.length() < size)
			s += padStr;
		return s.substring(0, size);
	}

	/**
	 * 왼쪽 패딩
	 * 
	 * @param s
	 *            - 문자열
	 * @param size
	 *            - 크기
	 * @param padStr
	 *            - 채울문자
	 * @return
	 */
	public static String leftPad(String s, int size, String padStr) {
		if (s.length() > size)
			return s.substring(s.length() - size);
		while (s.length() < size)
			s = padStr + s;
		return s.substring(s.length() - size);
	}

	/**
	 * 특정문자열을 지정한 갯수만큼 반복해서 리턴한다.
	 * 
	 * @param s
	 *            -문자열
	 * @param cnt
	 *            - 반복횟
	 * @return
	 */
	public static String addStr(String s, int cnt) {
		int i = 0;
		StringBuffer sb = new StringBuffer();
		while (++i <= cnt) {
			sb.append(s);
		}
		return sb.toString();
	}

	static char[] chars = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
			'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
			'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
			'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
			'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0' };

	/**
	 * 길이만큼 임의문자열을 리턴 문자열은 영문자와숫자로 구성
	 * 
	 * @param size
	 * @return
	 */
	public static String getRandomString(int size) {
		String randomString = "";
		for (int i = 0; i < size; i++) {
			randomString += chars[(int) (Math.random() * 62)];
		}
		return randomString;
	}

	public static String cvtHTML(String str) {

		StringBuffer sb = new StringBuffer();

		int len = (str != null) ? str.length() : 0;
		for (int i = 0; i < len; i++) {
			char ch = str.charAt(i);
			switch (ch) {
			case ' ':
				sb.append("&nbsp;");
				break;
			case '<':
				sb.append("&lt;");
				break;
			case '>':
				sb.append("&gt;");
				break;
			case '&':
				sb.append("&amp;");
				break;
			case '"':
				sb.append("&quot;");
				break;
			case '\'':
				sb.append("&acute;");
				break;
			case '\t':
				sb.append("&nbsp;&nbsp;&nbsp;&nbsp;");
				break;
			case '\n':
				sb.append("<br>");
				break;
			default:
				sb.append(ch);
			}
		}
		return sb.toString();
	}

	public static String cvtHTML2(String str) {

		StringBuffer sb = new StringBuffer();

		int len = (str != null) ? str.length() : 0;
		for (int i = 0; i < len; i++) {
			char ch = str.charAt(i);
			switch (ch) {
			case ' ':
				sb.append("&nbsp;");
				break;
			case '<':
				sb.append("&lt;");
				break;
			case '>':
				sb.append("&gt;");
				break;
			case '&':
				sb.append("&amp;");
				break;
			case '"':
				sb.append("&quot;");
				break;
			case '\'':
				sb.append("&acute;");
				break;
			default:
				sb.append(ch);
			}
		}
		return sb.toString();
	}

	public static String cvtTree(String str) {

		StringBuffer sb = new StringBuffer();

		int len = (str != null) ? str.length() : 0;
		for (int i = 0; i < len; i++) {
			char ch = str.charAt(i);
			switch (ch) {
			case '<':
				sb.append("&lt;");
				break;
			case '>':
				sb.append("&gt;");
				break;
			case '"':
				sb.append("&quot;");
				break;
			default:
				sb.append(ch);
			}
		}
		return sb.toString();
	}

	public static boolean isNumberStr(String str) {
		if (str == null || str.equals("")) {
			return false;
		}
		return str.matches("[0-9.-]{1,}");
	}

	// 문자열의 넓이를 구함 (픽셀, 굴림, 12px 기준)
	public static int getStringPixelWidth(String str) {

		char[] characters = str.toCharArray();
		int total_width = 0;

		int special_char_size = 6;
		int multibyte_char_size = 12;
		int base_char_start = 32;
		int base_char_end = 127;
		int ascii_char_size[] = { 4, 4, 4, 6, 6, 10, 8, 4, 5, 5, 6, 6, 4, 6, 4,
				6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 4, 4, 8, 6, 8, 6, 12, 8, 8, 9,
				8, 8, 7, 9, 8, 3, 6, 8, 7, 11, 9, 9, 8, 9, 8, 8, 8, 8, 8, 10,
				8, 8, 8, 6, 11, 6, 6, 6, 4, 7, 7, 7, 7, 7, 3, 7, 7, 3, 3, 6, 3,
				11, 7, 7, 7, 7, 4, 7, 3, 7, 6, 10, 7, 7, 7, 6, 6, 6, 9, 6 };

		for (int i = 0; i < characters.length; i++) {

			int character_width = 0;
			int ascii_index = characters[i];

			if (ascii_index < base_char_start) {
				character_width = special_char_size;
			} else if (ascii_index <= base_char_end) {
				int idx = ascii_index - base_char_start;
				character_width = ascii_char_size[idx];
			} else if (ascii_index > base_char_end) {
				character_width = multibyte_char_size;
			}
			total_width += character_width;
		}
		return total_width;
	}

	/**
	 * 입력된 숫자를 한글로 변환해서 반환한다.
	 * 
	 * @param num
	 * @return
	 */

	public static String numberToHangul(String num, String curr) {

		if (num.indexOf(",") != -1)
			num = replace(num, ",", "");

		String[] bigUnitArray = { "", "만", "억", "조" };
		String[] unitArray = { "", "십", "백", "천" };
		String[] hanArray = { "", "일", "이", "삼", "사", "오", "육", "칠", "팔", "구" };
		List<String> splitedNum = new ArrayList<String>();

		String han = "";
		String tmp = "";
		int tmplen = 0;
		String n = "";
		int splietedNumSize = 0;

		int pos = num.length();
		int idx = 0;

		try {
			while (true) {
				if (pos - 4 > 0) {
					splitedNum.add(idx, num.substring(pos - 4, pos));
				} else {
					splitedNum.add(idx, num.substring(0, pos));
					break;
				}
				pos = pos - 4;
				idx++;
			}

			splietedNumSize = splitedNum.size();
			for (int j = splietedNumSize - 1; j >= 0; j--) {

				tmp = (String) splitedNum.get(j);
				tmplen = ((String) splitedNum.get(j)).length();
				n = "";
				for (int i = tmplen; i > 0; i--) {

					n = String.valueOf(tmp.charAt(tmplen - i));
					if (n.equals("0"))
						continue;
					if (n.equals("1") && i != 1
							&& !(j == splietedNumSize - 1 && i == tmplen)) {

						han += unitArray[i - 1];
					} else {

						han += hanArray[Integer.parseInt(n)] + unitArray[i - 1];
					}
				}
				if (!tmp.equals("0"))
					han += bigUnitArray[j];
			}
			if (!han.equals(""))
				han += curr;
		} catch (Exception e) {
			WAFLogger.error(e);
		}
		return han;
	}

	public static String URLEncode(String str) throws Exception {
		return URLEncoder.encode(str, "utf-8");
	}

	public static String URLDecode(String str) throws Exception {
		return URLDecoder.decode(str, "utf-8");
	}

	/**
	 * 바이트 배열을 hex 문자열로 바꿈
	 * 
	 * @param b
	 *            바이트배열
	 * @return hex 문자열
	 */
	public static String toHexString(byte[] b) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < b.length; i++) {
			appendHex(sb, b[i]);
		}
		return sb.toString();
	}

	public static void appendHex(StringBuffer b, byte n) {
		b.append(getHexB((n & 0xf0) >> 4));
		b.append(getHexB((n & 0x0f)));
	}

	public static char getHexB(int no) {
		return (char) (no >= 10 ? no - 10 + 'a' : '0' + no);
	}

	/**
	 * 2010.08.10 고용혁 추가. 날짜형식 구분자 주기
	 * 
	 * @param code
	 *            (날짜)
	 * @param type
	 *            (구분값)
	 * @return String bb = util.getDateFull("20090310150512","-") -> 2009-03-10
	 *         15:05:12
	 */
	public static String getDateFull(String code, String type) {
		String temp = "";
		if (code == null || "".equals(code)) {
			temp = "";
		} else if (code.length() == 8) {
			temp = code.substring(0, 4) + type + code.substring(4, 6) + type
					+ code.substring(6, 8);
		} else if (code.length() == 12) {
			temp = code.substring(0, 4) + type + code.substring(4, 6) + type
					+ code.substring(6, 8) + " " + code.substring(8, 10) + ":"
					+ code.substring(10, 12);
		} else if (code.length() == 14) {
			temp = code.substring(0, 4) + type + code.substring(4, 6) + type
					+ code.substring(6, 8) + " " + code.substring(8, 10) + ":"
					+ code.substring(10, 12) + ":" + code.substring(12, 14);
		}
		return temp;
	}

	/**
	 * 2012.01.31 이범근 추가 그룹웨어 SSO 연동시 사번 Decryption.
	 * 
	 * @param enkey
	 * @param codedID
	 * @return
	 * @throws Exception
	 */
	public static String decrypt(String enkey, String codedID) throws Exception {
		if (codedID == null || codedID.length() == 0)
			return "";

		String instance = (key(enkey).length() == 24) ? "DESede/ECB/PKCS5Padding"
				: "DES/ECB/PKCS5Padding";
		javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance(instance);
		cipher.init(javax.crypto.Cipher.DECRYPT_MODE, getKey(enkey));
		sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();

		byte[] inputBytes1 = decoder.decodeBuffer(codedID);
		byte[] outputBytes2 = cipher.doFinal(inputBytes1);

		String strResult = new String(outputBytes2, "UTF8");
		return strResult;
	}

	/**
	 * 2012.01.31 이범근 추가. 그룹웨어 SSO 연동시 암호화키값을 리턴
	 * 
	 * @param enkey
	 * @return
	 * 
	 */
	public static String key(String enkey) {

		String keystr = WAFConfig.get("waf.gw.key");
		if (enkey.equals("enckey"))
			keystr = "";

		return keystr;
	}

	/**
	 * 2012.01.31 이범근 추가. 암호화 자리수에 따라 암호화 키를 리턴한다.
	 * 
	 * @param enkey
	 * @return
	 * @throws Exception
	 */
	public static Key getKey(String enkey) throws Exception {
		return (key(enkey).length() == 24) ? getKey2(key(enkey))
				: getKey1(key(enkey));
	}

	public static Key getKey2(String keyValue) throws Exception {
		DESedeKeySpec desKeySpec = new DESedeKeySpec(keyValue.getBytes());
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
		Key key = keyFactory.generateSecret(desKeySpec);
		return key;
	}

	public static Key getKey1(String keyValue) throws Exception {
		DESKeySpec desKeySpec = new DESKeySpec(keyValue.getBytes());
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
		Key key = keyFactory.generateSecret(desKeySpec);
		return key;
	}
	
	 public static String cvtHTML3(String str) {

	        StringBuffer sb = new StringBuffer();

	        int len = (str != null) ? str.length() : 0;
	        for (int i = 0; i < len; i++) {
	            char ch = str.charAt(i);
	            switch (ch) {
	            case '<':
	                    sb.append("&lt;");
	                    break;
	            case '>':
	                    sb.append("&gt;");
	                    break;
	            case '&':
	                    sb.append("&amp;");
	                    break;
	            case '"':
	                    sb.append("&quot;");
	                    break;
	            case '\'':
	                    sb.append("&acute;");
	                    break;
	            default:
	                    sb.append(ch);
	            }
	        }
	        return sb.toString();
	    }
	 
	 
	 public static String cvtHTML4(String str) {

			StringBuffer sb = new StringBuffer();

			int len = (str != null) ? str.length() : 0;
			for (int i = 0; i < len; i++) {
				char ch = str.charAt(i);
				switch (ch) {
				case '\n':
					sb.append("<br>");
					break;
				default:
					sb.append(ch);
				}
			}
			return sb.toString();
		}

}