package com.cheng.blzb.utils

import android.text.TextUtils
import com.example.base.utils.SpanUtils
import java.security.MessageDigest
import java.security.NoSuchAlgorithmException
import java.text.DecimalFormat
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.GregorianCalendar
import java.util.Hashtable
import java.util.Locale
import java.util.UUID
import java.util.concurrent.ThreadLocalRandom
import java.util.regex.Matcher
import java.util.regex.Pattern


object StringUtils {
    /**
     * 功能：身份证的有效验证
     *
     * @param IDStr 身份证号
     * @return 有效：返回"" 无效：返回String信息
     * @throws ParseException
     */
    @Throws(ParseException::class)
    fun IDCardValidate(IDStr: String): Boolean {
        var errorInfo = "" // 记录错误信息
        val ValCodeArr = arrayOf(
            "1", "0", "x", "9", "8", "7", "6", "5", "4",
            "3", "2"
        )
        val Wi = arrayOf(
            "7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7",
            "9", "10", "5", "8", "4", "2"
        )
        var Ai = ""
        // ================号码的长度 15位或18位 ================
        if (IDStr.length != 15 && IDStr.length != 18) {
            errorInfo = "身份证号码长度应该为15位或18位。"
            return false
        }
        // =======================(end)========================

        // ================ 数字 除最后以为都为数字================
        if (IDStr.length == 18) {
            Ai = IDStr.substring(0, 17)
        } else if (IDStr.length == 15) {
            Ai = IDStr.substring(0, 6) + "19" + IDStr.substring(6, 15)
        }
        if (isNumeric(Ai) == false) {
            errorInfo = "身份证15位号码都应为数字 ; 18位号码除最后一位外，都应为数字。"
            return false
        }
        // =======================(end)========================

        // ================ 出生年月是否有效 ================
        val strYear = Ai.substring(6, 10) //  年份
        val strMonth = Ai.substring(10, 12) // 月份
        val strDay = Ai.substring(12, 14) // 月份
        if (isDataFormat("$strYear-$strMonth-$strDay") == false) {
            errorInfo = "身份证生日无效。"
            return false
        }
        val gc = GregorianCalendar()
        val s = SimpleDateFormat("yyyy-MM-dd")
        try {
            if (gc[Calendar.YEAR] - strYear.toInt() > 150
                || gc.time.time - s.parse(
                    "$strYear-$strMonth-$strDay"
                ).time < 0
            ) {
                errorInfo = "身份证生日不在有效范围。"
                return false
            }
        } catch (e: NumberFormatException) {
            // TODO Auto-generated catch block
            e.printStackTrace()
        } catch (e: ParseException) {
            // TODO Auto-generated catch block
            e.printStackTrace()
        }
        if (strMonth.toInt() > 12 || strMonth.toInt() == 0) {
            errorInfo = "身份证月份无效"
            return false
        }
        if (strDay.toInt() > 31 || strDay.toInt() == 0) {
            errorInfo = "身份证日期无效"
            return false
        }
        // =====================(end)=====================

        // ================ 地区码时候有效================
        val h = GetAreaCode()
        if (h[Ai.substring(0, 2)] == null) {
            errorInfo = "身份证地区编码错误。"
            return false
        }
        // ==============================================

        // ================ 判断最后一位的值================
        var TotalmulAiWi = 0
        for (i in 0..16) {
            TotalmulAiWi = (TotalmulAiWi
                    + Ai[i].toString().toInt() * Wi[i].toInt())
        }
        val modValue = TotalmulAiWi % 11
        val strVerifyCode = ValCodeArr[modValue]
        Ai = Ai + strVerifyCode
        if (IDStr.length == 18) {
            if (Ai == IDStr == false) {
                errorInfo = "身份证无效，不是合法的身份证号码"
                return false
            }
        } else {
            return true
        }
        // =====================(end)=====================
        return true
    }

    /**
     * 功能：判断字符串是否为数字
     *
     * @param str
     * @return
     */
    private fun isNumeric(str: String): Boolean {
        val pattern = Pattern.compile("[0-9]*")
        val isNum = pattern.matcher(str)
        return if (isNum.matches()) {
            true
        } else {
            false
        }
    }

    /**
     * 功能：设置地区编码
     *
     * @return Hashtable 对象
     */
    private fun GetAreaCode(): Hashtable<String, String> {
        val hashtable = Hashtable<String, String>()
        hashtable["11"] = "北京"
        hashtable["12"] = "天津"
        hashtable["13"] = "河北"
        hashtable["14"] = "山西"
        hashtable["15"] = "内蒙古"
        hashtable["21"] = "辽宁"
        hashtable["22"] = "吉林"
        hashtable["23"] = "黑龙江"
        hashtable["31"] = "上海"
        hashtable["32"] = "江苏"
        hashtable["33"] = "浙江"
        hashtable["34"] = "安徽"
        hashtable["35"] = "福建"
        hashtable["36"] = "江西"
        hashtable["37"] = "山东"
        hashtable["41"] = "河南"
        hashtable["42"] = "湖北"
        hashtable["43"] = "湖南"
        hashtable["44"] = "广东"
        hashtable["45"] = "广西"
        hashtable["46"] = "海南"
        hashtable["50"] = "重庆"
        hashtable["51"] = "四川"
        hashtable["52"] = "贵州"
        hashtable["53"] = "云南"
        hashtable["54"] = "西藏"
        hashtable["61"] = "陕西"
        hashtable["62"] = "甘肃"
        hashtable["63"] = "青海"
        hashtable["64"] = "宁夏"
        hashtable["65"] = "新疆"
        hashtable["71"] = "台湾"
        hashtable["81"] = "香港"
        hashtable["82"] = "澳门"
        hashtable["91"] = "国外"
        return hashtable
    }

    /**
     * 验证日期字符串是否是YYYY-MM-DD格式
     *
     * @param str
     * @return
     */
    private fun isDataFormat(str: String): Boolean {
        var flag = false
        // String
        // regxStr="[1-9][0-9]{3}-[0-1][0-2]-((0[1-9])|([12][0-9])|(3[01]))";
        val regxStr =
            "^((\\d{2}(([02468][048])|([13579][26]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-\\/\\s]?((((0?[13578])|(1[02]))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\/\\s]?((0?[1-9])|(1[0-9])|(2[0-8]))))))(\\s(((0?[0-9])|([1-2][0-3]))\\:([0-5]?[0-9])((\\s)|(\\:([0-5]?[0-9])))))?$"
        val pattern1 = Pattern.compile(regxStr)
        val isNo = pattern1.matcher(str)
        if (isNo.matches()) {
            flag = true
        }
        return flag
    }
    //2.判断字符串是否是邮箱：
    /**
     * 描述：是否是邮箱.
     *
     * @param str 指定的字符串
     * @return 是否是邮箱:是为true，否则false
     */
    fun isEmail(str: String): Boolean {
        var isEmail = false
        val expr = "^([a-z0-9A-Z]+[-|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$"
        if (str.matches(expr.toRegex())) {
            isEmail = true
        }
        return isEmail
    }
    //3.判断字符串是否是银行卡
    /**
     * 判断是否是银行卡号
     *
     * @param cardId
     * @return
     */
    fun checkBankCard(cardId: String): Boolean {
        val bit = getBankCardCheckCode(
            cardId
                .substring(0, cardId.length - 1)
        )
        return if (bit == 'N') {
            false
        } else cardId[cardId.length - 1] == bit
    }

    private fun getBankCardCheckCode(nonCheckCodeCardId: String?): Char {
        if (nonCheckCodeCardId == null || nonCheckCodeCardId.trim { it <= ' ' }.length == 0 || !nonCheckCodeCardId.matches("\\d+".toRegex())) {
            // 如果传的不是数据返回N
            return 'N'
        }
        val chs = nonCheckCodeCardId.trim { it <= ' ' }.toCharArray()
        var luhmSum = 0
        var i = chs.size - 1
        var j = 0
        while (i >= 0) {
            var k = chs[i].code - '0'.code
            if (j % 2 == 0) {
                k *= 2
                k = k / 10 + k % 10
            }
            luhmSum += k
            i--
            j++
        }
        return if (luhmSum % 10 == 0) '0' else (10 - luhmSum % 10 + '0'.code).toChar()
    }
    //4、判断字符串是否是手机号
    /**
     * 判断是否是手机号
     *
     * @param phone
     * @return
     */
    fun checkPhone(phone: String?): Boolean {
        val pattern = Pattern
            .compile("^(13[0-9]|15[0-3]|15[5-9]|18[0-9]|14[57]|17[0678])\\d{8}$")
        val matcher = pattern.matcher(phone)
        return if (matcher.matches()) {
            true
        } else false
    }
    //5.判断字符串是否是中文或者包含中文
    /**
     * 描述：判断一个字符串是否为null或空值.
     *
     * @param str 指定的字符串
     * @return true or false
     */
    fun isEmpty(str: String?): Boolean {
        return str == null || str.trim { it <= ' ' }.length == 0
    }

    /**
     * 描述：是否是中文.
     *
     * @param str 指定的字符串
     * @return 是否是中文:是为true，否则false
     */
    fun isChinese(str: String): Boolean {
        var isChinese = true
        val chinese = "[\u0391-\uFFE5]"
        if (!isEmpty(str)) {
            //获取字段值的长度，如果含中文字符，则每个中文字符长度为2，否则为1
            for (i in 0 until str.length) {
                //获取一个字符
                val temp = str.substring(i, i + 1)
                //判断是否为中文字符
                if (temp.matches(chinese.toRegex())) {
                } else {
                    isChinese = false
                }
            }
        }
        return isChinese
    }

    /**
     * 描述：是否包含中文.
     *
     * @param str 指定的字符串
     * @return 是否包含中文:是为true，否则false
     */
    fun isContainChinese(str: String): Boolean {
        var isChinese = false
        val chinese = "[\u0391-\uFFE5]"
        if (!isEmpty(str)) {
            //获取字段值的长度，如果含中文字符，则每个中文字符长度为2，否则为1
            for (i in 0 until str.length) {
                //获取一个字符
                val temp = str.substring(i, i + 1)
                //判断是否为中文字符
                if (temp.matches(chinese.toRegex())) {
                    isChinese = true
                } else {
                }
            }
        }
        return isChinese
    }

    /**
     * 比较两个String的list 是否改变过
     *
     * @param listNew
     * @param listOld
     * @return
     */
    fun compareList(listNew: List<String?>?, listOld: List<String?>?): Boolean {
        return if (listOld == null && listNew == null) {
            false
        } else if (listOld != null && listNew != null) {
            if (listNew.size != listOld.size) {
                true
            } else !(listOld.containsAll(listNew) && listNew.containsAll(listOld))
        } else {
            true
        }
    }

    /**
     * 比较两个String 是否改变过
     *
     * @param newStr
     * @param oldStr
     * @return
     */
    fun compareString(newStr: String?, oldStr: String?): Boolean {
        return if (newStr == null && oldStr == null) {
            false
        } else if (newStr != null && oldStr != null) {
            newStr != oldStr
        } else {
            true
        }
    }

    /**
     * 比较签名 是否改变过
     *
     * @param newStr
     * @param oldStr
     * @return
     */
    fun compareSign(newStr: String, oldStr: String): Boolean {
        return if (TextUtils.isEmpty(oldStr)) { //当原始值没有的时候 无需验证  因为上报时需验证是否已签过字 而且当原始值有的时候 依据现有业务新值不可能清空 故无需再判断其他情况
            true
        } else newStr != oldStr
    }

    /**
     * 随机生成一个UUID
     */
    fun createUUID(): String {
        return UUID.randomUUID().toString()
    }

    fun createUUIDFromLong(): String {
        return UUID(ThreadLocalRandom.current().nextLong(), ThreadLocalRandom.current().nextLong()).toString()
    }

    /**
     * MD5加密
     */
    fun getMD5String(data: String): String? {
        try {
            val md = MessageDigest.getInstance("MD5")
            md.update(data.toByteArray())
            val result = md.digest()
            val stringBuffer = StringBuffer()
            for (i in result.indices) {
                val hex = Integer.toHexString(0xff and result[i].toInt())
                if (hex.length == 1) stringBuffer.append('0')
                stringBuffer.append(hex)
            }
            return stringBuffer.toString()
        } catch (e: NoSuchAlgorithmException) {
            e.printStackTrace()
        }
        return null
    }

    /**
     * 对数组进行MD5加密
     *
     * @param bytes
     * @return
     */
    fun getMD5Byte(bytes: ByteArray?): String? {
        try {
            val md = MessageDigest.getInstance("MD5")
            md.update(bytes)
            val result = md.digest()
            val stringBuffer = StringBuffer()
            for (i in result.indices) {
                val hex = Integer.toHexString(0xff and result[i].toInt())
                if (hex.length == 1) stringBuffer.append('0')
                stringBuffer.append(hex)
            }
            return stringBuffer.toString()
        } catch (e: NoSuchAlgorithmException) {
            e.printStackTrace()
        }
        return null
    }

    //两个数组进行相加
    fun addByte(array1: ByteArray, array2: ByteArray): ByteArray {
        val combined = ByteArray(array1.size + array2.size)
        System.arraycopy(array1, 0, combined, 0, array1.size)
        System.arraycopy(array2, 0, combined, array1.size, array2.size)
        return combined
    }

    //格式化时间yyyy-mm-dd
    fun getSimpleYYYYMMDD(str: String): String {
        if (TextUtils.isEmpty(str)) return ""

        val simpleDateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.CHINA)
        val date = simpleDateFormat.parse(str)
        return simpleDateFormat.format(date!!)

    }

    /**
     * @desc 格式化数量
     *
     * @param str 后台格式化后返回数量字符串
     * @param prefixUnit 前单位
     * @param suffixUnit 后单位
     */
    fun formatCount(str: String, prefixUnit: String = "", suffixUnit: String? = ""): CharSequence {
        val spanUtils = SpanUtils()
            .append(prefixUnit).setFontSize(12, true)
        if (str.endsWith("千")) {
            spanUtils.append(str.replace("千", "")).append("千$suffixUnit").setFontSize(12, true)
        } else if (str.endsWith("万")) {
            spanUtils.append(str.replace("万", "")).append("万$suffixUnit").setFontSize(12, true)
        } else {
            spanUtils.append(str).append("$suffixUnit").setFontSize(12, true)
        }
        return spanUtils.create()
    }

    /**
     * 格式化金额
     *
     * @param str 金额字符串
     */
    fun formatAmount(str: String): String {
        if (!isNumeric(str)) return str
        try {
            val formatter = DecimalFormat("0.00")
            val amount = str.toFloat()
            if (amount > 100000000) {
                return "${formatter.format(amount / 100000000)}亿元"
            } else if (amount > 10000) {
                return "${formatter.format(amount / 10000)}万元"
            } else {
                return "${formatter.format(amount)}元"
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
        return str
    }

    /**
     * 将字符串中的unicode字符转换为中文字符
     */
    fun convertUnicodeToCh(str: String): String {
        var newStr = str
        val pattern: Pattern = Pattern.compile("(\\\\u(\\w{4}))")
        val matcher: Matcher = pattern.matcher(newStr)

        // 迭代，将str中的所有unicode转换为正常字符
        while (matcher.find()) {
            val unicodeFull = matcher.group(1) // 匹配出的每个字的unicode，比如\u83b7
            val unicodeNum = matcher.group(2) // 匹配出每个字的数字，比如\u83b7，会匹配出u83b7

            // 将匹配出的数字按照16进制转换为10进制，转换为char类型，就是对应的正常字符了
            val singleChar = unicodeNum.toInt(16).toChar()

            // 替换原始字符串中的unicode码
            newStr = newStr.replace(unicodeFull, singleChar.toString() + "")
        }
        return newStr
    }
}

