package com.tofly.scada.util;

import cn.hutool.core.date.DateUtil;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.*;

/**
 * @author haiqiu
 * 时间操作工具类
 */
public class TimeUtils {

    /**
     * @param startMonth @example: "2016-01"
     * @param endMonth   @example: "2019-11"
     * @return 两个时间之间的月份(含开始, 结束)
     * @throws ParseException
     */
    private static List<String> getMonths(String startMonth, String endMonth) throws ParseException {
        LinkedList<String> months = new LinkedList<>();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");
        Calendar minCalender = Calendar.getInstance();
        Calendar maxCalender = Calendar.getInstance();

        // 设置开始月份
        minCalender.setTime(sdf.parse(startMonth));
        minCalender.set(minCalender.get(Calendar.YEAR), minCalender.get(Calendar.MONTH), 1);

        maxCalender.setTime(sdf.parse(endMonth));
        // 设置日期,保证最后一个日期参数 大于 开始时间日历
        maxCalender.set(maxCalender.get(Calendar.YEAR), maxCalender.get(Calendar.MONTH), 2);

        while (minCalender.before(maxCalender)) {
            months.add(sdf.format(minCalender.getTime()));
            minCalender.add(Calendar.MONTH, 1);
        }
        return months;
    }

    /**
     * @return 两个时间之间的月份(含开始, 结束) + 表名
     * @throws ParseException
     */
    private static   List<String> getMonths(Date start, Date end) {
        LinkedList<String> tableNames = new LinkedList<>();

        SimpleDateFormat format = new SimpleDateFormat("yyyy_MM");

        Calendar minCalender = Calendar.getInstance();
        Calendar maxCalender = Calendar.getInstance();

        // 设置开始月份
        minCalender.setTime(start);
        minCalender.set(minCalender.get(Calendar.YEAR), minCalender.get(Calendar.MONTH), 1);

        maxCalender.setTime(end);
        // 设置日期,保证最后一个日期参数 大于 开始时间日历
        maxCalender.set(maxCalender.get(Calendar.YEAR), maxCalender.get(Calendar.MONTH), 2);

        while (minCalender.before(maxCalender)) {
            String date = format.format(minCalender.getTime());
            String tableName = "SCADA_MONTH_" + date;
            tableNames.add(tableName);
            minCalender.add(Calendar.MONTH, 1);
        }
        return tableNames;
    }


    public static String getMonthsByEndDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.DATE, cal.getActualMaximum(Calendar.DATE));
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        String end = DateUtil.format(cal.getTime(), "yyyy-MM-dd HH:mm:ss");
        return end;
    }

    public static String getMonthsByStartDay(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        String start = DateUtil.format(cal.getTime(), "yyyy-MM-dd HH:mm:ss");
        return start;
    }


    /**
     * 获取当前月份的开始时间和结束时间
     *
     * @param time 时间
     * @return
     */
    public static List<Date> getMonthsToStartAndEndByDate(Date time) {
        //整个日历调整时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(time == null ? new Date() : time);
        //倒退一个月开始时间
        calendar.set(Calendar.DATE, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        Date start = calendar.getTime();
        //倒退一个月最后一天时间
        calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DATE));
        calendar.set(Calendar.HOUR_OF_DAY, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        Date end = calendar.getTime();
        List<Date> list = new ArrayList<>();
        list.add(start);
        list.add(end);
        return list;
    }
    /**
     * Long类型时间戳转化为LocalDateTime
     *
     * @param dateTimeLong
     * @return
     */
    public static LocalDateTime fromLong2LocalDateTime(Long dateTimeLong) {
        LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(dateTimeLong), ZoneId.systemDefault());
        return dateTime;
    }
    /**
     * LocalDateTime转换为Date
     *
     * @param time
     * @return
     */
    public static Date convertLDTToDate(LocalDateTime time) {
        return Date.from(time.atZone(ZoneId.systemDefault()).toInstant());
    }
    /**
     * 时间格式字符串转化为指定格式的时间
     *
     * @param beginDate
     * @param dateFormat
     * @return
     */
    public static LocalDate fromString2LocalDate(String beginDate, String dateFormat) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(dateFormat);
        try {
            LocalDate fromDate = LocalDate.parse(beginDate, df);
            return fromDate;
        } catch (Exception e) {
            return null;
        }

    }
    /**
     * 获取指定天开始时间 2019-06-12 00:00:00
     *
     * @return
     * @author wangjk
     * @date 2019年6月12日
     */
    public static LocalDateTime getAssignTodayBeginTime(LocalDateTime localDateTime) {
        LocalDate currentDay = localDateTime.toLocalDate();
        return LocalDateTime.of(currentDay, LocalTime.MIN);
    }

    /**
     * 获取指定天结束时间 2019-06-12 23:59:59
     *
     * @return
     * @author wangjk
     * @date 2019年6月12日
     */
    public static LocalDateTime getAssignTodayEndTime(LocalDateTime localDateTime) {
        LocalDate currentDay = localDateTime.toLocalDate();
        return LocalDateTime.of(currentDay, LocalTime.MAX);
    }
    /**
     * 获取指定月第一天
     *
     * @return
     * @author wangjk
     * @date 2019年6月12日
     */
    public static LocalDate getFirstDayOfCurrentSpecifiedMonth(LocalDateTime currentDay) {
        return currentDay.toLocalDate().with(TemporalAdjusters.firstDayOfMonth());
    }
    /**
     * 获取指定月最后一天
     *
     * @return
     * @author wangjk
     * @date 2019年6月12日
     */
    public static LocalDate getLastDayOfCurrentSpecifiedMonth(LocalDateTime currentDay) {
        return currentDay.toLocalDate().with(TemporalAdjusters.lastDayOfMonth());
    }
    /**
     * LocalDate 转 Date
     */
    public static Date localDateToDate(LocalDate localDate) {
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
        return Date.from(instant);
    }

    public static LocalDateTime fromString2LocalDateTime(String beginDateTime, String dateFormat) {
        DateTimeFormatter df = DateTimeFormatter.ofPattern(dateFormat);
        try {
            return LocalDateTime.parse(beginDateTime, df);
        } catch (Exception e) {
            return null;
        }

    }

    public static LinkedHashMap<LocalDateTime,LocalDateTime> getHourPeriodMap(LocalDateTime startTime , LocalDateTime endTime){
        LinkedHashMap<LocalDateTime,LocalDateTime> resultMap = new LinkedHashMap<>(12);
        while (true){
            LocalDateTime localDateTime = startTime.plusHours(1);
            if(localDateTime.isBefore(endTime)){
                resultMap.put(startTime,localDateTime);
                startTime = localDateTime;
            }else {
                resultMap.put(startTime,localDateTime);
                return resultMap;
            }
        }

    }
    public static LinkedHashMap<LocalDateTime,LocalDateTime> getDayPeriodMap(LocalDateTime startTime , LocalDateTime endTime){
        LinkedHashMap<LocalDateTime,LocalDateTime> resultMap = new LinkedHashMap<>(12);
        while (true){
            LocalDateTime localDateTime = getAssignTodayEndTime(startTime);
            if(localDateTime.isBefore(endTime)){
                resultMap.put(startTime,localDateTime);
                startTime = getAssignTodayBeginTime(localDateTime.plusDays(1));
            }else {
                resultMap.put(startTime,localDateTime);
                return resultMap;
            }
        }

    }
    public static LinkedHashMap<LocalDateTime,LocalDateTime> getMonthPeriodMap( LocalDateTime startTime , LocalDateTime endTime){
        LinkedHashMap<LocalDateTime,LocalDateTime> resultMap = new LinkedHashMap<>(12);
        while (true){
            LocalDateTime localDateTime = LocalDateTime.of(TimeUtils.fromLong2LocalDateTime(TimeUtils.localDateToDate(getLastDayOfCurrentSpecifiedMonth(startTime)).getTime()).toLocalDate(), LocalTime.MAX);
            if(localDateTime.isBefore(endTime)){
                resultMap.put(startTime,localDateTime);
                startTime = TimeUtils.fromLong2LocalDateTime(TimeUtils.localDateToDate(getFirstDayOfCurrentSpecifiedMonth(localDateTime.plusDays(1))).getTime());
            }else {
                resultMap.put(startTime,localDateTime);
                return resultMap;
            }
        }

    }
    public static LinkedHashMap<LocalDateTime,LocalDateTime> getDateIntervalMap(Date start,Date end,Integer type){
        LocalDateTime strTime = TimeUtils.fromLong2LocalDateTime(start.getTime());
        LocalDateTime endTime = TimeUtils.fromLong2LocalDateTime(end.getTime());
        if(0==type){
            return getHourPeriodMap(strTime, endTime);
        }else if(1==type){
            return getDayPeriodMap(strTime, endTime);
        }else {
            return getMonthPeriodMap(strTime, endTime);
        }

    }

}
