package itn.com.cmm.util;

import java.io.StringWriter;
import java.io.Writer;
import java.text.DecimalFormat;
import java.text.MessageFormat;
import java.text.ParseException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

import itn.let.utl.sim.service.EgovFileScrty;

//import com.google.common.base.CaseFormat;

//import egovframework.let.clean.core.base.CoreConstant;
//import egovframework.let.clean.core.exception.BaseException;

public final class StringUtil2 {
    private static final int HIGHEST_SPECIAL = '>'; // for escaping html code. by hessie; since 2007/10/01.
    private static final int LOWEST_SPECIAL = '\"'; // for escaping html code. by hessie; since 2007/10/01.
    private static final int HIGHEST_BR = '\r'; // for escaping html code. by hessie; since 2007/10/01.
    private static final int LOWEST_BR = '\n'; // for escaping html code. by hessie; since 2007/10/01.
    private static final int HIGHEST_JS_SPECIAL = '\\'; // for escaping js literal code. by hessie; since 2007/10/01
    private static char[][] specialCharactersRepresentation = new char[HIGHEST_SPECIAL + 1][];
    private static char[][] specialCharactersRepresentationWithNbsp = new char[HIGHEST_SPECIAL + 1][];

    public static String toString(Object o) {
        if (o == null) {
            return null;
        }
        return o.toString();
    }

    public static String toString(Object o, String defaultValue) {
        if (o == null) {
            return defaultValue;
        }
        return o.toString();
    }

    public static boolean isEmpty(String value) {
        return (value == null || value.length() == 0);
    }

    public static boolean isNotEmpty(String value) {
        return !isEmpty(value);
    }

    public static String trim(String value) {
        if (value == null) {
            return null;
        }
        return value.trim();
    }

    public static String lpad(String value, int len, String pad) {
        if (value == null) {
            value = "";
        }
        return StringUtils.leftPad(value, len, pad);
    }

    public static String rpad(String value, int len, String pad) {
        if (value == null) {
            value = "";
        }
        return StringUtils.rightPad(value, len, pad);
    }

    public static String rpadb(String value, int len, String pad) {
        if (value == null) {
            value = "";
        }
        int preLen = value.getBytes().length;

        return StringUtils.rightPad(value, len - preLen + value.length(), pad);
    }

    public static String rpadb(String value, int len, String pad, String encoding) throws Exception {
    	if (value == null) {
    		value = "";
    	}
    	int preLen = value.getBytes(encoding).length;

    	return StringUtils.rightPad(value, len - preLen + value.length(), pad);
    }

//    public static String camelLower(String name) {
//        return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name);
//    }
//
//    public static String camelUpper(String name) {
//        return CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, name);
//    }

    /**
     * 메시지 Format
     *
     * @param msg
     *            - "{0}는 {1}자리입니다."
     * @param params
     *            - new Object[]{"ID", 8}
     * @return
     */
    public static String msgFormat(String msg, Object... params) {
        String formatMsg = null;
        if (StringUtil2.isNotEmpty(msg)) {
            if (params != null && params.length > 0) {
                formatMsg = MessageFormat.format(msg, params);
            } else {
                formatMsg = msg;
            }
        }
        return formatMsg;
    }

    /**
     * 메시지 Parse
     *
     * @param pattern
     *            - "{0}는 {1}자리입니다."
     * @param msg
     *            - "ID는 8자리입니다."
     * @return new Object[]{"ID", 8}
     */
    public static Object[] msgParse(String pattern, String msg) {
        Object[] params = null;
        if (StringUtil2.isEmpty(pattern)) {
            return params;
        }
        if (StringUtil2.isEmpty(msg)) {
            return params;
        }
        try {
            MessageFormat formatter = new MessageFormat(pattern);
            params = formatter.parse(msg);
        } catch (ParseException e) {
//            throw new BaseException(e);
        }
        return params;
    }

    public static String formatPhone(String value, boolean crypt) {
        String format = null;
        if (value == null) {
            return format;
        }
        format = value.replaceAll(" ", "");
        int formatLen = format.length();
        if (formatLen < 1) {
            return format;
        }
        if (formatLen == 8) {
            if (crypt) {
                format = format.replaceAll("^(\\d{4})(\\d{2})(\\d{2})$", "$1-**$3");
            } else {
                format = format.replaceAll("^(\\d{4})(\\d{4})$", "$1-$2");
            }
        } else if (formatLen >= 9 && formatLen <= 12) {
            if (crypt) {
                format = format.replaceAll("^(02.{0}|01.{1}|050.{1}|[0-9]{3})([0-9]+)([0-9]{4})$", "$1-****-$3");
            } else {
                format = format.replaceAll("^(02.{0}|01.{1}|050.{1}|[0-9]{3})([0-9]+)([0-9]{4})$", "$1-$2-$3");
            }
        } else {
            if (crypt) {
                format = format.replaceAll("^(\\d+)(\\d{2})$", "$1**");
            } else {
                // nothing..
            }
        }
        return format;
    }

    public static String formatPhone(String value) {
        return StringUtil2.formatPhone(value, false);
    }

    public static String formatJdNo(String value) {
        String format = null;
        if (StringUtil2.isEmpty(value)) {
            return format;
        }
        format = value.replaceAll("^(\\d{2})(\\d{4})(\\d{1})(\\d{5})(\\d{2})$", "$1-$2-$3-$4-$5");
        return format;
    }

    public static String formatBalNo(String value) {
        String format = null;
        if (StringUtil2.isEmpty(value)) {
            return format;
        }
        format = value.replaceAll(" ", "");
        int formatLen = format.length();

        if (formatLen == 11) {
            format = value.replaceAll("^(\\S{1})(\\S{1})(\\S{6})(\\S{3})$", "$1-$2-$3-$4");
        } else if (formatLen == 14) {
            format = value.replaceAll("^(\\S{1})(\\S{1})(\\S{6})(\\S{3})(\\S{3})$", "$1-$2-$3-$4-$5");
        } else {

        }

        return format;
    }

    /**
     * 사업자등록번호
     *
     * @param value
     * @return
     */
    public static String formatBizNo(String value) {
        String format = null;
        if (StringUtil2.isEmpty(value)) {
            return format;
        }
        format = value.replaceAll("^(\\d{3})(\\d{2})(\\d{5})$", "$1-$2-$3");

        return format;
    }


    /**
     * 사업자등록번호
     *
     * @param value
     * @return
     */
    public static String formatBirthNo(String value) {
        String format = null;
        if (StringUtil2.isEmpty(value)) {
            return format;
        }
        format = value.replaceAll("^(\\d{2})(\\d{2})(\\d{2})(\\d{1})$", "$1.$2.$3.$4");

        return format;
    }


    /**
     * 법인번호
     *
     * @param value
     * @return
     */
    public static String formatBizIdNo(String value) {
        String format = null;
        if (StringUtil2.isEmpty(value)) {
            return format;
        }
        format = value.replaceAll("^(\\d{6})(\\d{7})$", "$1-$2");

        return format;
    }

    public static String formatAmount(String value, String pattern) {
        String format = null;
        if (StringUtil2.isNotEmpty(value)) {
            Double number = Double.parseDouble(value);
            DecimalFormat formatter = new DecimalFormat(pattern);
            format = formatter.format(number);
        }
        return format;
    }

    public static String formatAmount(Object value, String pattern) {
        return StringUtil2.formatAmount(String.valueOf(value), pattern);
    }

    public static String formatAmount(String value) {
        return StringUtil2.formatAmount(value, "#,###");
    }

    public static String formatAmount(Object value) {
        return StringUtil2.formatAmount(String.valueOf(value));
    }

    public static String formatFileSize(long fileSize) {
        if (fileSize <= 0) {
            return "0";
        }
        final String[] units = new String[] { "B", "kB", "MB", "GB", "TB" };
        int digitGroups = (int) (Math.log10(fileSize) / Math.log10(1024));
        return new DecimalFormat("#,##0.#").format(fileSize / Math.pow(1024, digitGroups)) + " " + units[digitGroups];
    }

    /**
     * 문자열을 Byte로 (한글 중간에 안 짤리게) 자름
     *
     * @param str
     * @param len
     * @param encoding
     * @return
     */
    public static String subByte(String str, int len, String encoding) {
        try {
            if (StringUtil2.isEmpty(str)) {
                return str;
            }
            byte[] strBytes = str.getBytes(encoding);
            int strLength = strBytes.length;
            int minusByteNum = 0;
            int offset = 0;
//            int hangulByteNum = encoding.equals(CoreConstant.CHARSET_UTF8) ? 3 : 2;
            int hangulByteNum = encoding.equals("UTF-8") ? 3 : 2;
            if (strLength > len) {
                minusByteNum = 0;
                offset = len;
                for (int j = 0; j < offset; j++) {
                    if ((strBytes[j] & 0x80) != 0) {
                        minusByteNum++;
                    }
                }
                if (minusByteNum % hangulByteNum != 0) {
                    offset -= minusByteNum % hangulByteNum;
                }
                return new String(strBytes, 0, offset, encoding);
            } else {
                return str;
            }
        } catch (Exception e) {
//            throw new BaseException(e);
        	return "";
        }
    }

    /**
     * 문자열을 Byte로 (한글 중간에 안 짤리게) 자름 - from-to
     *
     * @param str
     * @param len
     * @param encoding
     * @return
     */
    public static String subByte(String str, int from, int len, String encoding) {
    	try {
    		if (StringUtil2.isEmpty(str)) {
    			return str;
    		}
    		byte[] strBytes = str.getBytes(encoding);
    		int strLength = strBytes.length;
    		int minusByteNum = 0;
    		int offset = 0;
//    		int hangulByteNum = encoding.equals(CoreConstant.CHARSET_UTF8) ? 3 : 2;
    		int hangulByteNum = encoding.equals("UTF-8") ? 3 : 2;
    		if (strLength > len) {
    			minusByteNum = 0;
    			offset = len;
    			for (int j = 0; j < offset; j++) {
    				if ((strBytes[j] & 0x80) != 0) {
    					minusByteNum++;
    				}
    			}
    			if (minusByteNum % hangulByteNum != 0) {
    				offset -= minusByteNum % hangulByteNum;
    			}
    			return new String(strBytes, from, offset, encoding);
    		} else {
    			return str;
    		}
    	} catch (Exception e) {
//    		throw new BaseException(e);
    		return "";
    	}
    }

    /**
     * 문자열을 Byte로 (한글 중간에 안 짤리게) 자름 (UTF-8)
     *
     * @param str
     * @param len
     * @return
     */
    public static String subByte(String str, int len) {
//        return StringUtil2.subByte(str, len, CoreConstant.CHARSET_UTF8);
        return StringUtil2.subByte(str, len, "UTF-8");
    }

    /**
     * 문자열을 Byte로 (한글 중간에 안 짤리게) 자름 (EUC-KR)
     *
     * @param str
     * @param len
     * @return
     */
    public static String subByteEucKr(String str, int len) {
//        return StringUtil2.subByte(str, len, CoreConstant.CHARSET_EUCKR);
        return StringUtil2.subByte(str, len, "EUC-KR");
    }

    /**
     * 숫자만 추출.
     *
     * @param 추출문자
     * @return
     */
    public static String getOnlyNumber(String text) {
        Matcher m = Pattern.compile("[^0-9]").matcher(text);
        return m.replaceAll("");
    }

    /**
     * 비밀번호 유효성 체크
     *
     * @param 비밀번호
     * @return
     */
    public static String isEnablePassword(String passwd) {
        String returnValue = "";

        Pattern p = Pattern.compile("^(?=.*[A-Za-z])(?=.*\\d)(?=.*[$@$!%*#?&])[A-Za-z\\d$@$!%*#?&]{8,12}$");
        Matcher m = p.matcher(passwd);

        Pattern p2 = Pattern.compile("(\\w)\\1\\1");
        Matcher m2 = p2.matcher(passwd);

        if (!m.find()) { // 정규식 이용한 패턴 체크
            returnValue = "비밀번호는 영문,숫자,특수문자(!@$%^&* 만 허용)를\n조합하여 8~12자로 구성하세요.";
        } else if (m2.find()) { // 동일 문자 4번 입력 시 패턴 체크
            returnValue = "비밀번호에 동일문자를 3번 이상 사용할 수 없습니다.";
        } else if (continueNumberCheck(passwd)) { // 비밀번호 연속 숫자 4자리 체크
            returnValue = "비밀번호에 연속된 문자를 3자 이상 사용 할 수 없습니다.";
        }
        return returnValue;
    }

    /**
     * 연속된 숫자 체크
     *
     * @param numberCheck
     * @return
     */
    public static boolean continueNumberCheck(String numberCheck) {
        int o = 0;
        int d = 0;
        int p = 0;
        int n = 0;
        int limit = 3;

        for (int i = 0; i < numberCheck.length(); i++) {
            char tempVal = numberCheck.charAt(i);
            if (i > 0 && (p = o - tempVal) > -2 && p < 2 && (n = p == d ? n + 1 : 0) > limit - 3)
                return true;
            d = p;
            o = tempVal;
        }

        return false;
    }

    /**
     * 주어진 문자열에 대해 XML/HTML PCDATA에 적합한 이스케이프 문자 변환 처리를 수행한 결과 문자열을 반환한다. 변환되는 문자는 아래와 같다.
     *
     * <pre>
     *    & -> &amp;
     *    < -> &lt;
     *    > -> &gt;
     *    " -> &#034;
     *    ' -> &#039;
     * </pre>
     */
    public static String escapeXml(Object o) {
        if (o == null) {
            return null;
        }

        StringWriter writer = new StringWriter();
        try {
            writeXmlText(writer, o.toString(), true);
        } catch (java.io.IOException e) { // this exception cannot be catched.
        }

        return writer.toString();
    }

    public static void writeXmlText(Writer writer, String text) throws java.io.IOException {
        writeXmlText(writer, text, true, false, false);
    }

    public static void writeXmlText(Writer writer, String text, boolean escapeXml) throws java.io.IOException {
        writeXmlText(writer, text, escapeXml, false, false);
    }

    public static void writeXmlText(Writer writer, String text, boolean escapeXml, boolean applyBr) throws java.io.IOException {
        writeXmlText(writer, text, escapeXml, applyBr, false);
    }

    public static void writeXmlText(Writer writer, String text, boolean escapeXml, boolean applyBr, boolean escapeNbsp) throws java.io.IOException {
        if (text == null) {
            // do nothing.
        } else if (!escapeXml && !applyBr) {
            writer.write(text);
        } else {
            writeXmlText(writer, text.toCharArray(), text.length(), escapeXml, applyBr, escapeNbsp);
        }
    }

    public static void writeXmlText(Writer writer, char[] buffer, int length, boolean escapeXml, boolean applyBr, boolean escapeNbsp) throws java.io.IOException {
        int highest = HIGHEST_SPECIAL;
        int lowest = LOWEST_SPECIAL;
        int start = 0;
        int i = 0;
        char[][] representation = (escapeNbsp ? specialCharactersRepresentationWithNbsp : specialCharactersRepresentation);

        if (applyBr) {
            lowest = LOWEST_BR;
            if (!escapeXml) {
                highest = HIGHEST_BR;
            }
        } else {
            if (!escapeXml) {
                i = length;
            }
        }

        for (; i < length; i++) {
            char c = buffer[i];
            if (c <= highest && c >= lowest) {
                char[] escaped = representation[c];
                if (escaped != null) {
                    // add unescaped portion
                    if (start < i) {
                        writer.write(buffer, start, i - start);
                    }
                    // add escaped xml
                    writer.write(escaped);
                    start = i + 1;
                }
            }
        }
        // add rest of unescaped portion
        if (start < length) {
            writer.write(buffer, start, length - start);
        }
    }

    /**
     * 주어진 문자열이 빈 문자열("")인지 확인하여, 빈 문자열("")이 아니면 주어진 문자열을 그대로 반환하고, 빈 문자열("")이면 <tt>defaultValue</tt>를 반환한다.
     *
     * @param value
     * @param defaultValue
     * @return String
     */
    public static String nvl(String value, String defaultValue) {
        return coalesce(value, defaultValue);
    }

    /**
     * 주어진 문자열이 <tt>null</tt>인지 확인하여, <tt>null</tt>이 아니면 주어진 문자열을 그대로 반환하고, <tt>null</tt>이면 빈 문자열("")을 반환한다.
     *
     * @param value
     * @return String
     */
    public static String nvl(String value) {
        return coalesce(value, "");
    }

    private static String coalesce(String value, String defaultValue) {
        if (isEmpty(value)) {
            return defaultValue;
        }
        return value;
    }

    public static void test(List<String> listParam) {
    	listParam.add("bb");
    }
    
    public static String replaceBR(String str) {
    	return str.replaceAll("\r\n", "<br>");
    }


    public static void main(String args[]) throws Exception {
    	
    	String enpassword = EgovFileScrty.encryptPassword("1","cadmin1");

        System.out.print("암호화 비밀번호 : "+enpassword); // ?
    }
}
