package cn.palmte.work.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Stream;

/**
 * Created by wang.lin@esstx.cn on 2018/4/20.
 */
public class DateKit {
    public static final String TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DATE_FORMAT = "yyyy-MM-dd";
    public static final String DATE_FORMAT_YEAR_MONTH = "yyyyMM";
    public static final String DATE_FORMAT_YEAR_MONTH2 = "yyyy-MM";

    private DateKit() {
    }

    /**
     * 通过String类型获得指定时间
     */
    public static Date getDate(String date) {
        return getDate(date, TIME_FORMAT);
    }

    public static Date getDate(String date, String pattern) {
        if (StrKit.isBlank(date)) {
            return null;
        }
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat(StrKit.isBlank(pattern) ? TIME_FORMAT : pattern);
            return dateFormat.parse(date);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    public static String toStr(Date date, String format) {
        SimpleDateFormat sdf;
        if (null != format && !"".equals(format)) {
            sdf = new SimpleDateFormat(format);
            return sdf.format(date);
        } else {
            sdf = new SimpleDateFormat(DateKit.TIME_FORMAT);
            return sdf.format(date);
        }
    }

    /**
     * 将当前时间格式化为默认格式的字符串
     *
     * @return
     */
    public static String formatCurrentTime() {
        return new SimpleDateFormat(DATE_FORMAT).format(new Date());
    }


    /**
     * 获取默认格式的当前时间
     *
     * @return
     */
    public static String getCurrnetTimeString() {
        return new SimpleDateFormat(TIME_FORMAT).format(new Date());
    }


    /**
     * 获取当天（今日）零点零分零秒
     *
     * @return
     */
    public static Date todayZeroHour() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    /**
     * 获取当天(今日)23点59分59秒
     */
    public static Date todayLastHour() {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        return calendar.getTime();
    }

    public static Date dayZeroHour(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    public static Date dayLastHour(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        return calendar.getTime();
    }

    /**
     * 获取过去N天之前的日期
     */
    public static String getLastNDay(int n,String pattern){
        Calendar calendar = Calendar.getInstance();
        Date date = new Date();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, -n);
        date = calendar.getTime();
        SimpleDateFormat dateFormater = new SimpleDateFormat(pattern);
        String lastDay = dateFormater.format(date);
        return  lastDay;
    }

    /**
     * 获取未来第day天的日期
     * @param day
     * @return
     */
    public static String getFutureDate(int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) + day);
        Date today = calendar.getTime();
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        String result = format.format(today);
        return result;
    }

    /**
     * 获取日期的星期数
     *
     * @param datetime
     * @return
     */
    public static String dateToWeek(String datetime) {
        SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
        String[] weekDays = { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
        Calendar cal = Calendar.getInstance(); // 获得一个日历
        Date datet = null;
        try {
            datet = f.parse(datetime);
            cal.setTime(datet);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        int w = cal.get(Calendar.DAY_OF_WEEK) - 1; // 指示一个星期中的某天。
        if (w < 0)
            w = 0;
        return weekDays[w];
    }

    public static Date getLastNDay(int n){
        Calendar calendar = Calendar.getInstance();
        Date date = new Date();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, -n);
        return calendar.getTime();
    }

    public static Date getLastNDay(Date date, int n){
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, -n);
        return calendar.getTime();
    }

    /**
     *  获取两个日期相差的月数
     * @param d1    较大的日期
     * @param d2    较小的日期
     * @return  如果d1>d2返回 月数差 否则返回0
     */
    public static int getMonthDiff(Date d1, Date d2) {
        Calendar c1 = Calendar.getInstance();
        Calendar c2 = Calendar.getInstance();
        c1.setTime(d1);
        c2.setTime(d2);
        if(c1.getTimeInMillis() < c2.getTimeInMillis()) return 0;
        int year1 = c1.get(Calendar.YEAR);
        int year2 = c2.get(Calendar.YEAR);
        int month1 = c1.get(Calendar.MONTH);
        int month2 = c2.get(Calendar.MONTH);
        int day1 = c1.get(Calendar.DAY_OF_MONTH);
        int day2 = c2.get(Calendar.DAY_OF_MONTH);
        // 获取年的差值 假设 d1 = 2015-8-16  d2 = 2011-9-30
        int yearInterval = year1 - year2;
        // 如果 d1的 月-日 小于 d2的 月-日 那么 yearInterval-- 这样就得到了相差的年数
        if(month1 < month2 || month1 == month2 && day1 < day2) {yearInterval --;}
        // 获取月数差值
        int monthInterval =  (month1 + 12) - month2  ;
        if(day1 < day2) {monthInterval --;}
        monthInterval %= 12;
        return yearInterval * 12 + monthInterval;
    }

    /**
     * 返回 d2与d1之间相差的天数
     * @param d1
     * @param d2
     * @return
     */
    public static int getDayDiff(String d1, String d2) {
        Date date1 = getDate(d1);
        Date date2 = getDate(d2);
        if (date1 != null && date2 != null) {
            return (int) ((date2.getTime() - date1.getTime()) / (1000*3600*24));
        }
        return 0;
    }

    /**
     * 计算两个日期之间相差的天数
     * @param smdate 较小的时间
     * @param bdate  较大的时间
     * @return 相差天数
     * @throws ParseException
     */
    public static int daysBetween(Date smdate,Date bdate) throws ParseException
    {
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
        smdate=sdf.parse(sdf.format(smdate));
        bdate=sdf.parse(sdf.format(bdate));
        Calendar cal = Calendar.getInstance();
        cal.setTime(smdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(bdate);
        long time2 = cal.getTimeInMillis();
        long between_days=(time2-time1)/(1000*3600*24);

        return Integer.parseInt(String.valueOf(between_days));
    }

    /**
     * 获取某一天所在的月,返回yyyymm
     * @param day yyyy-mm-dd
     */
    public static String dayYearMonth(String day){
        Date date = DateKit.getDate(day, DateKit.DATE_FORMAT);
        return DateKit.toStr(date, DateKit.DATE_FORMAT_YEAR_MONTH);
    }

    /**
     * 获取当前时间是星期几
     * @return 星期一返回1 星期二返回2...
     */
    public static int dayForWeek(){
        Calendar c = Calendar.getInstance();
        c.setTime(new Date());
        int dayForWeek;
        if(c.get(Calendar.DAY_OF_WEEK) == 1){
            dayForWeek = 7;
        }else{
            dayForWeek = c.get(Calendar.DAY_OF_WEEK) - 1;
        }
        return dayForWeek;
    }




    public static Date getDateByParDate(Date date,int count){
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int day1 = c.get(Calendar.DATE);
        c.set(Calendar.DATE, day1 + count);
        return c.getTime();

    }

    public static void main(String[] args) {
        String dateStr = "2018-09-01";
        Date date = DateKit.getDate(dateStr,DATE_FORMAT);
        Date date2 = DateKit.getDateByParDate(date,-3);
        System.out.println(DateKit.toStr(date2,DATE_FORMAT));

        getBetweenDate("2018-08-01",dateStr);

    }

    /**
     * 获取两个时间中最新的一个
     * @param date1
     * @param date2
     * @return
     */
    public static Date getLastDate(Date date1, Date date2) {
        if (date1 == null && date2 == null) {
            return new Date();
        }
        if (date1 == null) {
            return date2;
        }
        if (date2 == null) {
            return date1;
        }

        if (date1.getTime() > date2.getTime()) {
            return date1;
        }else {
            return date2;
        }
    }

    /**
     * 传入一个日期，获取该日期所在月份的第一天
     * @param date
     * @return
     */
    public static Date getMonthStartByDate(Date date){
        return getMonthStart(date);
    }

    /**
     * 传入一个日期，获取该日期所在月份的最后一天
     * @param date
     * @return
     */
    public static Date getMonthEndByDate(Date date){
        return getMonthEnd(date);
    }


    private static Date getMonthStart(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int index = calendar.get(Calendar.DAY_OF_MONTH);
        calendar.add(Calendar.DATE, (1 - index));
        return calendar.getTime();
    }


    private static Date getMonthEnd(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MONTH, 1);
        int index = calendar.get(Calendar.DAY_OF_MONTH);
        calendar.add(Calendar.DATE, (-index));
        return calendar.getTime();
    }

    /**
     * 获取指定日期的月的第一天和最后一天日期字符串
     */
    public static SyncParams getFirstAndLastDateOfMonthBParams(Date date) {
        // 获取当前年份、月份、日期
        Calendar cale = Calendar.getInstance();
        cale.setTime(date);
        // 获取当月第一天和最后一天
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        // 获取前月的第一天
        cale = Calendar.getInstance();
        cale.setTime(date);
        cale.add(Calendar.MONTH, 0);
        cale.set(Calendar.DAY_OF_MONTH, 1);
        String firstday = format.format(cale.getTime());
        // 获取前月的最后一天
        cale = Calendar.getInstance();
        cale.setTime(date);
        cale.add(Calendar.MONTH, 1);
        cale.set(Calendar.DAY_OF_MONTH, 0);
        String lastday = format.format(cale.getTime());
        SyncParams s = new SyncParams();
        s.start = firstday;
        s.end = lastday;
        return s;
    }

    public static class SyncParams {
        public String start;
        public String end;

        /**
         * @return
         * @see Object#toString()
         */
        @Override
        public String toString() {
            return start + " - " + end;
        }

    }

    /**
     * 当前时间是否在某个时间段内
     * @param startDate
     * @param endDate
     * @return
     */
    public static boolean dateBetween(String startDate, String endDate) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Date now = null;
        Date start = null;
        Date end = null;
        try {
            start = format.parse(startDate);
            end = format.parse(endDate);
            now = format.parse(format.format(new Date()));
        } catch (ParseException e) {
            e.printStackTrace();
            return false;
        }

        long nowTime = now.getTime();
        long startTime = start.getTime();
        long endTime = end.getTime();

        return nowTime >= startTime && nowTime <= endTime;
    }


    public static Long getSecondsNextEarlyMorning() {
        Calendar cal = Calendar.getInstance();
        cal.add(Calendar.DAY_OF_YEAR, 1);
        // 改成这样就好了
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return (cal.getTimeInMillis() - System.currentTimeMillis()) / 1000;
    }


    /**
     * 获取两个日期间隔的所有日期
     * @param start 格式必须为'2018-01-25'
     * @param end 格式必须为'2018-01-25'
     * @return
     */
    public static List<String> getBetweenDate(String start, String end){
        List<String> list = new ArrayList<>();
        LocalDate startDate = LocalDate.parse(start);
        LocalDate endDate = LocalDate.parse(end);

        long distance = ChronoUnit.DAYS.between(startDate, endDate);
        if (distance < 1) {
            return list;
        }
        Stream.iterate(startDate, d -> {
            return d.plusDays(1);
        }).limit(distance + 1).forEach(f -> {
            list.add(f.toString());
        });
        return list;
    }

}
