/*
 * Copyright 2008-2009 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package itn.com.cmm.util;

import java.io.IOException;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.sql.Clob;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

public class StringUtil {

    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 final static char[] byteCodes;

	static {
		byteCodes = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
	}
	
	/**
	 * 문자열 빈 값 여부 - null 포함 
	 * @param str
	 * @return true: 입력받은 String 이 빈 문자열 또는 null인 경우
	 */
	public static boolean isEmpty(String str) {
		return str == null || str.length() == 0;
	}
	

	public static String bytesToOrgString(byte[] bytes) {
		int len = bytes.length;
		char[] chars = new char[len * 2];

		for (int i = 0; i < len; ++i) {
			chars[i * 2] = byteCodes[(bytes[i] & 0XF0) >> 4];
			chars[i * 2 + 1] = byteCodes[(bytes[i] & 0X0F)];
		}
		return new String(chars);
	}

	/**
	 * 글자 특정 사이즈로 잘라내기
	 *
	 * @param str
	 * @param size
	 * @return String
	 */
	public String cutString(String str, int size) {
		String returnStr = null;
		if (str.length() > size) {
			returnStr = str.substring(0, size) + "...";
		}
		else {
			returnStr = str;
		}
		return returnStr;
	}

	/**
	 * 글자 특정 사이즈로 잘라내기
	 *
	 * @param str
	 * @param size
	 * @param tail
	 * @return String
	 */
	public String cutString(String str, int size, boolean tail) {
		String returnStr = null;
		String tails = "";

		if (tail == true) {
			tails = "...";
		}

		if (str.length() > size) {
			returnStr = str.substring(0, size) + tails;
		}
		else {
			returnStr = str;
		}
		return returnStr;
	}
	
	/**
	 * 글자 특정 사이즈로 <br/> 분이기
	 *
	 * @param str
	 * @param size
	 * @return String
	 */
	public String brString(String str, int size) {
		String returnStr = "";
		int j = 0;
		for(int i = 0; i < str.length(); i++)
		{
			if(j >= size)
			{
				returnStr += "<br/>";
				j = 0;
			}
			returnStr += str.charAt(i);
			j++;
		}
		return returnStr;
	}

	/**
	 * \r\n을 <br/> 태그로 변환처리
	 *
	 * @param str
	 * @return String
	 */
	public String nl2br(String str) {
		String returnStr = null;
		returnStr = str.replaceAll("\r\n", "<br/>");
		return returnStr;
	}
	
	/**
	 * \r\n을  삭제
	 *
	 * @param str
	 * @return String
	 */
	public String nl2Null(String str) {
		String returnStr = null;
		returnStr = str.replaceAll("\r\n", "");
		return returnStr;
	}
	
	/**
	 * \n을 <br/> 태그로 변환처리
	 *
	 * @param str
	 * @return String
	 */
	public String nl2br2(String str) {
		String returnStr = null;
		returnStr = str.replaceAll("\n", "<br/>");
		return returnStr;
	}
	
	/**
	 * 특수문자를 변환합니다
	 *
	 * @param str
	 * @return String
	 */
	public String middot(String str) {
		str = str.replaceAll("&middot;", "·");
		str = str.replaceAll("&ldquo;", "“");
		str = str.replaceAll("&rdquo;", "”");
		str = str.replaceAll("&rarr;", "→");

		return str;
	}	

	/**
	 * html 태그를 제거합니다
	 *
	 * @param str
	 * @return String
	 */
	public static String stripTag(String str) {
		str = str.replaceAll("\\<.*?\\>", "");
		str = str.replaceAll("&nbsp;", "");
		str = str.replaceAll("<span>","");

		return str;
	}
	
	/**
	 * clob 스트링 출력
	 *
	 * @param str
	 * @param size
	 * @return String
	 * @throws IOException 
	 */
	public String getClob(Clob str) throws IOException {
		try {
			
			Reader reader = str.getCharacterStream();
			
			StringBuffer out = new StringBuffer();  
		    char[] buff = new char[1024];  
		    int nchars = 0;  
		  
		    // 스트링 버퍼에 append 시킨후  
		    while ((nchars = reader.read(buff)) > 0) {  
		        out.append(buff, 0, nchars);  
		    }  
		  			
			return out.toString();
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			System.out.println("clob에러");
			return "clob에러";
		}
		
	}
	
	/**
	 * 글자 널값이면 대체하기
	 *
	 * @param str
	 * @param size
	 * @return String
	 */
	public String nvl(String str, String str_r) {
		String returnStr = str;
		if (str == null) {
			if (str_r == null) {
				str_r = "";
			}
			returnStr = str_r;
		} else if (str.length() == 0) {
			if (str_r == null) {
				str_r = "";
			}
			returnStr = str_r;
		}
		
		return returnStr;
	}
	
	/**
	 * https 검색
	 *
	 * @param str
	 * @param size
	 * @return String
	 */
	public boolean httpsFind(String str) {
		
		if(str.matches("https://.*"))
			return true;
		
		return false;
			
	}
	
	public boolean checkReg(String reg, String str) {
		return Pattern.matches(reg, str);
	}
	
	public static boolean checkRegKor(String str) {
		return Pattern.matches("[가-힣]+", str);
	}
	
	public boolean checkRegNum(String str) {
		return Pattern.matches("[0-9]+", str);
	}
	
	public boolean checkRegEng(String str) {
		return Pattern.matches("[a-zA-z]+", str);
	}
	public boolean checkRegEngUp(String str) {
		return Pattern.matches("[A-z]+", str);
	}
	public boolean checkRegEngLo(String str) {
		return Pattern.matches("[a-z]+", str);
	}
	
	public static boolean checkRegKorEngNum(String str) {
		return Pattern.matches("[가-힣A-za-z0-9]+", str);
	}
	
	/**
	 * 새 우편번호 변환
	 */
	public String getPost(int area, int num) {
		String[][] newPosts = {
				{""}
				,{"05050","11787","13636","26475","25517","07988","05048"}
				,{"14041","14442","10449","14067","16704","21313"}
				,{"46700","44248","51708","52628"}
				,{"32840","32840","28684","31158","32839"}
				,{"62278","55316","57987","58457"}
				,{"41504","36709","37653"}
		};
		return newPosts[area][num];
	}
	
	public String nl2br() {
		String returnStr = null;
		return returnStr;
	}
	
	/**
	 * 파라미터를 String 타입으로 가져옵니다.<br>
	 *  - null일 경우 빈 문자열을 가져옵니다.<br>
	 * Get String(if object is null, return empty string). 
	 * @param Object
	 * @return String
	 */
	public static String getString(Object obj) {
		if (obj == null)
			return "";
		else
			return String.valueOf(obj);
	}
	
	/**
	 * 오늘 날짜를 형식에 맞는 문자열로 가져옵니다.
	 * 
	 * @param format
	 * @return
	 */
	public static String getDateToString(String format) {
		Date date = new Date();
		return getDateToString(date, format);
	}
	
	/**
	 * 날짜 객체를 형식에 맞는 문자열로 가져옵니다.
	 * 
	 * @param date
	 * @param format
	 * @return
	 */
	public static String getDateToString(Date date, String format) {
		SimpleDateFormat sdf = new SimpleDateFormat(format);
		return sdf.format(date);
	}
	
	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 getOnlyNum(String value) {
        if(value == null) {
            return null;
        }
        return value.replaceAll("[^0-9]","");
    }

    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.
        	System.out.println("escapeXml IOException Error");
        }

        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);
        }
    }
    
	// 처음부터 idx 만큼 잘라낸 나머지 글자 
	public static String getWordLeft(String word, int idx) {
		String rtnVal = "";
		
		if (word.length() >= idx) {
			rtnVal = word.trim().substring(0, word.trim().length()-idx);
		}
		else {
			rtnVal = word.trim();
		}		
		
		return rtnVal;		
	}
    
	// idx 에서부터 끝까지 잘라낸 글자 => Ex) 함.
	public static String getWordRight(String word, int idx) {
		String rtnVal = "";
		
		if (word.length() >= idx) {
			rtnVal = word.trim().substring(word.trim().length()-idx, word.trim().length());
		}
		else {
			rtnVal = word.trim();
		}
		
		return rtnVal;		
	}
	
	//3개월전 첫째날 받아오기
	public static String getDate3MonthAgoFirstDay() {
		
		Calendar cal = Calendar.getInstance();
		
		int year = cal.get(Calendar.YEAR) - 1;
		int month = cal.get(Calendar.MONTH) + 1;
		
		cal.set(year,month,1);
		String firstDay = Integer.toString(cal.getActualMinimum(Calendar.DAY_OF_MONTH));
		
		String repMonth = "";
		String repfirstDay = "";
		if(month < 10) {
			repMonth = "0" + Integer.toString(month);
		}else {
			repMonth = Integer.toString(month);
		}
		
		if(Integer.parseInt(firstDay) < 10) {
			repfirstDay = "0" + firstDay;
		}else {
			repfirstDay = firstDay;
		}
		
		String ntceBgnde = Integer.toString(year) + "-" + repMonth + "-" + repfirstDay;
		
		return ntceBgnde;
	}
	
	//이번달의 첫째날과 마지막날짜 받아오기
	public static String getDateMonthFirstDay() {
		
		Calendar cal = Calendar.getInstance();
		
		int year = cal.get(Calendar.YEAR);
		int month = cal.get(Calendar.MONTH) + 1;
		
		cal.set(year,month,1);
		String firstDay = Integer.toString(cal.getActualMinimum(Calendar.DAY_OF_MONTH));
		
		String repMonth = "";
		String repfirstDay = "";
		if(month < 10) {
			repMonth = "0" + Integer.toString(month);
		}else {
			repMonth = Integer.toString(month);
		}
		
		if(Integer.parseInt(firstDay) < 10) {
			repfirstDay = "0" + firstDay;
		}else {
			repfirstDay = firstDay;
		}
		
		String ntceBgnde = Integer.toString(year) + "-" + repMonth + "-" + repfirstDay;
		
		return ntceBgnde;
	}
	
	//이번달의 첫째날과 마지막날짜 받아오기
	public static String getDateMonthLastDay() {
		
		Calendar cal = Calendar.getInstance();
		
		int year = cal.get(Calendar.YEAR);
		int month = cal.get(Calendar.MONTH);
		
		cal.set(year,month,1);
		String lastDay = Integer.toString(cal.getActualMaximum(Calendar.DAY_OF_MONTH));
		
		month = month + 1;
		String repMonth = "";
		if(month < 10) {
			repMonth = "0" + Integer.toString(month);
		}else {
			repMonth = Integer.toString(month);
		}
		
		String ntceEndde = Integer.toString(year) + "-" + repMonth + "-" + lastDay;
		
		return ntceEndde;
	}
	
	//1년후 이번달의 첫째날과 마지막날짜 받아오기
	public static String getDateMonthLastDay1YearAfter() {
		
		Calendar cal = Calendar.getInstance();
		
		int year = cal.get(Calendar.YEAR) + 1;
		int month = cal.get(Calendar.MONTH);
		
		cal.set(year,month,1);
		String lastDay = Integer.toString(cal.getActualMaximum(Calendar.DAY_OF_MONTH));
		
		month = month + 1;
		String repMonth = "";
		if(month < 10) {
			repMonth = "0" + Integer.toString(month);
		}else {
			repMonth = Integer.toString(month);
		}
		
		String ntceEndde = Integer.toString(year) + "-" + repMonth + "-" + lastDay;
		
		return ntceEndde;
	}
	
	/*
	 * 검색 키워드 내용에 한글, 영문, 숫자를 제외한 특수문자가 있는 경우 검색이 안되도록 처리
	 * 
	 * 
	 * */
	public static boolean getSearchKeywordValidation(String paramKeyword) {
		
		boolean resultType = false;
		String keyword = paramKeyword;
		
		keyword = keyword.replaceAll("[ㄱ-ㅎㅏ-ㅣ가-힣a-zA-Z0-9 ]", "");
		
		//검색어에 특수기호가 없어서 공백이 되는 경우만 true를 리턴한다.
		if(keyword.equals("")) {
		
			resultType = true;
		}
		
		return resultType;
		
	}
	
	
	public static String getLengthChkAndSubString(String str, int maxLength) {
		
		if (StringUtils.length(str) > maxLength) {
			str = StringUtils.substring(str, 0, maxLength);
		    // 잘라낸 문자열을 다시 설정 (필요한 경우)
		}
		return str;
		
	}
	
	
}