package kcc.com.cmm.util;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;

public final class DateUtil {

	public static final String BASE_PATTERN = "yyyyMMddHHmmssSSS";
	public static final int BASE_PATTERN_LEN = BASE_PATTERN.length();
	private static final String[] PATTERN_CACHE = new String[BASE_PATTERN_LEN + 1];
	static {
		PATTERN_CACHE[BASE_PATTERN_LEN] = BASE_PATTERN;
		PATTERN_CACHE[14] = BASE_PATTERN.substring(0, 14);
		PATTERN_CACHE[12] = BASE_PATTERN.substring(0, 12);
		PATTERN_CACHE[10] = BASE_PATTERN.substring(0, 10);
		PATTERN_CACHE[8] = BASE_PATTERN.substring(0, 8);
		PATTERN_CACHE[6] = BASE_PATTERN.substring(0, 6);
		PATTERN_CACHE[4] = BASE_PATTERN.substring(0, 4);
		PATTERN_CACHE[0] = "";
	}
	public static final String DATE_PATTERN = PATTERN_CACHE[8];
	public static final String DATETIME_PATTERN = PATTERN_CACHE[14];


	public static LocalDateTime now() {
		return LocalDateTime.now();
	}


	public static Date toDate(LocalDate ld) {
		Date date = null;
		if(ld != null) {
			Instant instant = ld.atStartOfDay(ZoneId.systemDefault()).toInstant();
			date = Date.from(instant);
		}
		return date;
	}


	public static Date toDate(LocalDateTime ldt) {
		Date date = null;
		if(ldt != null) {
			Instant instant = ldt.atZone(ZoneId.systemDefault()).toInstant();
			date = Date.from(instant);
		}
		return date;
	}


	public static LocalDate toLocalDate(Date date) {
		LocalDate ld = null;
		if(date != null) {
			ld = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
		}
		return ld;
	}


	public static LocalDateTime toLocalDateTime(Date date) {
		LocalDateTime ldt = null;
		if(date != null) {
			ldt = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
		}
		return ldt;
	}


	public static Date parse(String source, String pattern) {
		Date date = null;
		if(source == null) {
			return date;
		}
		int sourceLen = source.length();
		if(sourceLen < 1) {
			return date;
		}
		if(sourceLen > 8) {
			LocalDateTime ldt = DateUtil.parseLocalDateTime(source, pattern);
			date = DateUtil.toDate(ldt);
		} else {
			LocalDate ld = DateUtil.parseLocalDate(source, pattern);
			date = DateUtil.toDate(ld);
		}
		return date;
	}


	public static Date parse(String source) {
		return DateUtil.parse(source, null);
	}


	public static LocalDate parseLocalDate(String source, String pattern) {
		LocalDate ld = null;
		if(source == null) {
			return ld;
		}
		int sourceLen = source.length();
		if(sourceLen < 1) {
			return ld;
		}
		if(StringUtil.isEmpty(pattern)) {
			pattern = PATTERN_CACHE[sourceLen];
			if(StringUtil.isEmpty(pattern)) {
				return ld;
			}
		}
		ld = LocalDate.parse(source, DateTimeFormatter.ofPattern(pattern));
		return ld;
	}


	public static LocalDate parseLocalDate(String source) {
		return DateUtil.parseLocalDate(source, null);
	}


	public static LocalDateTime parseLocalDateTime(String source, String pattern) {
		LocalDateTime ldt = null;
		if(source == null) {
			return ldt;
		}
		int sourceLen = source.length();
		if(sourceLen < 1) {
			return ldt;
		}
		if(StringUtil.isEmpty(pattern)) {
			pattern = PATTERN_CACHE[sourceLen];
			if(StringUtil.isEmpty(pattern)) {
				return ldt;
			}
		}
		ldt = LocalDateTime.parse(source, DateTimeFormatter.ofPattern(PATTERN_CACHE[sourceLen]));
		return ldt;
	}


	public static LocalDateTime parseLocalDateTime(String source) {
		return DateUtil.parseLocalDateTime(source, null);
	}

	public static String format(Date date, String pattern) {
		if (date == null)
			return null;

		return getInnerDateFormat(pattern).format(date);
	}

	private static SimpleDateFormat getInnerDateFormat(String pattern) {
		SimpleDateFormat f = cache.get(pattern);
		if (f == null)
			f = createDateformat(pattern);

		return f;
	}

	private static final Locale __DEFAULT_LOCALE = Locale.ENGLISH;

	private static HashMap<String, SimpleDateFormat> cache = new HashMap<String, SimpleDateFormat>();


	private synchronized static SimpleDateFormat createDateformat(String pattern) {
		SimpleDateFormat f = cache.get(pattern);
		if (f == null) {
			f = new SimpleDateFormat(pattern, __DEFAULT_LOCALE);
			cache.put(pattern, f);
		}
		return f;
	}
	
    //날짜 계산 더해주기
    /*
     * //year 년 전 cal.add(Calendar.YEAR, -year); 
     * //month 월 전 cal.add(Calendar.MONTH, -month); 
     * //month 일 전 cal.add(Calendar.DATE, -day);
     * 
     * */
    public static String AddDate(String strDate, int year, int month, int day) throws Exception { 
    	SimpleDateFormat dtFormat = new SimpleDateFormat("yyyy-MM-dd"); 
    	Calendar cal = Calendar.getInstance(); 
    	Date dt = dtFormat.parse(strDate); cal.setTime(dt); 
    	cal.add(Calendar.YEAR, year); 
    	cal.add(Calendar.MONTH, month); 
    	cal.add(Calendar.DATE, day); 
    	return dtFormat.format(cal.getTime()); 
    
    }
    
	public static String setDiffYear(String searchYear) {

		int yearChar = Integer.parseInt(searchYear);
		Calendar cal = Calendar.getInstance();
		cal.setTime(new Date());
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd");

		cal.add(Calendar.YEAR, -yearChar);
		
		return df.format(cal.getTime());
	}

	public static String setDiffMonth(String searchMonth) {
		
		int yearChar = Integer.parseInt(searchMonth);
		Calendar cal = Calendar.getInstance();
		cal.setTime(new Date());
		DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
		
		cal.add(Calendar.MONTH, -yearChar);
		
		return df.format(cal.getTime());
	}
	
	/** 
	 * @methodName	: setLastDayOfMonth 
	 * @author		: 이호영
	 * @date		: 2022.11.23 
	 * @description	: 해당 년 월의 마지막 날짜 구함
	 * @param year
	 * @param month
	 * @return 
	 */
	public static int setLastDayOfMonth(String year, String month) {

		Calendar cal = Calendar.getInstance();
		cal.set(Integer.parseInt(year), Integer.parseInt(month)-1, 1); 
		
		return cal.getActualMaximum(Calendar.DAY_OF_MONTH);
	}
	
}
