package com.microservices.wiki.refactoring.utils;


import com.microservices.wiki.refactoring.exception.BusiException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Assert;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

public class DateUtils {
    public static final String PATTERN_DATE_HOUR = "yyyy-MM-dd HH:mm";
    public static final String PATTERN_STANDARD = "yyyy-MM-dd HH:mm:ss";
    public static final String PATTERN_DATE = "yyyy-MM-dd";
    public static final String SHORT_PATTERN_DATE = "yyyyMMdd";
    public static final String PATTERN_FULL_DATE = "yyyyMMddHHmmss";
    public static final String SHORT_HOUR_MIN_DATE = "HHmm";
    public static final String PATTERN_DATE_ONLY_YEAR_MONTH = "yyyy-MM";
    public static final String ZERO_STR = "0";
    public static final String PATTERN_STANDARD_MILLISECOND = "yyyy-MM-dd HH:mm:ss.SSS";
    private static final Logger LOG = LoggerFactory.getLogger(DateUtils.class);

    private static final long ONE_DAY_MSED = 86400000L;

    private static final int MIN_TO_MSEC = 60000;

    private static final int[] WEEK_OF_DAYS = {7, 1, 2, 3, 4, 5, 6};

    public static long calculateTimeInMillis(Date from, Date to) {
        Calendar fromCal = getCalendar(from);
        Calendar toCal = getCalendar(to);
        return toCal.getTimeInMillis() - fromCal.getTimeInMillis();
    }

    public static Calendar getCalendar(Date date) {
        Calendar gc = Calendar.getInstance();
        gc.setTime(date);
        return gc;
    }

    public static String date2String(Date date, String pattern) {
        if (date == null) {
            return "";
        }
        String patternNew = pattern;
        if (StringUtils.isEmpty(pattern)) {
            patternNew = "yyyy-MM-dd HH:mm:ss";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(patternNew);
        return sdf.format(date);
    }

    public static String getNowDateTime() {
        Date now = new Date();
        return getFormatDate(now, "yyyy-MM-dd HH:mm:ss");
    }

    public static Date string2Date(String strDate, String pattern) throws BusiException {
        if ((strDate == null) || ("".equals(strDate))) {
            throw new BusiException("str date null");
        }
        String patternNew = pattern;
        if ((pattern == null) || ("".equals(pattern))) {
            patternNew = "yyyy-MM-dd";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(patternNew);
        Date date = null;
        try {
            date = sdf.parse(strDate);
        } catch (ParseException e) {
            throw new BusiException(e.toString());
        }
        return date;
    }

    public static String stringToYear(String strDest) throws BusiException {
        if ((strDest == null) || ("".equals(strDest))) {
            throw new BusiException("str dest null");
        }

        Date date = string2Date(strDest, "yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        return String.valueOf(c.get(1));
    }

    public static String stringToMonth(String strDest) throws BusiException {
        if ((strDest == null) || ("".equals(strDest))) {
            throw new BusiException("strDest null");
        }

        Date date = string2Date(strDest, "yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int month = c.get(2);
        month += 1;
        if (month < 10) {
            return "0" + month;
        }
        return String.valueOf(month);
    }

    public static String stringToDay(String strDest) throws BusiException {
        if ((strDest == null) || ("".equals(strDest))) {
            throw new BusiException("strDest is null");
        }

        Date date = string2Date(strDest, "yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int day = c.get(5);
        if (day < 10) {
            return "0" + day;
        }
        return Integer.toString(day);
    }

    public static Date getFirstDayOfMonth(Calendar c) {
        int year = c.get(1);
        int month = c.get(2);
        int day = 1;
        c.set(year, month, day, 0, 0, 0);
        return c.getTime();
    }

    public static Date getLastDayOfMonth(Calendar c) {
        int year = c.get(1);
        int month = c.get(2) + 1;
        int day = 1;
        if (month > 11) {
            month = 0;
            year += 1;
        }
        c.set(year, month, day - 1, 0, 0, 0);
        return c.getTime();
    }

    public static String date2GregorianCalendarString(Date date) throws BusiException {
        if (date == null) {
            throw new BusiException("Date is null");
        }
        long tmp = date.getTime();
        GregorianCalendar ca = new GregorianCalendar();
        ca.setTimeInMillis(tmp);
        try {
            XMLGregorianCalendar tXmlGregorianCalendar = DatatypeFactory.newInstance().newXMLGregorianCalendar(ca);
            return tXmlGregorianCalendar.normalize().toString();
        } catch (DatatypeConfigurationException e) {
            throw new BusiException("Date is null:" + e);
        }
    }

    public static boolean compareDate(Date firstDate, Date secondDate) throws BusiException {
        if ((firstDate == null) || (secondDate == null)) {
            throw new BusiException("Date is null");
        }

        String strFirstDate = date2String(firstDate, "yyyy-MM-dd");
        String strSecondDate = date2String(secondDate, "yyyy-MM-dd");
        return StringUtils.equals(strFirstDate, strSecondDate);
    }

    public static Date getStartTimeOfDate(Date currentDate) throws BusiException {
        Assert.notNull(currentDate, "");
        String strDateTime = date2String(currentDate, "yyyy-MM-dd") + " 00:00:00";
        return string2Date(strDateTime, "yyyy-MM-dd HH:mm:ss");
    }

    public static Date getEndTimeOfDate(Date currentDate) throws BusiException {
        Assert.notNull(currentDate, "");
        String strDateTime = date2String(currentDate, "yyyy-MM-dd") + " 23:59:59";
        return string2Date(strDateTime, "yyyy-MM-dd HH:mm:ss");
    }

    public static long dateStrToLong(String[] symbols, String dateStr) {
        String newDateStr = dateStr;
        for (String symbol : symbols) {
            newDateStr = newDateStr.replaceAll(symbol, "");
        }

        return Long.parseLong(newDateStr);
    }

    public static long dateAddMonthToLong(int month, int dateType) throws BusiException {
        Calendar c = Calendar.getInstance();
        c.add(2, month);
        String fmt;
        if (dateType == 1) {
            fmt = "yyyyMMddHHmm";
        } else {
            fmt = "yyyyMMdd";
        }
        try {
            return Long.parseLong(date2String(c.getTime(), fmt));
        } catch (Exception e) {
            LOG.error("日期转化异常：", e);
            throw new BusiException(e.toString());
        }
    }

    public static Date dateAddMin(Date date, int min) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(12, min);

        return c.getTime();
    }

    public static Date dateAddDay(Date date, int day) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(5, day);

        return c.getTime();
    }

    public static long getCurrtDateToLong(int dateType) throws BusiException {
        Date date = new Date();
        String fmt;
        if (dateType == 1) {
            fmt = "yyyyMMddHHmm";
        } else {
            fmt = "yyyyMMdd";
        }
        try {
            return Long.parseLong(date2String(date, fmt));
        } catch (Exception e) {
            LOG.error("getCurrtDateToLong异常：", e);
            throw new BusiException(e.toString());
        }
    }

    public static int daysOfTwo(Date sDate, Date eDate) {
        Calendar aCalendar = Calendar.getInstance();

        aCalendar.setTime(sDate);
        int day1 = aCalendar.get(6);
        aCalendar.setTime(eDate);
        int day2 = aCalendar.get(6);

        return day2 - day1;
    }

    public static int daysBetween(Date smdate, Date bdate)
            throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date newsmdate = sdf.parse(sdf.format(smdate));
        Date newBdate = sdf.parse(sdf.format(bdate));
        Calendar cal = Calendar.getInstance();
        cal.setTime(newsmdate);
        long time1 = cal.getTimeInMillis();
        cal.setTime(newBdate);
        long time2 = cal.getTimeInMillis();
        long betweenDays = (time2 - time1) / 86400000L;

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

    public static String getFormatDate(Date date) {
        Date newDate = date;
        if (newDate == null) {
            newDate = new Date();
        }
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        return sdf.format(newDate);
    }

    public static String getFormatDate() {
        return getFormatDate(new Date(), "yyyy-MM-dd");
    }

    public static String getFormatDate(Date date, String pattern) {
        Date newDate = date;
        if (newDate == null) {
            newDate = new Date();
        }
        String patternNew = pattern;
        if ((pattern == null) || ("".equals(pattern))) {
            patternNew = "yyyy-MM-dd";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(newDate);
    }

    public static String getFormatDateNoDefaultValue(Date date, String pattern) {
        Date newDate = date;
        if (newDate == null) {
            return "";
        }
        String patternNew = pattern;
        if ((pattern == null) || ("".equals(pattern))) {
            patternNew = "yyyy-MM-dd";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        return sdf.format(newDate);
    }

    public static boolean checkTimeIsInRange(Date date, int startTime, int endTime) {
        int hour = getCalendarResult(date, 11);
        int minute = getCalendarResult(date, 12);
        String nowStr = String.valueOf(hour);
        if (minute / 10 == 0) {
            nowStr = nowStr + "0" + minute;
        } else {
            nowStr = nowStr + Integer.toString(minute);
        }
        int mixTime = Integer.parseInt(String.format("%s", new Object[]{nowStr}));
        return (startTime <= mixTime) && (mixTime <= endTime);
    }

    public static int getDayOfWeek(Date date) {
        Date newDate = date;
        if (newDate == null) {
            newDate = new Date();
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int weekday = calendar.get(7) - 1;
        return WEEK_OF_DAYS[weekday];
    }

    private static int getCalendarResult(Date date, int type) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(type);
    }

    public static Date calculateDateWithMinutes(Date sourceDate, int minutes) {
        if (sourceDate == null)
            return null;
        return new Date(sourceDate.getTime() + minutes * 60000);
    }

    public static Date getDateFromStr1(String str) {
        try {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            return sdf.parse(str);
        } catch (Exception e) {
            LOG.error("字符串转yyyy-MM-dd HH:mm:ss格式时间出错，str=" + str + ",e=", e);
        }
        return null;
    }

    public static int getShortHourMin() {
        Date newDate = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("HHmm");
        return Integer.parseInt(sdf.format(newDate));
    }

    public static Date getShortMonth(int count) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(new Date());
        cal.add(2, count);
        return cal.getTime();
    }

    public static long getDateDiff(Date d1, Date d2) {
        Calendar c = Calendar.getInstance();
        c.setTime(d1);
        Calendar c1 = Calendar.getInstance();
        c1.setTime(d2);
        int date = c.get(6);
        int date1 = c1.get(6);
        return date - date1;
    }

    //日期天数加法
    public static String getDateAddDayString(Date date,Integer day){
        if(date == null || day==null){
            return null;
        }
        Calendar calendar = new GregorianCalendar();
        DateFormat df=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_WEEK,day);
        return df.format(calendar.getTime());
    }

    //日期天数加法
    public static Date getDateAddDay(Date date,Integer day,String pattern) throws ParseException {
        if(date.equals(null) || day.equals(null)){
            return null;
        }
        Calendar calendar = new GregorianCalendar();
        DateFormat df=new SimpleDateFormat(pattern);
        calendar.setTime(date);
        calendar.add(Calendar.DAY_OF_WEEK,day);
        String time = df.format(calendar.getTime());
        return df.parse(time);
    }

    //之前的日期与当前日期相差的时间（天、小时、分）
    public static String getDelayTime(Date previousDate) {
        Date now = new Date();
        if (previousDate == null) {
            return null;
        }
        long a = (now.getTime() - previousDate.getTime()) / (1000 * 60);
        int c = ((a < 0) == true ? 1 : 0) + ((a < 60) == true ? 1 : 0) + ((a < 60 * 24) == true ? 1 : 0);
        int day, hour, min;
        switch (c) {
            case 0:
                day = (int) a / 60 / 24;
                hour = (int) (a % (60 * 24)) / 60;
                min = (int) (a - day * 24 * 60 - hour * 60);
                return "相差" + day + "天" + hour + "小时" + min + "分钟";
            case 1:
                hour = (int) (a / 60);
                min = (int) (a % 60);
                return "相差" + hour + "小时" + min + "分钟";
            case 2:
                return "相差" + a + "分钟";
            case 3:
                return null;
        }
        return null;

    }

}

