package com.takensoft.pohangTp.common.util;



import java.io.UnsupportedEncodingException;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.Random;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * @author 최정우
 * @since 2019.11.13
 * 
 * 문자열과 관련된 기능을 정의 해놓은 Util입니다.
 */
public class StringUtil {

	private static final Logger LOGGER = LoggerFactory.getLogger(StringUtil.class);
	
	public static final String NULL_TEXT = "NULL";
	
	public static String toString(Object obj) {
		if (obj == null) {
			return null;
		} else {
			try {
				return obj.toString();
			} catch (Exception e) {
				return null;
			}
		}
	}
	
	public static String toStringNotNull(Object obj) {
		if (obj == null) {
			return "";
		} else {
			try {
				return obj.toString();
			} catch (Exception e) {
				return "";
			}
		}
	}
	
	/**
     * @author 최정우
     * @since 2020.11.26
     * 
     * 객체를 문자열로 바꾼 후, 문자열 길이 반환
     */
	public static int stringLength(Object obj) {
		if (obj == null) {
			return 0;
		} else {
			try {
				return obj.toString().length();
			} catch (Exception e) {
				return 0;
			}
		}
	}
	
	/**
     * @author 최정우
     * @since 2020.11.26
     * 
     * 문자열이 Null or null or NULL인 경우 실제 null값 세팅 
     */
	public static boolean isNullText(String text) {
		if (isEmpty(text) == false && text.toUpperCase().equals(NULL_TEXT)) {
			return true;
		} else {
			return false;
		}
	}
	
    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * 빈 문자열 검사
     */
    public static boolean isEmpty(String text) {
        return text == null || text.trim().length() == 0;
    }
    
    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * indexOf - 문자 검색 후, 해당 문자의 위치(index)반환
     */
    public static int indexOf(String text, String searchText) {
        if (text == null || searchText == null) {
            return -1;
        }
        return text.indexOf(searchText);
    }
    
    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * lastIndexOf - 문자 검색 후, 해당 문자의 위치(index)반환
     */
    public static int lastIndexOf(String text, String searchText) {
    	if (text == null || searchText == null) {
            return -1;
        }
        return text.lastIndexOf(searchText);
    }
    
    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * substringBetween - 특정 문자열 사이에 값을 뽑아내는 메서드
     */
    public static String substringBetween(String text, String startText, String endText) {
		if (isEmpty(text) == true || isEmpty(startText) == true || isEmpty(endText) == true) {
			return null;
		}
		text = text.toLowerCase();
		startText = startText.toLowerCase();
		endText = endText.toLowerCase();
		
		int start = text.indexOf(startText);
		if (start != -1) {
			int end = text.indexOf(endText, start + startText.length());
			if (end != -1) {
				return text.substring(start + startText.length(), end);
			}
		}
		return null;
	}

    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * 모든 공백 제거
     */
    public static String removeSpace(String text) {
        if (isEmpty(text)) {
            return text;
        }
        int length = text.length();
        char[] newCharList = new char[length];
        int count = 0;
        for (int i = 0; i < length; i++) {
            if (Character.isWhitespace(text.charAt(i)) == false) {
            	newCharList[count++] = text.charAt(i);
            }
        }
        if (count == length) {
            return text;
        }

        return new String(newCharList, 0, count);
    }
    
	 

    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * 소문자 변환
     */
    public static String lowerCase(String text) {
        if (isEmpty(text) == true) {
            return text;
        } else {
        	return text.toLowerCase();
        }
    }

    /**
     * 대문자 변환
     */
    public static String upperCase(String text) {
    	if (isEmpty(text) == true) {
            return text;
        } else {
        	return text.toUpperCase();
        }
    }

    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * 현재날짜(년,월,일)를 구하는 기능
     */
    public static String getToday() {
		String pattern = "yyyy-MM-dd";
		SimpleDateFormat dateFormat = new SimpleDateFormat(pattern, Locale.KOREA);
		Timestamp timestamp = new Timestamp(System.currentTimeMillis());
		return dateFormat.format(timestamp.getTime());
    }
    
    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * 현재날짜(년,월,일)를 구하는 기능
     */
    public static String getToday(String pattern) {
    	String defaultPattern = "yyyy-MM-dd";
    	if (isEmpty(pattern) == true) {
    		pattern = defaultPattern;
    	}
    	
    	SimpleDateFormat dateFormat = null;
		try {
			dateFormat = new SimpleDateFormat(pattern, Locale.KOREA);
		} catch (Exception e) {
			dateFormat = new SimpleDateFormat(defaultPattern, Locale.KOREA);
		}
		Timestamp timestamp = new Timestamp(System.currentTimeMillis());		
		return dateFormat.format(timestamp.getTime());
    }
    
    
    /**
     * @author 김성원
     * @since 2019.11.13
     * 
     * 현재날짜(년,월,일)에 특정 날짜 + -
     */
    public static String getTodayaddDate(String pattern, String type,  int date) {
    	String defaultPattern = "yyyy-MM-dd";
    	if (isEmpty(pattern) == true) {
    		pattern = defaultPattern;
    	}
    	
    	SimpleDateFormat dateFormat = null;
		try {
			dateFormat = new SimpleDateFormat(pattern, Locale.KOREA);
		} catch (Exception e) {
			dateFormat = new SimpleDateFormat(defaultPattern, Locale.KOREA);
		}
		
		Timestamp timestamp = new Timestamp(System.currentTimeMillis());		
		Calendar cal = Calendar.getInstance();
		if(type.equals("year")) {
			cal.add(Calendar.YEAR, date);
		}else if(type.equals("month")) {
			cal.add(Calendar.MONTH, date);
		}else if(type.equals("day")) {
			cal.add(Calendar.DATE, date);
		}		
		
		return dateFormat.format(cal.getTime());
    }
    
    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * 현재날짜(년,월,일)를 구하는 기능
     */
    public static String getToday(String yearSuffix, String monthSuffix, String daySuffix) {
    	String defaultPattern = "yyyy년MM월dd일";
    	if (isEmpty(yearSuffix) == true) {
    		yearSuffix = "";
    	}
    	if (isEmpty(monthSuffix) == true) {
    		monthSuffix = "";
    	}
    	if (isEmpty(daySuffix) == true) {
    		daySuffix = "";
    	}
    	
    	String pattern = "yyyy" + yearSuffix + "MM" + monthSuffix + "dd" + daySuffix;
    	
    	SimpleDateFormat dateFormat = null;
		try {
			dateFormat = new SimpleDateFormat(pattern, Locale.KOREA);
		} catch (Exception e) {
			dateFormat = new SimpleDateFormat(defaultPattern, Locale.KOREA);
		}
		Timestamp timestamp = new Timestamp(System.currentTimeMillis());
		return dateFormat.format(timestamp.getTime());
    }
    
    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * 17자리의 현재일시를 구하는 기능
     */
    public static String getDateTime() {
		// 문자열로 변환하기 위한 패턴 설정(년도-월-일 시:분:초:초(자정이후 초))
		String pattern = "yyyyMMddHHmmssSSS";
		SimpleDateFormat dateFormat = new SimpleDateFormat(pattern, Locale.KOREA);
		Timestamp timestamp = new Timestamp(System.currentTimeMillis());
		return dateFormat.format(timestamp.getTime());
    }
    
    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * 원하는 패턴의 현재일시 구하는 기능
     */
    public static String getDateTime(String pattern) {
    	// 문자열로 변환하기 위한 패턴 설정(년도-월-일 시:분:초:초(자정이후 초))
    	String defaultPattern = "yyyyMMddHHmmssSSS";
    	if (isEmpty(pattern)) {
    		pattern = defaultPattern;
    	}
		SimpleDateFormat dateFormat = null;
		try {
			dateFormat = new SimpleDateFormat(pattern, Locale.KOREA);
		} catch (Exception e) {
			dateFormat = new SimpleDateFormat(defaultPattern, Locale.KOREA);
		}
		Timestamp timestamp = new Timestamp(System.currentTimeMillis());
		return dateFormat.format(timestamp.getTime());
    }
    
    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * 현재 일시 - addDay => 원하는 패턴의 일시를 구하는 기능 
     */
    public static String getDateTime(String pattern, int addDay) {
    	// 문자열로 변환하기 위한 패턴 설정(년도-월-일 시:분:초:초(자정이후 초))
    	String defaultPattern = "yyyyMMddHHmmssSSS";	
    	if (pattern == null) {
    		pattern = defaultPattern;
    	}
		SimpleDateFormat dateFormat = null;
		try {
			dateFormat = new SimpleDateFormat(pattern, Locale.KOREA);
		} catch (Exception e) {
			dateFormat = new SimpleDateFormat(defaultPattern, Locale.KOREA);
		}
		Calendar cal = new GregorianCalendar();
		cal.add(Calendar.DATE, addDay);
		Date date = cal.getTime();
		return dateFormat.format(date.getTime());
    }
    
    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * 현재 일시 - addDay => 원하는 패턴의 일시를 구하는 기능 
     */
    public static String getDateTime(String pattern, int addDay, int addHour, int addMin, int addSec) {
    	// 문자열로 변환하기 위한 패턴 설정(년도-월-일 시:분:초:초(자정이후 초))
    	String defaultPattern = "yyyyMMddHHmmssSSS";	
    	if (pattern == null) {
    		pattern = defaultPattern;
    	}
		SimpleDateFormat dateFormat = null;
		try {
			dateFormat = new SimpleDateFormat(pattern, Locale.KOREA);
		} catch (Exception e) {
			dateFormat = new SimpleDateFormat(defaultPattern, Locale.KOREA);
		}
		Calendar cal = new GregorianCalendar();
		cal.add(Calendar.DATE, addDay);
		cal.add(Calendar.HOUR, addHour);
		cal.add(Calendar.MINUTE, addMin);
		cal.add(Calendar.SECOND, addSec);
		Date date = cal.getTime();
		return dateFormat.format(date.getTime());
    }
    
    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * 현재 일시(17자리)와, 랜덤숫자(4자리)를 이용하여 키값 생성
     */
    public static String getCreateKey (String prefix) {
		int random = new Random().nextInt(9999);
		String result = prefix + "_" + getDateTime() + "_" + numberToText(random, 4);
		return result;
    }
    
    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * 문자열이 Date문자열(yyyy-MM-dd)로 포맷 가능한지
     * text: 문자열
     * pattern: 문자열의 날짜 패턴
     */
    public static boolean isDate(String text, String pattern) {
    	try {
    		Date date = new SimpleDateFormat(pattern).parse(text);
    		text = new SimpleDateFormat("yyyy-MM-dd").format(date);
        	return true;
    	} catch (java.text.ParseException e) {
			// TODO Auto-generated catch block
			return false;
		}
    }
    
    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * 문자열을 날짜형태로 Convert
     * text: 문자열
     * pattern: 문자열의 날짜 패턴
     * newPattern: 해당 문자열을 Converting할 날짜 패턴 
     */
    public static String textToDateText (String text, String pattern, String newPattern) {
		String defaultPattern = "yyyy-MM-dd";
		if (isEmpty(newPattern) == true) {
			newPattern = defaultPattern;
    	}
		
		SimpleDateFormat dateFormat = new SimpleDateFormat(pattern);
		Date date = new Date();
		try {
			date = dateFormat.parse(text);
			dateFormat.applyPattern(newPattern);
			return dateFormat.format(date);
        } catch (Exception e) {
            //e.printStackTrace();
            return text;
        }
	}
    
    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * 숫자 -> 문자열 -> 문자열 길이가 length보다 작을 때, length길이 만큼될 수 있도록 앞에 '0'을 붙여줌
     */
    public static String numberToText (int number, int length) {
    	String text = Integer.toString(number);
    	if (text.length() < length) {
            int emptyLength = length - text.length();
            for (int i = 0; i < emptyLength; i++) {
            	text = "0" + text;
            }
        }
        return text;
    }

    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * 문자열이 지정한 길이를 초과했을때 해당 문자열을 삭제하는 메서드
     * @param text 원본 문자열 배열
     * @param maxLength 지정길이
     * @return 지정길이로 자른 문자열
     */
    public static String cutString(String text, int maxLength) {
        String result = null;
        if (text != null) {
            if (text.length() > maxLength) {
                result = text.substring(0, maxLength);
            } else
                result = text;
        }
        return result;
    }
	

    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * 문자열이 지정한 길이를 초과했을때 지정한길이에다가 해당 문자열을 붙여주는 메서드.
     * @param text 원본 문자열 배열
     * @param addText 더할문자열
     * @param maxLength 지정길이
     * @return 지정길이로 잘라서 더할분자열 합친 문자열
     */
    public static String cutString(String text, String addText, int maxLength) {
        String result = null;
        if (text != null) {
            if (text.length() > maxLength) {
            	result = text.substring(0, maxLength) + addText;
            } else
            	result = text;
        }
        return result;
    }

    
    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * <p>기준 문자열에 포함된 모든 대상 문자(char)를 제거한다.</p>
     *
     * <pre>
     * StringUtil.remove(null, *)       = null
     * StringUtil.remove("", *)         = ""
     * StringUtil.remove("queued", 'u') = "qeed"
     * StringUtil.remove("queued", 'z') = "queued"
     * </pre>
     *
     * @param str  입력받는 기준 문자열
     * @param remove  입력받는 문자열에서 제거할 대상 문자열
     * @return 제거대상 문자열이 제거된 입력문자열. 입력문자열이 null인 경우 출력문자열은 null
     */
    public static String remove(String text, char remove) {
        if (isEmpty(text) || text.indexOf(remove) == -1) {
            return text;
        }
        char[] chars = text.toCharArray();
        int pos = 0;
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] != remove) {
                chars[pos++] = chars[i];
            }
        }
        
        return new String(chars, 0, pos);
    }


    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * 원본 문자열의 포함된 특정 문자열을 새로운 문자열로 변환하는 메서드
     * @param source 원본 문자열
     * @param subject 원본 문자열에 포함된 특정 문자열
     * @param object 변환할 문자열
     * @return sb.toString() 새로운 문자열로 변환된 문자열
     */
    public static String replace(String text, String subject, String object) {
        StringBuffer rtnStr = new StringBuffer();
        String preStr = "";
        String nextStr = text;
        String srcStr  = text;

        while (srcStr.indexOf(subject) >= 0) {
            preStr = srcStr.substring(0, srcStr.indexOf(subject));
            nextStr = srcStr.substring(srcStr.indexOf(subject) + subject.length(), srcStr.length());
            srcStr = nextStr;
            rtnStr.append(preStr).append(object);
        }
        rtnStr.append(nextStr);
        return rtnStr.toString();
    }

    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * 원본 문자열의 포함된 특정 문자열 첫번째 한개만 새로운 문자열로 변환하는 메서드
     * @param source 원본 문자열
     * @param subject 원본 문자열에 포함된 특정 문자열
     * @param object 변환할 문자열
     * @return sb.toString() 새로운 문자열로 변환된 문자열 / source 특정문자열이 없는 경우 원본 문자열
     */
    public static String replaceOnce(String source, String subject, String object) {
        StringBuffer rtnStr = new StringBuffer();
        String preStr = "";
        String nextStr = source;
        if (source.indexOf(subject) >= 0) {
            preStr = source.substring(0, source.indexOf(subject));
            nextStr = source.substring(source.indexOf(subject) + subject.length(), source.length());
            rtnStr.append(preStr).append(object).append(nextStr);
            return rtnStr.toString();
        } else {
            return source;
        }
    }

    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * <code>subject</code>에 포함된 각각의 문자를 object로 변환한다.
     *
     * @param source 원본 문자열
     * @param subject 원본 문자열에 포함된 특정 문자열
     * @param object 변환할 문자열
     * @return sb.toString() 새로운 문자열로 변환된 문자열
     */
    public static String replaceChar(String source, String subject, String object) {
        StringBuffer rtnStr = new StringBuffer();
        String preStr = "";
        String nextStr = source;
        String srcStr  = source;

        char chA;

        for (int i = 0; i < subject.length(); i++) {
            chA = subject.charAt(i);

            if (srcStr.indexOf(chA) >= 0) {
                preStr = srcStr.substring(0, srcStr.indexOf(chA));
                nextStr = srcStr.substring(srcStr.indexOf(chA) + 1, srcStr.length());
                srcStr = rtnStr.append(preStr).append(object).append(nextStr).toString();
            }
        }

        return srcStr;
    }

    /**
     * @author 최정우
     * @since 2019.11.13
     * 
     * 문자열을 다양한 문자셋(EUC-KR[KSC5601],UTF-8..)을 사용하여 인코딩하는 기능 역으로 디코딩하여 원래의 문자열을
     * 복원하는 기능을 제공함 String temp = new String(문자열.getBytes("바꾸기전 인코딩"),"바꿀 인코딩");
     * String temp = new String(문자열.getBytes("8859_1"),"KSC5601"); => UTF-8 에서
     * EUC-KR
     *
     * @param text - 문자열
     * @param encoding - 원래의 인코딩된 값
     * @param decoding - 디코딩할 문자값
     * @return 인(디)코딩 문자열
     * @exception MyException
     * @see
     */
    public static String textDecoding(String text, String encoding, String decoding) {
		if (text == null) {
			return null;
		}
	
		try {
			text = new String(text.getBytes(encoding), decoding);
		} catch (UnsupportedEncodingException e) {
			text = null;
		}
	
		return text;
    }
    
    
    /**
     * @author 최정우
     * @since 2020.11.26
     * 
     * 문자열 특정 포맷팅으로 변환 ##-####
     */
    public static String formatConvert(String data, String format) {
		
    	StringBuilder bf = new StringBuilder();
		
    	if(StringUtil.isEmpty(format) || StringUtil.isEmpty(data)) {
    		bf.append(data);
    	}else {
    		int num =  data.length()-1;    		
    		for(int i = format.length()-1 ; i >= 0 ; i--) {
    			if(format.charAt(i) == '#') {
    				bf.insert(0, data.charAt(num--));
    			}else {
    				bf.insert(0,format.charAt(i));
    			}
    		}
    	}
		
		return bf.toString();
	}
    
    /**
     * @author 김성원
     * @since 2022.07.06
     * 
     * 날짜형식 문자열  특정 포맷팅으로 변환 ##-####
     */
    public static String dateConvert(String date) {
    	
    	StringBuilder bf = new StringBuilder();
    	
    	boolean dateForm = true;
    	
    	if(!date.contains("-") && date.length() > 4) {
    		dateForm = false;
    	}
    	
    	if(!StringUtil.isEmpty(date)) {
    	
    		String dateStr =  date.replaceAll("[^0-9]", "");
    		// 년도 처리 
    		if(dateStr.length() < 5) {
    			bf.append(date.substring(0,4));
    		}else {
    			if(dateForm == true) {
    				bf.append(StringUtil.formatConvert(dateStr.substring(0,6),"####-##"));
    			}else {
    				bf.append(StringUtil.formatConvert(dateStr.substring(0,6),"####-##"));
    				//bf.append(dateStr.substring(0,4));
    				//bf.append("년 ");
    			}
    		}
    	}    
		
		return bf.toString();
	}
    
    
	
}
