package com.cpop.common.utils;

import com.cpop.common.enums.CycleEnum;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.management.ManagementFactory;
import java.net.HttpURLConnection;
import java.net.URL;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.DayOfWeek;
import java.time.Instant;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * 时间工具类
 *
 * @author DB
 */
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
    public static String YYYY = "yyyy";

    public static String YYYY_MM = "yyyy-MM";

    public static String YYYY_MM_DD = "yyyy-MM-dd";

    public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    public static String YYYYMMDD = "yyyyMMdd";

    public static String TIME = "HH:mm:ss";
    /**
     * （yyyy-MM-dd HH:mm）
     */
    public final static String DATE_TIME_HOUR_MINUTE = "yyyy-MM-dd HH:mm";

    private static final String[] parsePatterns = {
            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
            "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
            "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

    public final static String HOUR = "HH:mm";

    /**
     * 获取当前Date型日期
     *
     * @return Date() 当前日期
     */
    public static Date getNowDate() {
        return new Date();
    }

    /**
     * 获取当前日期, 默认格式为yyyy-MM-dd
     *
     * @return String
     */
    public static String getDate() {
        return dateTimeNow(YYYY_MM_DD);
    }

    public static String getTime() {
        return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
    }

    public static String dateTimeNow() {
        return dateTimeNow(YYYYMMDDHHMMSS);
    }

    public static String dateTimeNow(final String format) {
        return parseDateToStr(format, new Date());
    }

    public static String dateTime(final Date date) {
        return parseDateToStr(YYYY_MM_DD, date);
    }

    public static String parseDateToStr(final String format, final Date date) {
        return new SimpleDateFormat(format).format(date);
    }

    public static Date dateTime(final String format, final String ts) {
        try {
            return new SimpleDateFormat(format).parse(ts);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 日期路径 即年/月/日 如2018/08/08
     */
    public static String datePath() {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyy/MM/dd");
    }

    /**
     * 日期路径 即年/月/日 如20180808
     */
    public static String dateTime() {
        Date now = new Date();
        return DateFormatUtils.format(now, "yyyyMMdd");
    }

    /**
     * 日期型字符串转化为日期 格式
     */
    public static Date parseDate(Object str) {
        if (str == null) {
            return null;
        }
        try {
            return parseDate(str.toString(), parsePatterns);
        } catch (ParseException e) {
            return null;
        }
    }

    /**
     * 获取服务器启动时间
     */
    public static Date getServerStartDate() {
        long time = ManagementFactory.getRuntimeMXBean().getStartTime();
        return new Date(time);
    }

    /**
     * 计算两个时间差
     */
    public static String getDatePoor(Date endDate, Date nowDate) {
        long nd = 1000 * 24 * 60 * 60;
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        // long ns = 1000;
        // 获得两个时间的毫秒时间差异
        long diff = endDate.getTime() - nowDate.getTime();
        // 计算差多少天
        long day = diff / nd;
        // 计算差多少小时
        long hour = diff % nd / nh;
        // 计算差多少分钟
        long min = diff % nd % nh / nm;
        // 计算差多少秒//输出结果
        // long sec = diff % nd % nh % nm / ns;
        return day + "天" + hour + "小时" + min + "分钟";
    }

    /**
     * 对日期的【月】进行加/减
     *
     * @param date   日期
     * @param months 月数，负数为减
     * @return 加/减几月后的日期
     */
    public static Date addDateMonths(Date date, int months) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusMonths(months).toDate();
    }

    /**
     * 获取指定时间前一天的时间
     *
     * @param date
     * @return
     * @Author: ZJ
     */
    public static Date getLasDate(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - 1);
        return calendar.getTime();
    }

    /**
     * 对日期的【天】进行加/减
     *
     * @param date 日期
     * @param days 天数，负数为减
     * @return 加/减几天后的日期
     */
    public static Date addDateDays(Date date, int days) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusDays(days).toDate();
    }

    /**
     * 对日期的【小时】进行加/减
     *
     * @param date  日期
     * @param hours 小时数，负数为减
     * @return 加/减几小时后的日期
     */
    public static Date addDateHours(Date date, int hours) {
        DateTime dateTime = new DateTime(date);
        return dateTime.plusHours(hours).toDate();
    }

    /**
     * 判断当前时间是周几
     *
     * @param date
     * @return
     */
    public static String getWeek(Date date) {
        String format = DateUtils.parseDateToStr("yyyy-MM-dd", date);
        DateFormat format1 = new SimpleDateFormat("yyyy-MM-dd");
        Date now = null;
        try {
            now = format1.parse(format);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        assert now != null;
        Instant instant = now.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        java.time.LocalDate localDate = instant.atZone(zoneId).toLocalDate();
        DayOfWeek day = localDate.getDayOfWeek();
        String WeekDay = "";
        switch (day) {
            case MONDAY:
                WeekDay = "1";
                break;
            case FRIDAY:
                WeekDay = "5";
                break;
            case SATURDAY:
                WeekDay = "6";
                break;
            case SUNDAY:
                WeekDay = "7";
                break;
            case THURSDAY:
                WeekDay = "4";
                break;
            case TUESDAY:
                WeekDay = "2";
                break;
            case WEDNESDAY:
                WeekDay = "3";
                break;
        }
        return WeekDay;
    }

    /**
     * 获取指定时间前一个月的时间
     *
     * @param date 指定时间如果传空为当前时间
     * @return
     * @Author: 李性禄
     */
    public static Date getLastMon(Date date) {
        Calendar calendar = Calendar.getInstance();
        if (date != null) {
            calendar.setTime(date);
        }
        calendar.add(Calendar.MONTH, -1);
        return calendar.getTime();
    }

    /**
     * 获取指定时间前一年的时间
     *
     * @param date 指定时间如果传空为当前时间
     * @return
     * @Author: 李性禄
     */
    public static Date getLastYear(Date date) {
        Calendar calendar = Calendar.getInstance();
        if (date != null) {
            calendar.setTime(date);
        }
        calendar.add(Calendar.YEAR, -1);
        return calendar.getTime();
    }

    /**
     * 传入两个时间，比较两个时间相差年、月、日
     *
     * @param startDate
     * @param endxDate
     * @return
     */
    public static List<String> getTimeList(String startDate, String endxDate) {
        SimpleDateFormat sdf;
        int calendarType;

        switch (startDate.length()) {
            case 10:
                sdf = new SimpleDateFormat("yyyy-MM-dd");
                calendarType = Calendar.DATE;
                break;
            case 7:
                sdf = new SimpleDateFormat("yyyy-MM");
                calendarType = Calendar.MONTH;
                break;
            case 4:
                sdf = new SimpleDateFormat("yyyy");
                calendarType = Calendar.YEAR;
                break;
            default:
                return null;
        }

        List<String> result = new ArrayList<>();
        Calendar min = Calendar.getInstance();
        Calendar max = Calendar.getInstance();
        try {
            min.setTime(sdf.parse(startDate));
            min.add(calendarType, 0);
            max.setTime(sdf.parse(endxDate));
            max.add(calendarType, 1);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar curr = min;
        while (curr.before(max)) {
            result.add(sdf.format(min.getTime()));
            curr.add(calendarType, 1);
        }
        return result;
    }

    /**
     * 日期转换字符串
     *
     * @param date
     * @param pattern 转换的类型
     * @return
     */
    public static String format(Date date, String pattern) {
        if (date != null) {
            SimpleDateFormat df = new SimpleDateFormat(pattern);
            return df.format(date);
        }
        return null;
    }

    /**
     * 根据相差毫秒值查询相差多少天
     *
     * @param result
     * @return
     */
    public static long days(long result) {
        return result / (1000 * 60 * 60 * 24);
    }

    /**
     * 根据相差毫秒值查询相差多少个钟
     *
     * @param result
     * @return
     */
    public static long hour(long result) {
        return (result % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60);
    }

    /**
     * 根据相差毫秒值查询相差多少分钟
     *
     * @param result
     * @return
     */
    public static long minutes(long result) {
        return (result % (1000 * 60 * 60)) / (1000 * 60);
    }

    /**
     * 字符串转换成日期
     *
     * @param strDate 日期字符串
     * @param pattern 日期的格式，如：DateUtils.DATE_TIME_PATTERN
     */
    public static Date stringToDate(String strDate, String pattern) {
        if (StringUtils.isBlank(strDate)) {
            return null;
        }
        DateTimeFormatter fmt = DateTimeFormat.forPattern(pattern);
        return fmt.parseLocalDateTime(strDate).toDate();
    }

    /**
     * 根据传入的时间获取当前月份的所有日期
     *
     * @param date
     * @return
     */
    public static List<Date> getAllTheDateOfTheMonth(Date date) {
        List<Date> list = new ArrayList<Date>();
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DATE, 1);
        int month = cal.get(Calendar.MONTH);
        while (cal.get(Calendar.MONTH) == month) {
            list.add(cal.getTime());
            cal.add(Calendar.DAY_OF_YEAR, 1);
        }
        return list;
    }

    /**
     * 根据传入的时间获取是当月的第几天
     *
     * @param date
     * @return
     */
    public static Integer dayOfMonth(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 根据当前时间yyyyMMdd 格式判断是否是节假日（私人api慎用，容易服务挂掉）
     *
     * @param date 请求参数
     * @return 返回结果  默认返回 0：工作1-5  1：周末  2：节假日
     */
    public static String holidays(String date) {
        String httpUrl = "http://tool.bitefu.net/jiari/";
        BufferedReader reader = null;
        String holidays = null;
        StringBuffer sbf = new StringBuffer();
        httpUrl = httpUrl + "?d=" + date;
        try {
            URL url = new URL(httpUrl);
            HttpURLConnection connection = (HttpURLConnection) url
                    .openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            InputStream is = connection.getInputStream();
            reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
            String strRead = null;
            while ((strRead = reader.readLine()) != null) {
                sbf.append(strRead);
            }
            reader.close();
            holidays = sbf.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return holidays;
    }

    /**
     * 获取两个时间之前的日期
     *
     * @return
     */
    public static List<String> getDatesBetweenTwoDatesForApprove(Date startTime, Date endTime) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String date1 = sdf.format(startTime);
        String date2 = sdf.format(endTime);
        List<String> dateList = new ArrayList<String>();
        try {
            Date dateOne = sdf.parse(date1);
            Date dateTwo = sdf.parse(date2);
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(dateOne);
            dateList.add(sdf.format(dateOne));
            while (calendar.getTime().before(dateTwo)) {
                calendar.add(Calendar.DAY_OF_MONTH, +1);
                dateList.add(sdf.format(calendar.getTime()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return dateList;
    }

    /**
     * 计算两个时间是否为同一周期
     *
     * @param d1   时间1
     * @param d2   时间2
     * @param type 周期类型
     */
    public static Boolean sameCycle(Date d1, Date d2, int type) {
        CycleEnum cycle = CycleEnum.getCycle(type);
        assert cycle != null;
        if (cycle.equals(CycleEnum.YEAR)) {
            return isSameYear(d1, d2);
        } else if (cycle.equals(CycleEnum.MONTH)) {
            return isSameMonth(d1, d2);
        } else if (cycle.equals(CycleEnum.WEEK)) {
            return isSameWeek(d1, d2);
        } else if (cycle.equals(CycleEnum.DAY)) {
            return isSameDate(d1, d2);
        }
        return false;
    }

    /**
     * 同一年
     *
     * @param date1
     * @param date2
     */
    public static Boolean isSameYear(Date date1, Date date2) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);
        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        return cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR);
    }

    /**
     * 同一月
     *
     * @param date1
     * @param date2
     * @return
     */
    public static Boolean isSameMonth(Date date1, Date date2) {
        if (!isSameYear(date1, date2)) {
            return false;
        }
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);
        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        return cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH);
    }

    /**
     * 同一周
     *
     * @param date1
     * @param date2
     * @return
     */
    public static Boolean isSameWeek(Date date1, Date date2) {
        Calendar cal1 = Calendar.getInstance();
        Calendar cal2 = Calendar.getInstance();
        //西方周日为一周的第一天，咱得将周一设为一周第一天
        cal1.setFirstDayOfWeek(Calendar.MONDAY);
        cal1.setTime(date1);
        cal2.setTime(date2);
        return cal1.get(Calendar.WEEK_OF_YEAR) == cal2.get(Calendar.WEEK_OF_YEAR);
    }

    /**
     * 同一天
     *
     * @param date1
     * @param date2
     * @return
     */
    public static Boolean isSameDate(Date date1, Date date2) {
        if (!isSameMonth(date1, date2)) {
            return false;
        }
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);
        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        return cal1.get(Calendar.DAY_OF_MONTH) == cal2.get(Calendar.DAY_OF_MONTH);
    }

    /**
     * 查看两个时间之间的日期(包含结束那一天)
     *
     * @param startTime
     * @param endTime
     * @return
     */
    public static List<String> getDatesBetweenTwoDatesT(Date startTime, Date endTime) {
        List<String> days = new ArrayList<>();
        Calendar startCal = Calendar.getInstance();
        startCal.setTime(startTime);
        Calendar endCal = Calendar.getInstance();
        endCal.setTime(endTime);
        endCal.add(Calendar.DATE, 1);
        while (startCal.before(endCal)) {
            days.add(DateUtils.format(startCal.getTime(), DateUtils.YYYY_MM_DD));
            startCal.add(Calendar.DAY_OF_YEAR, 1);
        }
        return days;
    }


    /**
     * 获取指定时间内所有时间，所有天数转为字符串集合
     *
     * @param startTime 开始时间，
     *                  * @param endTime 结束时间
     *                  *@Author: 李性禄
     * @return
     */
    public static List<String> getDateList(Date startTime, Date endTime, String format) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format);
        List<String> list = new ArrayList<>();
        list.add(simpleDateFormat.format(startTime));
        String endDay = simpleDateFormat.format(endTime);

        String end = null;
        Date date = startTime;
        while (!endDay.equals(end)) {
            if ("yyyy-MM-dd".equals(format)) {
                date = getLasDate(date);
            }
            if ("yyyy-MM".equals(format)) {
                date = getLastMon(date);
            }
            end = simpleDateFormat.format(date);
            list.add(end);

        }
        return list;
    }


    public static String setTime(Date date) {
        long millis = System.currentTimeMillis();
        String endTim = "";
        if (date != null) {
            long time = date.getTime();
            long end = (millis - time) / 1000;
            if (end < 60L) {
                endTim = end + "秒前";
            } else if (end < 3600L) {
                endTim = (end / 60) + "分前";
            } else if (end < (long) (60 * 60 * 24)) {
                endTim = (end / (60 * 60)) + "小时前";
            } else if (end < (long) (60 * 60 * 24 * 30)) {
                endTim = (end / (60 * 60 * 24)) + "天前";
            } else if (end < (long) (60 * 60 * 24 * 30 * 12)) {
                endTim = (end / (60 * 60 * 24)) + "月前";
            } else {
                endTim = (end / (60 * 60 * 24 * 30 * 12)) + "年前";
            }
        }
        return endTim;
    }
}



