package com.abbidot.baselibrary.util

import android.os.Build
import android.text.TextUtils
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.text.SimpleDateFormat
import java.time.LocalDate
import java.time.Period
import java.util.Calendar
import java.util.Date
import java.util.Locale
import java.util.TimeZone
import java.util.concurrent.TimeUnit
import java.util.regex.Pattern
import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.roundToInt
import kotlin.math.sin


/**
 *Created  by .yzq on 2022/1/19/019.
 * @link
 * @description:工具类
 */
class Utils {

    companion object {

        //HTTP请求加密key
        var SECRET_KEY = ""
        const val DATE_FORMAT_PATTERN_CN = "yyyy-MM-dd"
        const val DATE_FORMAT_PATTERN_CN2 = "yyyy-MM-dd HH:mm:ss"
        const val DATE_FORMAT_PATTERN_CN3 = "yyyy/MM/dd HH:mm:ss"
        const val DATE_FORMAT_PATTERN_CN4 = "yyyy-MM-dd HH:mm"
        const val DATE_FORMAT_PATTERN_CN5 = "MM-dd HH:mm:ss"
        const val DATE_FORMAT_PATTERN_EN1 = "MMM d, yyyy | HH:mm"
        const val DATE_FORMAT_PATTERN_EN2 = "d MMM yyyy  hh:mm a"
        const val DATE_FORMAT_PATTERN_EN3 = "MMM d, yyyy"
        const val DATE_FORMAT_PATTERN_EN4 = "MMM d yyyy"
        const val DATE_FORMAT_PATTERN_EN5 = "d/M"
        const val DATE_FORMAT_PATTERN_EN6 = "dd/MM/yyyy HH:mm"
        const val DATE_FORMAT_PATTERN_EN7 = "dd/MM/yyyy"
        const val DATE_FORMAT_PATTERN_EN8 = "hh:mm a"
        const val DATE_FORMAT_PATTERN_EN9 = "MMM d, yyyy  hh:mm a"
        const val DATE_FORMAT_PATTERN_EN10 = "dd/MM/yyyy HH:mm:ss"
        const val DATE_FORMAT_PATTERN_EN11 = "dd/MM HH:mm"
        const val DATE_FORMAT_PATTERN_EN12 = "HH:mm:ss"
        const val DATE_FORMAT_PATTERN_EN13 = "MMM d  |  HH:mm"
        const val DATE_FORMAT_PATTERN_EN14 = "HH:mm"
        const val DATE_FORMAT_PATTERN_EN15 = "MM-dd HH:mm"

        //返回星期几 简写
        const val WEEK_FORMAT_PATTERN = "E"

        /**
         * 时间戳转指定格式时间
         *
         * @param cTimestamp 13位时间戳
         * @return 时间
         */
        fun formatTime(cTimestamp: Long, format: String): String {
            val timeMillis = if (cTimestamp < 1000000000000) cTimestamp * 1000 else cTimestamp
            // 创建一个使用系统默认时区的格式化器
            val sdf = SimpleDateFormat(format, Locale.getDefault())
            // 直接将时间戳（代表UTC时刻）格式化为本地时间字符串
            return sdf.format(Date(timeMillis))
        }

        /**
         * 获取当前时间
         * @param format 返回时间格式
         */
        fun getCurrentTime(format: String): String {
            val date = Calendar.getInstance().time
            val sdf = SimpleDateFormat(format, Locale.getDefault())
            return sdf.format(date)
        }

        /**
         * 把字符串转成日期
         * @param parseFormat 字符串是什么格式的日期就传什么格式
         * @param resultFormat 转换后的格式
         */
        fun stringToDate(
            dateString: String,
            parseFormat: String = DATE_FORMAT_PATTERN_CN2,
            resultFormat: String = DATE_FORMAT_PATTERN_CN2
        ): String {
            return try {
                formatTime(stringToTimestamp(dateString, parseFormat), resultFormat)
            } catch (e: Exception) {
                e.printStackTrace()
                LogUtil.e("解析失败,$e")
                ""
            }
        }

        /**
         * 把字符串转成时间戳,返回13位时间戳
         * @param parseFormat 字符串是什么格式的日期就传什么格式
         * @param isUtc 是否是0时区utc
         */
        fun stringToTimestamp(
            dateString: String,
            parseFormat: String = DATE_FORMAT_PATTERN_CN2,
            isUtc: Boolean = false
        ): Long {
            return try {
                val formatter = SimpleDateFormat(parseFormat, Locale.getDefault())
                if (isUtc) formatter.timeZone = TimeZone.getTimeZone("UTC")
                val date = formatter.parse(dateString)
                date?.time ?: 0
            } catch (e: Exception) {
                e.printStackTrace()
                LogUtil.e("解析失败,$e")
                0
            }
        }

        fun timestampAddHowTimestamp(cTimestamp: Long, period: Int, timeUnit: String): Long {
            val timeMillis = if (cTimestamp < 1000000000000) cTimestamp * 1000 else cTimestamp
            val calendar = Calendar.getInstance()
            calendar.timeInMillis = timeMillis
            when (timeUnit) {
                "DAY" -> calendar.add(Calendar.DAY_OF_MONTH, period)
                "MONTH" -> calendar.add(Calendar.MONTH, period)
                "YEAR" -> calendar.add(Calendar.YEAR, period)
            }
            return calendar.timeInMillis
        }

        /**
         * 获取这个时间戳的,前几天13位时间戳
         */
        fun getBeforeHowTimestamp(cTimestamp: Long, before: Long): Long {
            return cTimestamp - (before * 24 * 60 * 60 * 1000L)
        }

        /**
         * 获取这个时间戳的,后几天13位时间戳
         */
        fun getAfterHowTimestamp(cTimestamp: Long, after: Long): Long {
            return cTimestamp + (after * 24 * 60 * 60 * 1000L)
        }

        /**
         * 计算2个日期相册多少年,多少月,多少天
         */
        fun differYear(startTimestamp: Long, endTimestamp: Long): Array<String?> {
            val result = arrayOfNulls<String>(3)
            val startDate = formatTime(startTimestamp, DATE_FORMAT_PATTERN_CN)
            val endDate = formatTime(endTimestamp, DATE_FORMAT_PATTERN_CN)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                val period = Period.between(LocalDate.parse(startDate), LocalDate.parse(endDate))
                result[0] = "${period.years}"
                result[1] = "${period.months}"
                result[2] = "${if (period.days < 0) 0 else period.days}"
            } else {
                val dfs = SimpleDateFormat(DATE_FORMAT_PATTERN_CN, Locale.getDefault())
                val sDate = dfs.parse(startDate)!!
                val eDate = dfs.parse(endDate)!!

                val calendarStart = Calendar.getInstance()
                calendarStart.time = sDate
                val calendarEnd = Calendar.getInstance()
                calendarEnd.time = eDate

                var years = calendarEnd[Calendar.YEAR] - calendarStart[Calendar.YEAR]
                var months = calendarEnd[Calendar.MONTH] - calendarStart[Calendar.MONTH]
                var days = calendarEnd[Calendar.DAY_OF_MONTH] - calendarStart[Calendar.DAY_OF_MONTH]

                // 调整月份和天数以处理跨年情况
                if (days < 0) {
                    months--
                    calendarStart.add(Calendar.MONTH, 1) // 将开始日期增加一个月以进行比较
                    days =
                        calendarEnd[Calendar.DAY_OF_MONTH] + (30 - calendarStart[Calendar.DAY_OF_MONTH]) // 假设每个月有30天，简化计算
                }
                if (months < 0) {
                    years--
                    months += 12 // 将月份调整为正数以处理跨年情况
                }
                result[0] = "$years"
                result[1] = "$months"
                result[2] = "${if (days < 0) 0 else days}"
            }
            return result
        }

        /**
         * 秒转换为 时分秒
         */
        fun timeConversion(time: Int): String {
            var hour = 0
            var minutes = 0
            var second = 0
            val temp = time % 3600
            if (time > 3600) {
                hour = time / 3600
                if (temp != 0) {
                    if (temp > 60) {
                        minutes = temp / 60
                        if (temp % 60 != 0) {
                            second = temp % 60
                        }
                    } else {
                        second = temp
                    }
                }
            } else {
                minutes = time / 60
                if (time % 60 != 0) {
                    second = time % 60
                }
            }
            return "${fill2Digits(hour)}:${fill2Digits(minutes)}:${fill2Digits(second)}"
        }

        /**
         * 格式化2个时间相差多少
         */
        fun getTimeDifference(startMillis: Long, endMillis: Long): String {
            var diff = endMillis - startMillis
            val days = TimeUnit.MILLISECONDS.toDays(diff)
            diff -= TimeUnit.DAYS.toMillis(days)

            val hours = TimeUnit.MILLISECONDS.toHours(diff)
            diff -= TimeUnit.HOURS.toMillis(hours)

            val minutes = TimeUnit.MILLISECONDS.toMinutes(diff)
            var timeStr: String
            if (days > 0) {
                timeStr = if (days > 1) {
                    "$days days"
                } else {
                    "$days day"
                }
                if (hours > 0) {
                    timeStr += " ${hours}h"
                }
            } else {
                if (hours > 0) {
                    timeStr = "${hours}h"
                    if (minutes > 0) timeStr += " ${minutes}m"
                } else {
                    timeStr = if (minutes > 0) "${minutes}m"
                    else "1m"
                }
            }
            return timeStr
        }

        /**
         * 把秒转换为 day hour min
         */
        fun getSecondToDayHourMin(second: Long): Array<String> {
            val day = second / (24 * 60 * 60)
            val hour = (second % (24 * 60 * 60)) / (60 * 60)
            val min = ((second % (24 * 60 * 60)) % (60 * 60)) / 60
            return arrayOf(
                fill2Digits(day.toInt()), fill2Digits(hour.toInt()), fill2Digits(min.toInt())
            )
        }

        /**
         * @param d   需要处理的数字
         * @param num 保留位数
         * @return 保留num位小数后的字符串
         */
        fun formatDecimal(d: Double, num: Int = 2): String {
            return String.format(Locale("en", "US"), "%.${num}f", d)
        }

        /**
         * @param f   需要处理的数字
         * @param num 保留位数
         * @return 保留num位小数后的字符串
         */
        fun formatDecimal(f: Float, num: Int): String {
            return String.format(Locale("en", "US"), "%.${num}f", f)
        }

        /**
         * 四舍五入取整
         */
        fun roundOffToInt(f: Double): Int {
            return f.roundToInt()
        }

        const val KM = 0
        const val KCAL = 1

        /**
         * 处理转换为千 不足千不转换
         *
         * @param d        需要处理的数字 double类型才会精准四舍五入
         * @param num      保留位数(只能是1或者2)
         * @param unitType 单位类型 0里程m，km  1卡路里 cal kcal
         * @return
         */
        fun convertThousand(d: Double, num: Int, unitType: Int): String {
            return if (d < 1000) {
                var unit = " m"
                when (unitType) {
                    KM -> unit = " m"
                    KCAL -> unit = " Cal"
                }
                formatDecimal(d, num) + unit
            } else {
                var unit = " Km"
                when (unitType) {
                    KM -> unit = " Km"
                    KCAL -> unit = " KCal"
                }
                formatDecimal(d / 1000, num) + unit
            }
        }

        /**
         * 个位数补0转两位数
         */
        fun fill2Digits(value: Int): String {
            var str = value.toString()
            if (value < 10) {
                str = "0$value"
            }
            return str
        }

        /**
         * md5加密、32位小写加密
         */
        fun get32Md5Value(sSecret: String): String {
            if (TextUtils.isEmpty(sSecret)) {
                return ""
            }
            try {
                val bmd5 = MessageDigest.getInstance("MD5")
                bmd5.update(sSecret.toByteArray())
                var i: Int
                val buf = StringBuffer()
                val b = bmd5.digest()
                for (offset in b.indices) {
                    i = b[offset].toInt()
                    if (i < 0) i += 256
                    if (i < 16) buf.append("0")
                    buf.append(Integer.toHexString(i))
                }
                return buf.toString()
            } catch (e: NoSuchAlgorithmException) {
                e.printStackTrace()
            }
            return ""
        }

        /**
         * 判断邮箱email格式是否正确
         */
        fun isValidEmail(email: String): Boolean {
            val str =
                "^([a-zA-Z0-9_\\-.+]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(]?)$"
            return isRegularExpression(email, str)
        }

        /**
         * 是否符合该正则表达式
         */
        fun isRegularExpression(value: String, regex: String): Boolean {
            val p = Pattern.compile(regex)
            val m = p.matcher(value)
            return m.matches()
        }

        /**
         *求圆弧上某个点的坐标
         * @angle 角度是以圆的右方开始计算角度，顺时针增加
         */
        fun getPointOnCircleArc(
            centerX: Float, centerY: Float, radius: Float, angle: Double
        ): FloatArray {
            val angleInRadians = Math.toRadians(angle)
            val x = (centerX + radius * cos(angleInRadians)).toFloat()
            val y = (centerY + radius * sin(angleInRadians)).toFloat()
            return floatArrayOf(x, y)
        }

        /**
         * 获取圆弧上某个点和圆心角度
         */
        fun getAngleFromCenter(x: Float, y: Float, centerX: Float, centerY: Float): Double {
            val angle = atan2((y - centerY).toDouble(), (x - centerX).toDouble())
            // 转换为角度
            return Math.toDegrees(angle)
        }

        /**
         *根据信号区间转换为信号级别
         * @param numLevels 级别个数
         */
        fun calculateSignalLevel(
            rssi: Int, numLevels: Int, minRssi: Int = -100, maxRssi: Int = -55
        ): Int {
            return if (rssi <= minRssi) {
                0
            } else if (rssi >= maxRssi) {
                numLevels - 1
            } else {
                val inputRange: Float = (maxRssi - minRssi).toFloat()
                val outputRange = (numLevels - 1).toFloat()
                ((rssi - minRssi).toFloat() * outputRange / inputRange).toInt()
            }
        }

        /**
         * 根据电量计算级别
         */
        fun calculatePowerLevel(power: Int): Int {
            return if (power in 10..24) 1
            else if (power in 25..49) 2
            else if (power in 50..74) 3
            else if (power >= 75) 4
            else 0
        }
    }
}