package com.cyksj.common.util;

import cn.hutool.core.date.DateUtil;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

/**
 * @author valor
 * @date 2018/9/22 14:17
 */
public class Times {

    /**
     * 一天的秒数
     */
    public static final int second_per_day = 86400;
    /**
     * 一小时的毫秒数
     */
    public static final int millisecond_per_hour = 3600000;

    /**
     * 一个月的秒数
     */
    public static final int second_per_month = 259200;

    /**
     * 一分钟的毫秒数
     */
    public static final int millisecond_per_minute = 60000;

    /**
     * 默认时区
     */
//    private static final ZoneId zoneId;
//    static {
//        zoneId = ZoneId.of("Asia/Shanghai");
//    }

    /**
     * 默认时区的时间偏移量
     */
    private static final ZoneOffset zoneOffSet;
    static {
        // 8小时的秒数 8 * 60 * 60
        zoneOffSet = ZoneOffset.ofTotalSeconds(28800);
    }

    /**
     * 时间格式化 枚举类
     */
    public enum Formatter {
        DateTime(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.US)),
        ISO_8601(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US)),
        RFC_1123(DateTimeFormatter.ofPattern("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US)),
        DATAS(DateTimeFormatter.ofPattern("yyyy-MM-dd",Locale.US)),
        DATA_YM(DateTimeFormatter.ofPattern("yyyy-MM",Locale.US)),
        DATAS_ST(DateTimeFormatter.ofPattern("yyyy-MM-10",Locale.US)),
        MSEC(DateTimeFormatter.ofPattern("yyyy-MM-dd HHmmssSSS",Locale.US)),
        HOUR_MIN_SEC(DateTimeFormatter.ofPattern("HH:mm:ss",Locale.US)),
        HOUR_MIN_SEC_MSEC(DateTimeFormatter.ofPattern("HH:mm:ss:SSS",Locale.US)),
        YEAR_MONTH_DAY(DateTimeFormatter.ofPattern("yyyyMMdd HH:mm:ss",Locale.US)),
        DATE_YMD(DateTimeFormatter.ofPattern("yyyyMMdd",Locale.US)),
        DATA_10H(DateTimeFormatter.ofPattern("yyyy-MM-dd 10:00:00", Locale.US)),
        MONTH_DAY(DateTimeFormatter.ofPattern("MM/dd",Locale.US));


        private DateTimeFormatter formatter;

        Formatter(DateTimeFormatter formatter) {
            this.formatter = formatter;
        }

        public DateTimeFormatter getFormatter() {
            return this.formatter;
        }
    }

    /**
     * 不允许外部实例化
     */
    private Times() { }

    /**
     * 指定日期字符串 按指定格式转换成timestamp
     */
    public static long toTimestamp(String str, Formatter formatter) {
        return toTimestamp(str, formatter, zoneOffSet);
    }

    /**
     * 指定日期字符串 按指定格式转换成timestamp
     */
    public static long toTimestamp(String str, Formatter formatter, ZoneOffset offset) {
        return toDateTime(str, formatter).toEpochSecond(offset) * 1000L;
    }

    /**
     * 指定timestamp 按指定格式 格式化时间
     */
    public static String format(long time, Formatter formatter) {
        return format(time, formatter, zoneOffSet);
    }

    /**
     * 指定timestamp 按指定格式 格式化时间
     */
    public static String format(long time, Formatter formatter, ZoneOffset offset) {
        return format(toDateTime(time, offset), formatter);
    }

    /**
     * 指定LocalDateTime 按指定格式 格式化时间
     */
    public static String format(LocalDateTime time, Formatter formatter) {
        return time.format(formatter.getFormatter());
    }

    /**
     * 指定日期字符串 按指定格式转换成localDateTime
     */
    public static LocalDateTime toDateTime(String str, Formatter formatter) {
        return LocalDateTime.parse(str, formatter.getFormatter());
    }

    /**
     * 指定timestamp 转换成localDateTime
     */
    public static LocalDateTime toDateTime(long timestamp) {
        return toDateTime(timestamp, zoneOffSet);
    }

    /**
     * 指定timestamp 转换成localDateTime
     */
    public static LocalDateTime toDateTime(long timestamp, ZoneOffset offset) {
        long secs = timestamp / 1000L;
        return LocalDateTime.ofEpochSecond(secs, 0, offset);
    }

    /**
     * 判断指定timestamp 是否是过去的时间
     */
    public static boolean isPast(long time) {
        return System.currentTimeMillis() > time;
    }

    /**
     * 判断指定timestamp 是否是未来的时间
     */
    public static boolean isFuture(long time) {
        return System.currentTimeMillis() < time;
    }

    /**
     * 判断当前timestamp 是否在某个时间段内
     */
    public static boolean isInTime(long start, long end) {
        return isInTime(System.currentTimeMillis(), start, end);
    }

    /**
     * 判断指定timestamp 是否在某个时间段内
     */
    public static boolean isInTime(long time, long start, long end) {
        return start <= time && time <= end;
    }

    /**
     * 计算两个日期相差的 毫秒数
     */
    public static long between(LocalDateTime one, LocalDateTime another) {
        return Duration.between(one, another).toMillis();
    }

    /**
     * 获取今日零时timestamp
     */
    public static long getZeroPoint() {
        return getZeroPoint(0);
    }

    /**
     * 获取今日日期 格式 yyyy-MM-dd
     */
    public static String getTodayStr(){
        return format(getZeroPoint(0),Formatter.DATAS);
    }

    /**
     * 指定与今日相差的天数 获取零时timestamp
     */
    public static long getZeroPoint(int days) {
        return getZeroPoint(days, zoneOffSet);
    }

    /**
     * 指定与今日相差的天数 获取零时timestamp
     */
    public static long getZeroPoint(int days, ZoneOffset zoneOffSet) {
        return getZeroPoint(System.currentTimeMillis(), days, zoneOffSet);
    }

    /**
     * 指定时间戳 获取零时timestamp
     */
    public static long getZeroPoint(long timestamp) {
        return getZeroPoint(timestamp, 0);
    }

    /**
     * 指定时间戳 获取零时timestamp
     */
    public static long getZeroPoint(long timestamp, int days) {
        return getZeroPoint(timestamp, days, zoneOffSet);
    }

    /**
     * 指定时间戳 获取零时timestamp
     */
    public static long getZeroPoint(long timestamp, int days, ZoneOffset zoneOffSet) {
        int offset = zoneOffSet.getTotalSeconds();

        long time = timestamp / 1000L + offset;
        long point = time - time % second_per_day;

        if (0 != days) {
            point += days * second_per_day;
        }

        // 计算时 传入的时区为标准
        return (point - offset) * 1000L;
    }

    /**
     * 获取当前时间的10号时间戳
     */
    public static long getStartTime(long startTime){
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(startTime);
        long l = Times.toTimestamp(Times.format(c.getTimeInMillis(),Times.Formatter.DATAS_ST) + " 00:00:00", Times.Formatter.DateTime);
        if (c.getTimeInMillis() < l){
            c.add(Calendar.MONTH, -1);
            l = Times.toTimestamp(Times.format(c.getTimeInMillis(),Times.Formatter.DATAS_ST) + " 00:00:00", Times.Formatter.DateTime);
        }
        return l;
    }
    /**
     * 获取当前时间的次月10号时间戳
     */
    public static long getEndTime(){
        Calendar c = Calendar.getInstance();
        long l = Times.toTimestamp(Times.format(c.getTimeInMillis(), Times.Formatter.DATAS_ST) + " 00:00:00", Times.Formatter.DateTime);
        if (c.getTimeInMillis() >= l){
            c.add(Calendar.MONTH, 1);
            l = Times.toTimestamp(Times.format(c.getTimeInMillis(), Times.Formatter.DATAS_ST) + " 00:00:00", Times.Formatter.DateTime);
        }
        return l;
    }

    /**
     * 判断选择的日期是否是本周
     */
    public static boolean isThisWeek(long time) {
        Calendar calendar = Calendar.getInstance();
        calendar.setFirstDayOfWeek(Calendar.MONDAY);
        int currentWeek = calendar.get(Calendar.WEEK_OF_YEAR);
        calendar.setTime(new Date(time));
        int paramWeek = calendar.get(Calendar.WEEK_OF_YEAR);
        return paramWeek == currentWeek;
    }


    /**
     * 传入一个日期返回距今几年几天
     * @param date
     * @return 1年223天
     */
    public static String getDaysOfYear(String date) {
        String time = "";
        LocalDate startDate = LocalDate.parse(date);
        startDate = startDate.plusDays(-1L);
        LocalDate endDate = LocalDate.parse(DateUtil.format(new Date(), "yyyy-MM-dd"));
        LocalDate startDateOfYear = startDate.with(TemporalAdjusters.firstDayOfYear());
        LocalDate endDateOfYear = endDate.with(TemporalAdjusters.firstDayOfYear());
        long day1 = ChronoUnit.DAYS.between(startDate, endDate);
        long year = ChronoUnit.YEARS.between(startDate, endDate);
        long day2 = ChronoUnit.DAYS.between(startDateOfYear, endDateOfYear);
        if (day2 > day1) {
            endDateOfYear = endDateOfYear.minusYears(1);
            day2 = ChronoUnit.DAYS.between(startDateOfYear, endDateOfYear);
        }
        long sub = day1 - day2;
        if (year > 0) {
            time = year + "年";
            if (sub > 0) {
                time = time + sub + "天";
            }
        } else if (sub > 0) {
            time = sub + "天";
        }
        return time;
    }
}
