package com.tsi.sig.server.utils;

import jdk.nashorn.internal.runtime.ParserException;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.rmi.dgc.VMID;
import java.sql.Clob;
import java.sql.SQLException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Pattern;

/**
 * Project : TICS_REV File : com.common.util.CommonUtil.java Desc : 공통 유틸 기능 제공
 * 
 * @Company : LBCSOFT
 * @author : Administrator
 * @Date : 2013. 5. 9.
 */
@Slf4j
public class CommonUtil {

	//private static Logger logger = Logger.getLogger(CommonUtil.class);
	
	public static String trimAll(String str) {
		return str.replaceAll(" ", "");
	}
	
	public static String setUTF(String str) {
		String utf = null;
		
		if (str == null || str.equals("")) 
			utf = "";
		else
		{
			try {
				utf = new String(str.getBytes("8859_1"),"UTF-8");
			} catch (UnsupportedEncodingException e) {
				log.error("This Method Cause UnsupportedEncodingException : setUTF");
//				e.printStackTrace();
			}
		}
		
		//return str;
		return utf;
	}

	/**
	 * <PRE>
	 * 현재 날짜로부터 날짜 계산
	 * EX) getDate('yyyyMMdd',2,-3) ,  오늘 CommonUtil.getDate("yyyyMMddHHmmss", 1, 0);
	 * </PRE>
	 * 
	 * @param pat
	 *            날짜패턴 field 1 = 일(한달), 2 = 월, 3 = 년, 해당사하잉 없을 경우 날짜 계산 안함
	 *            amount 빼거나 더할 일자 또는 월 또는 년
	 * @return String 패턴으로 된 날짜
	 * @throws Exception
	 */
	public static String getDate(String pat, int field, int amount)
			throws Exception, NullPointerException {

		SimpleDateFormat dataFormat = new SimpleDateFormat(pat);
		String serverDate = null;
		Calendar cal = Calendar.getInstance();
		switch (field) {
		case 1:
			cal.add(Calendar.DAY_OF_MONTH, amount);
			break;
		case 2:
			cal.add(Calendar.MONTH, amount);
			break;
		case 3:
			cal.add(Calendar.YEAR, amount);
			break;
		}
		serverDate = dataFormat.format(cal.getTime());
		return serverDate;
	}

	/**
	 * 현재 시분초 구하기(HHMMSS)
	 * 
	 * @return
	 */
	public static String getTime() {
		Calendar cal = Calendar.getInstance();

		int hh = cal.get(Calendar.HOUR_OF_DAY);
		int mm = cal.get(Calendar.MINUTE);
		int ss = cal.get(Calendar.SECOND);

		String hhh = null;
		String mmm = null;
		String sss = null;

		if (hh < 10) {
			hhh = "0" + hh;
		} else {
			hhh = "" + hh;
		}

		if (mm < 10) {
			mmm = "0" + mm;
		} else {
			mmm = "" + mm;
		}

		if (ss < 10) {
			sss = "0" + ss;
		} else {
			sss = "" + ss;
		}

		return hhh + "" + mmm + "" + sss;
	}

	/**
	 * 문자열로 넘어온 날짜를 주어진 포멧으로 변한하여 리턴한다. formatDate("20100630",".") => 2010.06.30
	 * 
	 * @param date
	 * @param c
	 * @return
	 */
	public static String formatDate(String date, char c) {
		String newDate = null;

		date = date.trim();

		if (date == null || date.equals("")) {
			return "";
		}

		if (date.length() != 8) {
			return date;
		}

		newDate = date.substring(0, 4) + c + date.substring(4, 6) + c
				+ date.substring(6, 8);

		return newDate;
	}

	/**
	 * 문자열에 특정 값을 제거한 문자열을 리턴한다. remove("2010.06.30",".") => 20100630
	 * 
	 * @param str
	 * @param delim
	 * @return
	 */
	public static String remove(String str, String delim) {
		if (str == null) {
			str = "";
			return str;
		}

		StringBuffer sb = new StringBuffer();
		StringTokenizer st = new StringTokenizer(str, delim);

		while (st.hasMoreTokens()) {
			sb.append(st.nextToken());
		}

		return sb.toString();
	}

	/**
	 * 3번째 자리 수 마다 [,] 삽입 getCurrencyType("1000000") => 1,000,000
	 * 
	 * @param value
	 * @return
	 */
	public static String getCurrencyType(String value) {
		if (value != null) {
			if (value.length() > 3) {
				value = getCurrencyType(value.substring(0, value.length() - 3))
						+ "," + value.substring(value.length() - 3);
			}
		}
		return value;
	}

	/**
	 * NULL 체크하여 NULL일 경우 "" 값으로 리턴
	 * 
	 * @param str
	 * @return
	 */
	public static String checkNull(String str) {
		if (str == null || str == "undefined") {
			str = "";
		}
		return str;
	}

	/**
	 * NULL 체크하여 NULL일 경우 iValue 값으로 리턴
	 * 
	 * @param str
	 * @param sValue
	 * @return
	 */
	public static String checkNull(Object str, String sValue) {
		if (str == null || str.equals("")) {
			str = sValue;
		}
		return String.valueOf(str);
	}

	/**
	 * Desc : 배열일 넣어올때 NULL 체크하여 NULL일 경우 iValue 값으로 리턴
	 * 
	 * @Method name : checkNullArray
	 * @param
	 * @return String[]
	 * @throws
	 */

	public static String[] checkNullArray(String str[], String sValue) {
		for (int i = 0; i < str.length; i++) {
			if (str == null || str.equals("")) {
				str[i] = sValue;
			}
		}
		return str;
	}

	/**
	 * 제한된 글자수 많큼 자름.
	 * 
	 * @param str uploadPath 업로드 경로
	 * @return void
	 */
	public static String cutString(String str, int maxNum) {
		int tLen = str.length();
		int count = 0;
		char c;
		int s = 0;
		for (s = 0; s < tLen; s++) {
			c = str.charAt(s);
			if (count > maxNum)
				break;
			if (c > 127)
				count += 2;
			else
				count++;
		}
		return (tLen > s) ? str.substring(0, s) + "..." : str;
	}

	/**
	 * Temp 디렉토리 생성
	 * 
	 * @param dirPath
	 *            : 생성 경로
	 * @return
	 */
//
//	public static void makeTempDir(String dirPath) {
//
//		File dir = new File(dirPath);
//
//		if (!dir.isDirectory()) {
//			dir.mkdirs();
//		}
//	}

	/**
	 * Temp 디렉토리 삭제
	 * 
	 * @param dirPath
	 *            : 삭제 경로
	 * @return
	 */
	public static void delTempDir(String dirPath) {

		File file = new File(dirPath);
		String[] fnameList = file.list();
		int fCnt = fnameList.length;
		String childPath = "";

		for (int i = 0; i < fCnt; i++) {
			childPath = dirPath + "/" + fnameList[i];
			File f = new File(childPath);
			if (!f.isDirectory()) {
				f.delete(); // 파일이면 바로 삭제
			} else {
				delTempDir(childPath);
			}
		}

		File f = new File(dirPath);
		f.delete(); // 폴더는 맨 나중에 삭제
	}

	/**
	 * 현재 날짜
	 * 
	 * @param
	 * @return
	 */
	public String getDay() {
		String time = "";
		Calendar cal = Calendar.getInstance();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");

		time = sdf.format(cal.getTime());

		return time;
	}

	/**
	 * Desc : 날짜 더하기 빼기
	 * 
	 * @Method name : setDateFormat
	 * @param gc
	 * @param fm
	 * @return
	 */
	public static String setDateFormat(GregorianCalendar gc, String fm) {

		if (fm == null)
			return fm;

		SimpleDateFormat sdf = new SimpleDateFormat(fm);
		return sdf.format(gc.getTime());

	}

	/**
	 * Desc : 전환번호 형식 변환
	 * 
	 * @Method name : convPhonNumber
	 * @param text
	 * @return
	 */
	public String convPhonNumber(String text) {

		int textLength = text.length();

		String textOut = "";

		if (textLength >= 9) {

			int startIndex = 0;

			if ("02".equals(text.substring(0, 2))) {
				textOut += "02";
				startIndex += 2;
			} else {
				textOut += text.substring(0, 3);
				startIndex += 3;
			}

			textOut += "-" + text.substring(startIndex, textLength - 4);
			textOut += "-" + text.substring(textLength - 4, textLength);
		}

		return textOut;
	}

	/**
	 * Desc : 특수문자 제거 하기
	 * 
	 * @Method name : StringReplace
	 * @param str
	 * @return
	 */
	public String StringReplace(String str) {

		String match = "[^\uAC00-\uD7A3xfe0-9a-zA-Z\\s]";

		str = str.replaceAll(match, "");

		return str;
	}

	/**
	 * Desc : String null 체크
	 * 
	 * @Method name : checkStringNull
	 * @param str
	 * @return
	 */
	public static String checkStringNull(String str) {

		if ("null".equals(str)) {

			str = "";
		}

		return str;
	}

	/**
	 * http://levin01.tistory.com/372 유일 아이디 생성
	 * */
	public String getVMID() {
		VMID getUID = new VMID();
		String getStrUID = String.valueOf(getUID).toUpperCase();
		return getStrUID.replaceAll("-", "");
	}

	public static Boolean checkMapParamsNull(Map<String,Object> map) {

		Map<String, Object> parameters = map;
		Boolean result = true;

		for (String parameter : parameters.keySet()) {
			if (parameters.get(parameter) instanceof String[]) {
				String[] a = (String[]) parameters.get(parameter);
				if (a.length < 1) {
					result = false;
					break;
				}
			} else if (parameters.get(parameter) instanceof String) {
				if (parameters.get(parameter).toString().trim() == null
						|| parameters.get(parameter).toString().trim()
								.equals("")) {
					result = false;
					break;
				}
			} else if (parameters.get(parameter) == null) {
				result = false;
				break;
			} else
				;
		}
		return result;
	}

	/**
	 * Desc : 0-9일때 앞자리에 0을 붙여이기 ex) 9 -> 09
	 * 
	 * @Method name : checkDecimal
	 * @param
	 * @return String
	 * @throws
	 */

	public static String checkDecimal(String str) {
		if (str.length() == 1) {
			str = "0" + str;
		}
		return str;
	}
	
	public static boolean isNumber(String str){
		return Pattern.matches("^[0-9]*$", str);
	}
	
	public static boolean isEmail(String str){
		return Pattern.matches("^(?:\\w+\\.?)*\\w+@(?:\\w+\\.)+\\w+$", str);
	}
	
	/**
    * <pre>
    *  parameter값의 필수 여부 및 숫자타입 확인 메소드
    * </pre> 
    * */
	public static boolean paramsChk(Map<String,Object> paramMap, Map<String,Object> paramMapChk) throws Exception, ParserException {
	
		if(paramMapChk.isEmpty()) {
			return true;
		}
		
		Object key = null;
		Iterator<String> iterator = paramMapChk.keySet().iterator();

		boolean result = false;
		
		while (iterator.hasNext()) {
			key = iterator.next();		   
			
			if(paramMapChk != null 
			   && !paramMapChk.isEmpty() 
			   && paramMapChk.containsKey(key)
			   ){
				   //필수 요구 사항일 경우
				   if(paramMapChk.get(key).toString().contains("R")){
					   
					    if(paramMap.get(key) != null && paramMap.containsKey(key) && paramMap.get(key) instanceof String)
					    {
					    	if("".equals(CommonUtil.checkNull(paramMap.get(key).toString().trim(),""))){
					    		result = false;
					    		break;
					    	}else{
					    		result = true;
					    	}
					    	
					    }else{
					    	result = false;
					    	break;
					    }
				   }
				   
				   //숫자타입 확인
				   if(paramMapChk.get(key).toString().contains("N")){
					   if(paramMap.get(key) != null && paramMap.containsKey(key) && paramMap.get(key) instanceof String)
					    {
					    	if(!isStringDouble(paramMap.get(key).toString())){
					    		result = false;
					    		break;
					    	}else{
					    		result = true;
					    	}					    	
					    }else{
					    	result = false;
					    	break;
					    }
				   }   
				} 
			}	
	
		return result;
	}
	
	/**
	 * <pre>[스트링->더블] 타입 변환 체크</pre>
	 * */
   public static boolean isStringDouble(String s) {
	    try {
	        Double.parseDouble(s);
	        return true;
	    } catch (NumberFormatException e) {
	        return false;
	    }
	}
   
   
//   /**
//	 * Map형태의 객체에서 Value값 얻기
//	 * @param obj
//	 * @param key
//	 * @return
//	 */
	@SuppressWarnings("rawtypes")
//	public static Object getValue(Object obj
//			                     ,String key) {
//
//		// return할 객체
//		Object objj = null;
//
//		try {
//
//			// Map
//			if(obj instanceof Map) {
//
//				objj = ((Map)obj).get(key);
//			}
//
//			// HashMap
//			else if(obj instanceof HashMap) {
//
//				objj = ((HashMap)obj).get(key);
//			}
//
//			// 그 외
//			else {
//
//				objj = null;
//			}
//		}
//
//		catch(Exception ex) {
//
//			// 에러 발생시 null return
//			objj = null;
//		}
//
//		return objj;
//	}
//
	/**
	 * String 변환
	 * @param obj
	 * @param replacement
	 * @return
	 */
//	public static String parseString(Object obj
//			                        ,String replacement) {
//
//		// 변환해서 return할 값
//		String str = "";
//
//		try {
//
//			// Null이면 replacement로 교체
//			if(obj == null) {
//
//				str = replacement;
//			}
//
//			// Null이 아니면
//			else {
//
//				// String 변환
//				String strr = String.valueOf(obj);
//
//				// Null인지 체크
//				if(strr == null) {
//
//					str = replacement;
//				}
//
//				// Null이 아닌 경우
//				else {
//
//					// 공백제거
//					String val = strr.trim().toLowerCase();
//
//					// 공백이거나 null 텍스트인 경우 대체문자로 대체
//					if("".equals(val) || "null".equals(val)) {
//
//						str = replacement;
//					}
//
//					// 아닌 경우 String 변환객체 return
//					else {
//
//						str = strr;
//					}
//				}
//			}
//		}
//
//		catch(Exception ex) {
//
//			// 에러발생시 공백 return
//			str = replacement;
//		}
//
//		return str;
//	}
//
	
	/**
	 * convertNtXSS2 Convertor
	 * @param target
	 * @return
	 */
	public static String convertNtXSS2(String target) {

		// target문자열이 null이 아닌 경우 실행
		if(target != null) {
			// 공백제거
			target = target.trim();
			// 문자열 치환
			target = target.replaceAll("&lt;", "<");
			target = target.replaceAll("&gt;", ">");
			target = target.replaceAll("&quot;", "'");
			target = target.replaceAll("&#123;", "{");
			target = target.replaceAll("&#125;", "}");
			target = target.replaceAll("&#34;", "\"");
			target = target.replaceAll("&#39;", "'");
			target = target.replaceAll("&amp;", "&");
		}
		
		return target;
	}
	
	@SuppressWarnings("unchecked")
	public static Map<String, Object> paramToMap(HttpServletRequest request, Map<String, Object> paramMap) {
		
		Enumeration<String> e = request.getParameterNames();
		
		while (e.hasMoreElements()) {
			
			String name = e.nextElement();
			paramMap.put(name, checkNull(request.getParameter(name), ""));
		}
		return paramMap;
	}
//
//	public static void makeImg(String img, File filePath, String regionCd, String intNo) throws IOException {
//		BufferedImage image = null;
//		ByteArrayInputStream bis = null;
//		try {
//	        img = img.replaceAll("data:image/png;base64,", "").replaceAll(" ", "+");
//	        byte[] file = Base64.decodeBase64(img);
//	        bis = new ByteArrayInputStream(file);
//	        image = ImageIO.read(bis);
//
//			File intImage = new File(filePath,intNo+".png");
//	        ImageIO.write(image, "png", intImage);
//
//	    } catch(IOException e) {
//	        //logger.error("", e);
//	    	System.out.println("error : "+ e );
//	    	//bis.close();
//	    }
//		finally {
//			if (bis != null) {
//				bis.close();
//			}
//		}
//	}
	
	public static int byteArrayToInt(byte[] bytes) {
		final int size = Integer.SIZE / 8;
		ByteBuffer buff = ByteBuffer.allocate(size);
		final byte[] newBytes = new byte[size];
		for (int i = 0; i < size; i++) {
			if (i + bytes.length < size) {
				newBytes[i] = (byte) 0x00;
			} else {
				newBytes[i] = bytes[i + bytes.length - size];
			}
		}
		buff = ByteBuffer.wrap(newBytes);
		buff.order(ByteOrder.BIG_ENDIAN); // Endian에 맞게 세팅
		return buff.getInt();
	}
	
	/**
     * 바이너리 바이트 배열을 스트링으로 변환
     * 
     * @param b
     * @return
     */
    public static String byteArrayToBinaryString(byte[] b) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < b.length; ++i) {
            sb.append(byteToBinaryString(b[i]));
        }
        return sb.toString();
    }
 
    /**
     * 바이너리 바이트를 스트링으로 변환
     * 
     * @param n
     * @return
     */
    public static String byteToBinaryString(byte n) {
        StringBuilder sb = new StringBuilder("00000000");
        for (int bit = 0; bit < 8; bit++) {
            if (((n >> bit) & 1) > 0) {
                sb.setCharAt(7 - bit, '1');
            }
        }
        return sb.toString();
    }
 
    /**
     * 바이너리 스트링을 바이트배열로 변환
     * 
     * @param s
     * @return
     */
    public static byte[] binaryStringToByteArray(String s) {
        int count = s.length() / 8;
        byte[] b = new byte[count];
        for (int i = 1; i < count; ++i) {
            String t = s.substring((i - 1) * 8, i * 8);
            b[i - 1] = binaryStringToByte(t);
        }
        return b;
    }
 
    /**
     * 바이너리 스트링을 바이트로 변환
     * 
     * @param s
     * @return
     */
    public static byte binaryStringToByte(String s) {
        byte ret = 0, total = 0;
        for (int i = 0; i < 8; ++i) {
            ret = (s.charAt(7 - i) == '1') ? (byte) (1 << i) : 0;
            total = (byte) (ret | total);
        }
        return total;
    }
    
    public static void binarytoString (String letters) {
    	//java solution
    	String s = " ";
    	for(int index = 0; index < letters.length(); index+=9) {
    		String temp = letters.substring(index, index+8);
    		int num = Integer.parseInt(temp,2);
    		char letter = (char) num;
    		s = s+letter;
    	}
//    	System.out.print(s); //  Happy Easter!
    }
    
    public static String convertBinaryStringToString(String string){
        StringBuilder sb = new StringBuilder();
        char[] chars = string.toCharArray();

        //for each character
        for (int j = 0; j < chars.length; j+=9) {
            int idx = 0;
            int sum = 0;
            //for each bit in reverse
            for (int i = 7; i>= 0; i--) {
                if (chars[i+j] == '1') {
                    sum += 1 << idx;
                }
                idx++;
            }
//            System.out.println(sum);//debug
            sb.append(Character.toChars(sum));
        }
        return sb.toString();
    }
    
    public static int BE_convertBytes2Int(byte[] buffer, int startPos) {
    	/* old way
               int retval =  (int)(buffer[startPos]<<24)+
                             (int)((buffer[startPos+1]<<24)>>>8)+
                             (int)((buffer[startPos+2]<<24)>>>16)+
                             (int)((buffer[startPos+3]<<24)>>>24) ;
    	*/
    	/*
    	System.err.println("startPos " + startPos);
    	System.err.println(buffer[startPos]);
    	System.err.println(buffer[startPos + 1]);
    	System.err.println(buffer[startPos + 2]);
    	System.err.println(buffer[startPos + 3]);
    	*/
    	int retval = 
    	    ((buffer[startPos] << 24) & 0xff000000) |
    	    ((buffer[startPos + 1] << 16) & 0xff0000) |
    	    ((buffer[startPos + 2] << 8) & 0xff00) |
    	    (buffer[startPos + 3] & 0xff);
    	return retval;
    }
    
    public static String LE_makeIPAddr(byte buf[], int pos) {
    	//ip addr 4 bytes
    	Byte holder;
    	String seg[] = new String[4];
    	String retval;
    	for (int i = 3; i >= 0; i--) {
    	    //holder = new Byte(buf[pos +i]);
    	    //seg[i] = Integer.toString(holder.intValue());
    	    holder = new Byte((byte)(buf[pos + i] & 0377));
    	    int tmp = holder.intValue();
    	    if (tmp < 0) { 
    		//due to signess in java, a byte value is also signed.
    		//hence this trash.
    		tmp = 127 + (128 + tmp) + 1;
    	    }
    	    seg[i] = Integer.toString(tmp);
    	    
    	}
    	retval = seg[3] + "." + seg[2] + "." +
    	         seg[1] + "." + seg[0];

    	return retval;
    }
    
    public static final byte[] getbytes(byte src[], int offset, int length) {
        byte dest[] = new byte[length];
        System.arraycopy(src, offset, dest, 0, length);
        return dest;
    }
    
    public static String byteArrayToHex(byte a) {
        StringBuilder sb = new StringBuilder();
        //for(final byte b: a)
            sb.append(String.format("%02x ", a&0xff));
        return sb.toString();
    }
    
    public static String clobToString(Clob clob) throws SQLException, IOException {
		
		  if (clob == null) {
			  return "";
		  }
	
		  StringBuffer strOut = new StringBuffer();
	
		  String str = "";
		  BufferedReader br = null;
		  try {

			  br = new BufferedReader(clob.getCharacterStream());

			  while ((str = br.readLine()) != null) {
				  strOut.append(str);
			  }
		  }
		  catch (IOException e) {
			  log.error("Cause IOException");
		  }
		  finally {
			  if (br != null) {
				  br.close();
			  }
		  }


		  return strOut.toString();
	 }

}
