package sgc.portal.base.util;

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

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;

/**
 * <pre>
 * 프로그램ID : DateUtil
 * 프로그램명  : Date Util
 * </pre>
 *
 * @author 이범근
 * @version 2019.11.18
 * @since JDK1.8
 */
public class DateUtil {

    private final static Logger logger = LoggerFactory.getLogger(DateUtil.class);

    /**
     * getStringToDate (스트링형태의 데이터를 입력받아 데이트형태의 데이터로 변환)
     *
     * @param paramDate the param date
     * @return String string to date
     */
    public static Date getStringToDate(String paramDate) {
        SimpleDateFormat transFormat = new SimpleDateFormat("yyyyMMddHHmmss", Locale.KOREA);
        Date date = null;
        try {
            paramDate = StringUtil.rpad(paramDate, 14, "0");
            date = transFormat.parse(paramDate);
        } catch (ParseException e) {
            StackTraceElement[] el =  e.getStackTrace();
            for(StackTraceElement se : el) {
                logger.debug(se.toString());
            }
        }

        return date;
    }

    /**
     * getDateToString (데이터 형태의 데이터를 입력받아 스트링형태의 데이터로 변환)
     *
     * @param paramDate the param date
     * @param dateFmt   the date fmt
     * @return string
     */
    public static String getDateToString(Date paramDate, String dateFmt){
        String dateFormat = "yyyy.MM.dd HH:mm:ss";

        if(dateFmt != null && !dateFmt.isEmpty() ){
            dateFormat = dateFmt;
        }

        SimpleDateFormat transFormat = new SimpleDateFormat(dateFormat);
        String date;
        date = transFormat.format(paramDate);

        return date;
    }

    /**
     * getCurrentDate (오늘날짜정보를 dateFmt에 맞게 가져오기)
     *
     * @param dateFmt ("yyyy-MM-dd HH:mm:ss.S")
     * @return string
     */
    public static String getCurrentDate(String dateFmt){
        String dateFormat = "yyyyMMdd";

        if(dateFmt != null && !dateFmt.isEmpty() ){
            dateFormat = dateFmt;
        }

        Date dt			=	new Date();
        SimpleDateFormat sformat	=	new SimpleDateFormat(dateFormat);



        return sformat.format(dt);
    }

    /**
     * getCurrentDate (오늘날짜정보를 기본 포멧에 맞게 가져오기)
     *
     * @return string
     */
    public static String getCurrentDateStr(){
        String dateFormat = "yyyyMMdd";

        Date dt         =   new Date();
        SimpleDateFormat sformat    =   new SimpleDateFormat(dateFormat);

        return sformat.format(dt);
    }

    /**
     * toDateFormat (전달받은 문자열을 날짜형식으로 변환)
     *
     * @param strDt   the str dt
     * @param dateFmt the date fmt
     * @return string
     */
    public static String toDateFormat(String strDt, String dateFmt){
        String dateFormat = "yyyy.MM.dd HH:mm:ss";

        if(dateFmt != null && !dateFmt.isEmpty() ){
            dateFormat = dateFmt;
        }

        Date dt         =   getStringToDate(strDt);

        SimpleDateFormat sformat	=	new SimpleDateFormat(dateFormat);

        return sformat.format(dt);
    }

    /**
     * formatWeekDayHg (해당 요일 반환)
     *
     * @param fromstr (" 20200101" )
     * @return string
     */
    public static String formatWeekDayHg(String fromstr) {
        String rtnstr;

        SimpleDateFormat sdf = new SimpleDateFormat("E");
        java.util.Calendar c = Calendar.getInstance();

        int cyear, cmonth, cdate;

        if (!fromstr.equals("")) {
            c = new GregorianCalendar(Integer.parseInt(fromstr.substring(0, 4)), Integer.parseInt(fromstr.substring(4, 6)) - 1, Integer.parseInt(fromstr.substring(6)) );
        }

        cyear  = c.get(Calendar.YEAR);
        cmonth = c.get(Calendar.MONTH) + 1;
        cdate  = c.get(Calendar.DATE);

        rtnstr = sdf.format(new java.util.Date(cyear - 1900, cmonth - 1, cdate));

        return rtnstr;
    }

    /**
     * addDate (해당 요일 반환)(전달받은 날짜에(date) 날짜/월/년 을(addDvn) 더하여(term) 특정 날짜  반환)
     *
     * @param fromstr the fromstr
     * @param ymd     the ymd
     * @param term    the term
     * @return string
     */
    public static String addDate(String fromstr, String ymd, int term) {

        String rtnstr;

        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd", Locale.KOREA);
        java.util.Calendar c = Calendar.getInstance();
        int cyear, cmonth, cdate;

        ymd = ymd.toLowerCase();

        if (!fromstr.equals("")) {
            c = new GregorianCalendar(Integer.parseInt(fromstr.substring(0, 4)), Integer.parseInt(fromstr.substring(4, 6)) - 1, Integer.parseInt(fromstr.substring(6)) );
        }

        switch (ymd) {
            case "y":
                c.add(Calendar.YEAR, term);
                break;
            case "m":
                c.add(Calendar.MONTH, term);
                break;
            case "d":
                c.add(Calendar.DATE, term);
                break;
            default:
                break;
        }

        cyear  = c.get(Calendar.YEAR);
        cmonth = c.get(Calendar.MONTH) + 1;
        cdate  = c.get(Calendar.DATE);

        rtnstr = sdf.format(new java.util.Date(cyear - 1900, cmonth - 1, cdate));
        return rtnstr;
    }


    /**
     * getSysDate (현재날짜를 반환한다.)
     *
     * @return sys date
     */
    public static String getSysDate() {
        Date today = new Date();

        String sysToDate;

        SimpleDateFormat date = new SimpleDateFormat("yyyyMMdd", Locale.KOREAN);

        sysToDate = date.format(today);

        return sysToDate;
    }

    /**
     * getTimeStamp
     *
     * @return time stamp
     */
    public static String getTimeStamp() {
        String sysToTimeStamp;
        java.text.SimpleDateFormat formatter=new java.text.SimpleDateFormat("yyyyMMddHHmmss", Locale.KOREA);

        sysToTimeStamp = formatter.format(new java.util.Date());

        return sysToTimeStamp;
    }


    /**
     * Gets current date.
     *
     * @return the current date
     */
    public static Date getCurrentDate() {

        return new Date();
    }

    /**
     * getTzCurrentDate (타임존 Date 가져오기)
     *
     * @param timeZone the time zone
     * @return the tz current date
     */
    private static Date getTzCurrentDate(String timeZone) {
        ZoneId defaultTimeZone = ZoneId.of(timeZone);

        Instant now = Instant.now();
        ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(now, defaultTimeZone);

        Date ans = null;
        try {
            ans = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(zonedDateTime.toString().substring(0, 19).replace("T", " "));
        } catch (ParseException e) {
            logger.error(e.getMessage());
            //e.printStackTrace();
        }

        return ans;
    }

    /**
     * main
     *
     * @param args the input arguments
     */
    public static void main(String[] args) {
        //logger.debug(getSysDate());
        //logger.debug(getTimeStamp());
        //logger.debug(getCurrentDate().toString());
        logger.debug(getTzCurrentDate("America/Los_Angeles").toString());
        logger.debug(getTzCurrentDate("Asia/Seoul").toString());

        //logger.debug(DateUtil.getDateToString(DateUtil.getTzCurrentDate("Asia/Seoul"),"yyyyMMddHHmmss"));
    }

    /**
     * Add date string.
     *
     * @param date1 the date 1
     * @param value the value
     * @return the string
     */
    public static String addDate(String date1, int value) {

        String dateStr = date1.replace("-", "");
        SimpleDateFormat fmt = new SimpleDateFormat("yyyyMMdd", Locale.KOREAN);
        Date date = null;
        try {
            date = fmt.parse(dateStr);
        } catch (ParseException e) {
            logger.error(e.getMessage());
            //e.getMessage();
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(Objects.requireNonNull(date));
        cal.add(Calendar.DATE, value);

        return fmt.format(cal.getTime());

    }

    /**
     * getBizDate (영업일자 가져오기)
     *
     * @return string
     */
    public static String getBizDate(){
        //TO-DO
        //영업일자 테이블에서 일자 정보 가져옴 TB_BIZ_DATE
        String dateFormat = "yyyyMMdd";

        Date dt         =   new Date();
        SimpleDateFormat sformat    =   new SimpleDateFormat(dateFormat);

        return sformat.format(dt);
    }


    /**
     * 두 날짜 차이 일수 가져오기 (PEK)
     *
     * @return int 차이일수
     */
    public static long getDateBetweenAandB(String fromDate, String toDate) {
        try{
            SimpleDateFormat sdf = new SimpleDateFormat(FormatStr.DATE_nr);
            //두날짜 사이의 시간 차이(ms)를 하루 동안의 ms(24시*60분*60초*1000밀리초) 로 나눈다.
            return (sdf.parse(toDate.replace("-","").replace(".","")).getTime()-sdf.parse(fromDate.replace("-","").replace(".","")).getTime())/(24*60*60*1000);
        }catch(ParseException e){
            logger.error(e.getMessage());
            //e.printStackTrace();
            return 0;
        }
    }


    /**
     * 포맷
     */
    interface FormatStr {
        /**
         * The constant DATE_nr.
         *
         * @일자포맷: yyyyMMdd
         */
        String DATE_nr = "yyyyMMdd";
        /**
         * The constant DTIME_nr.
         *
         * @일시포맷: yyyyMMddHHmmss
         */
        String DTIME_nr = "yyyyMMddHHmmss";
    }
}
