package com.fastcashier.lib_common.util

import com.blankj.utilcode.util.StringUtils
import java.lang.Exception
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
import kotlin.Throws

/**
 * 日期相关工具类
 */
object DateUtils {
    const val DF_YYYYMMDD = "yyyyMMdd"
    const val DF_YYMMDD = "yyMMdd"
    const val DF_YYYY_MM_DD = "yyyy-MM-dd"
    const val DF_YYYY_MM_DD2 = "yyyy/MM/dd"
    const val DF_YYYYMMDDHHMMSS = "yyyyMMddHHmmss"
    const val DF_YYYY_MM_DDHHMMSS = "yyyy-MM-dd HH:mm:ss"
    const val DF_HHMMSS = "HHmmss"
    const val DF_HHMMSS2 = "HH:mm:ss"
    const val DF_CN_YYYY_MM_DD = "yyyy年MM月dd日"
    const val DF_HHMM = "HH:mm"

    /**
     * 带ms的时间戳，与poshub对接时添加
     */
    const val DF_YYYY_MM_DD_HHMMSSSS = "yyyy-MM-dd HH:mm:ss.SSS"
    const val DF_YYYYMMDDHHMM = "yyyy/MM/dd HH:mm"
    private const val TAG = "DateUtils"

    /**
     * 将日期转换成yyyy-MM-dd HH:mm:ss.SSS字符串
     *
     * @return yyyy-MM-dd HH:mm:ss.SSS
     */
    fun format17(date: Date?): String {
        return format(date, DF_YYYY_MM_DD_HHMMSSSS)
    }

    /**
     * 将日期转换成字符串
     *
     * @param date
     * @param format
     * @return
     */
    fun format(date: Date?, format: String?): String {
        requireNotNull(date) { "Param date is null!" }
        require(!StringUtils.isEmpty(format)) { "Param format is blank!" }
        val sdf = SimpleDateFormat(format)
        return sdf.format(date)
    }

    /**
     * 将日期转换成yyyyMMddHHmmss字符串
     *
     * @param date
     * @return
     */
    fun format14(date: Date?): String {
        return format(date, DF_YYYYMMDDHHMMSS)
    }

    /**
     * 将日期转换成yyyy-MM-dd- HH:mm:ss字符串
     *
     * @param date
     * @return
     */
    fun format18(date: Date?): String {
        return format(date, DF_YYYY_MM_DDHHMMSS)
    }

    fun format8(date: Date?): String {
        return format(date, DF_YYYYMMDD)
    }

    fun format6(date: Date?): String {
        return format(date, DF_YYMMDD)
    }

    fun format10(date: Date?): String {
        return format(date, DF_YYYY_MM_DD)
    }

    fun formatCN(date: Date?): String {
        return format(date, DF_CN_YYYY_MM_DD)
    }

    fun formatCustom(date: Date?, style: String?): String {
        return format(date, style)
    }

    @Throws(ParseException::class)
    fun parse8(dateStr: String?): Date {
        return parse(dateStr, DF_YYYYMMDD)
    }

    @Throws(ParseException::class)
    fun parse10(dateStr: String?): Date {
        return parse(dateStr, DF_YYYY_MM_DD)
    }

    /**
     * 返回当前日期 yyyyMMdd格式 字符串
     *
     * @return
     */
    val now8: String
        get() = format8(Date())

    /**
     * 返回当前日期 yyyyMMdd格式 字符串
     *
     * @return
     */
    val now6: String
        get() = format6(Date())

    /**
     * 返回当前日期 yyyyMMdd格式 字符串
     *
     * @return
     */
    val now10: String
        get() = format10(Date())//unreachable

    /**
     * 获取当天0点 date对象
     *
     * @return
     */
    val today: Date?
        get() {
            var today: Date? = null
            today = try {
                parse(now8, DF_YYYYMMDD)
            } catch (e: ParseException) {
                //unreachable
                Date()
            }
            return today
        }

    /**
     * 获取某天的n天以前的0点
     */
    fun getDaysAgo(time: Date?, daysAgoNum: Int): Long {
        val calendar = Calendar.getInstance()
        calendar.time = time
        calendar.add(Calendar.DATE, -daysAgoNum)
        calendar[Calendar.HOUR_OF_DAY] = 0
        calendar[Calendar.MINUTE] = 0
        calendar[Calendar.SECOND] = 0
        calendar[Calendar.MILLISECOND] = 0
        return calendar.time.time
    }

    /**
     * 获取某天的n天以前的当前时间
     */
    fun getDaysAgoCurrent(date: Date, daysAgoNum: Int): Long {
        return date.time - daysAgoNum * 24 * 3600 * 1000
    }//得到前一天

    /**
     * 得到前一天
     */
    val yestedayFormat8: String
        get() {
            val calendar = Calendar.getInstance()
            calendar.add(Calendar.DATE, -1) //得到前一天
            val date = calendar.time
            return format8(date)
        }

    /**
     * 根据时间的字符串转成Date对象
     * yyyy-MM-dd HH:mm:ss
     *
     * @return
     */
    fun getDateByDateString(dateStr: String?): Date? {
        var today: Date? = null
        today = try {
            val sdf = SimpleDateFormat(DF_YYYY_MM_DDHHMMSS)
            return sdf.parse(dateStr)
        } catch (e: ParseException) {
            //unreachable
            Date()
        }
        return today
    }

    /**
     * 将不同格式的 String 转换成 时间戳
     *
     * @param str
     * @param formatStyle
     * @return
     */
    @Throws(ParseException::class)
    fun stringToLong(str: String?, formatStyle: String?): Long {
        val sdf = SimpleDateFormat(formatStyle)
        return sdf.parse(str).time //毫秒
    }

    /**
     * 根据时间的字符串转成Date对象
     * yyyy-MM-dd HH:mm:ss
     *
     * @return
     */
    fun getDateByDateString2(dateStr: String?): Date? {
        var today: Date? = null
        today = try {
            val sdf = SimpleDateFormat(DF_YYYYMMDDHHMMSS)
            return sdf.parse(dateStr)
        } catch (e: ParseException) {
            //unreachable
            Date()
        }
        return today
    }

    fun getDateStringByTimeStamp(timestamp: Long): String {
        val c = Calendar.getInstance()
        c.timeInMillis = timestamp
        val sdf = SimpleDateFormat(DF_YYYY_MM_DDHHMMSS)
        return sdf.format(c.time)
    }

    fun getDateStringByTimeStamp(timestamp: Long, pattern: String?): String {
        val c = Calendar.getInstance()
        c.timeInMillis = timestamp
        val sdf = SimpleDateFormat(pattern)
        return sdf.format(c.time)
    }//unreachable

    /**
     * 获取当年1月1日0点 date对象
     *
     * @return
     */
    val nowYear: Date?
        get() {
            var year: Date? = null
            year = try {
                val format = "yyyy"
                parse(format(Date(), format), format)
            } catch (e: ParseException) {
                //unreachable
                Date()
            }
            return year
        }//unreachable

    /**
     * 获取当月1号0点 date对象
     *
     * @return
     */
    val nowMonth: Date?
        get() {
            var month: Date? = null
            month = try {
                val format = "yyyy-MM"
                parse(format(Date(), format), format)
            } catch (e: ParseException) {
                //unreachable
                Date()
            }
            return month
        }

    fun getMonthSpace(date1: Date?, date2: Date?): Int {
        val c1 = Calendar.getInstance()
        val c2 = Calendar.getInstance()
        c1.time = date1
        c2.time = date2
        val result = c2[Calendar.YEAR] - c1[Calendar.YEAR]
        return if (result == 0) 1 else Math.abs(result)
    }

    @Throws(ParseException::class)
    fun getYearSpace4Now(date: String?): Int {
        val c1 = Calendar.getInstance()
        val c2 = Calendar.getInstance()
        val sdf = SimpleDateFormat("yyyyMM")
        c1.time = Date()
        c2.time = sdf.parse(date)
        val result = c2[Calendar.YEAR] - c1[Calendar.YEAR]
        return if (result == 0) 1 else Math.abs(result)
    }

    @Throws(ParseException::class)
    fun parse(dateStr: String?, format: String?): Date {
        val sdf = SimpleDateFormat(format)
        return sdf.parse(dateStr)
    }//设置为1号,当前日期既为本月第一天

    /**
     * @return 获取当前月第一天：
     */
    val firstDateOfCurrentMonth: Date?
        get() {
            val c = Calendar.getInstance()
            c.add(Calendar.MONTH, 0)
            c[Calendar.DAY_OF_MONTH] = 1 //设置为1号,当前日期既为本月第一天
            return try {
                parse(format8(c.time), DF_YYYYMMDD)
            } catch (e: ParseException) {
                null
            }
        }//设置为1号,当前日期既为本月第一天

    /**
     * @return 获取下月第一天：
     */
    val firstDateOfNextMonth: Date?
        get() {
            val c = Calendar.getInstance()
            c.add(Calendar.MONTH, 1)
            c[Calendar.DAY_OF_MONTH] = 1 //设置为1号,当前日期既为本月第一天
            return try {
                parse(format8(c.time), DF_YYYYMMDD)
            } catch (e: ParseException) {
                null
            }
        }

    /**
     * @return 获取当前月最后一天
     */
    val listDateOfCurrentMonth: Date?
        get() {
            val c = Calendar.getInstance()
            c[Calendar.DAY_OF_MONTH] = c.getActualMaximum(Calendar.DAY_OF_MONTH)
            return try {
                parse(format8(c.time), DF_YYYYMMDD)
            } catch (e: ParseException) {
                null
            }
        }

    /**
     * @return 当月的总天数
     */
    val currentMonthDay: Int
        get() {
            val a = Calendar.getInstance()
            a[Calendar.DATE] = 1
            a.roll(Calendar.DATE, -1)
            return a[Calendar.DATE]
        }

    /**
     * 计算时间间隔
     *
     * @param fDate 上次时间
     * @param oDate 本次时间
     * @return 精确到天
     */
    fun getIntervalDays(fDate: Date?, oDate: Date?): Int {
        var fDate = fDate
        var oDate = oDate
        if (fDate == null || oDate == null) {
            return -1
        }
        try {
            fDate = parse(format8(fDate), DF_YYYYMMDD)
            oDate = parse(format8(oDate), DF_YYYYMMDD)
        } catch (e: ParseException) {
        }
        val nd = (1000 * 24 * 60 * 60).toLong() //一天的毫秒数
        //获得两个时间的毫秒时间差异
        val diff = oDate!!.time - fDate!!.time
        val day = diff / nd //计算差多少天
        return day.toInt()
    }

    /**
     * @param date
     * @return
     * @throws ParseException
     */
    fun getDate8(date: Date?): Date? {
        try {
            return parse8(format8(date))
        } catch (e: ParseException) {
            //unreachable
        }
        return null
    }

    /**
     * 时间加days天
     *
     * @param date
     * @param days
     * @return
     */
    fun addDate(date: Date?, days: Int): Date {
        val calendar = Calendar.getInstance()
        calendar.time = date
        calendar.add(Calendar.DATE, days)
        return calendar.time
    }

    /**
     * 日期加法运算
     *
     * @param sourceDate
     * @param months     增加的月数，可为负数
     * @return
     */
    fun addMonths(sourceDate: Date?, months: Int): Date {
        val calendar = Calendar.getInstance()
        calendar.time = sourceDate
        calendar.add(Calendar.MONTH, months)
        return calendar.time
    }

    /**
     * 时间戳转换成日期格式字符串
     *
     * @param mseconds 精确到毫秒的字符串
     * @param format
     * @return
     */
    fun timeStamp2Date(mseconds: String?, format: String?): String {
        var format = format
        if (mseconds == null || mseconds.isEmpty() || mseconds == "null") {
            return ""
        }
        if (format == null || format.isEmpty()) {
            format = "yyyy-MM-dd HH:mm:ss"
        }
        val sdf = SimpleDateFormat(format)
        return sdf.format(Date(java.lang.Long.valueOf(mseconds)))
    }

    /**
     * @param startDate 开始时间
     * @param endDate   结束时间
     * @return true在时间段内，false不在时间段内
     */
    fun hourMinuteBetween(startDate: String?, endDate: String?): Boolean {
        return try {
            val format = SimpleDateFormat("HH:mm")
            val now = format.parse(format(Date(), DF_HHMM))
            val start = format.parse(startDate)
            val end = format.parse(endDate)
            val nowTime = now.time
            val startTime = start.time
            val endTime = end.time
            nowTime >= startTime && nowTime <= endTime
        } catch (e: Exception) {
            false
        }
    }
}