package com.abbidot.tracker.util

import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.location.LocationManager
import android.os.Build
import android.os.Parcelable
import android.provider.Settings
import androidx.lifecycle.LifecycleCoroutineScope
import androidx.lifecycle.ViewModelProvider
import cn.jpush.android.api.JPushInterface
import com.abbidot.baselibrary.constant.EventName
import com.abbidot.baselibrary.constant.MMKVKey
import com.abbidot.baselibrary.eventbus.XEventBus
import com.abbidot.baselibrary.util.AppUtils
import com.abbidot.baselibrary.util.LogUtil
import com.abbidot.baselibrary.util.MMKVUtil
import com.abbidot.baselibrary.util.Utils
import com.abbidot.tracker.R
import com.abbidot.tracker.base.BaseActivity
import com.abbidot.tracker.base.BaseDialog
import com.abbidot.tracker.bean.BleReportDataBean
import com.abbidot.tracker.bean.MapDeviceBean
import com.abbidot.tracker.bean.UserBean
import com.abbidot.tracker.constant.ConstantInt
import com.abbidot.tracker.constant.ConstantString
import com.abbidot.tracker.constant.GetResultCallback
import com.abbidot.tracker.database.MyDatabase
import com.abbidot.tracker.dialog.CommonDialog2
import com.abbidot.tracker.dialog.PackageUpgradeDialog
import com.abbidot.tracker.ui.activity.HomeV2Activity
import com.abbidot.tracker.ui.activity.SayHelloActivity
import com.abbidot.tracker.ui.activity.device.AddNewTracker1Activity
import com.abbidot.tracker.ui.activity.pet.ShowInviteDeviceActivity
import com.abbidot.tracker.ui.activity.pet.first.FirstSetPetTypeActivity
import com.abbidot.tracker.ui.activity.subscribe.SubscriptionPlanActivity
import com.abbidot.tracker.util.bluetooth.SRBleUtil
import com.abbidot.tracker.vm.SubscriptionManageViewModel
import com.baidu.mapapi.utils.DistanceUtil
import com.clj.fastble.BleManager
import com.google.android.gms.maps.model.LatLng
import com.hjq.permissions.XXPermissions
import com.hjq.permissions.permission.PermissionLists
import com.hjq.permissions.permission.base.IPermission
import com.hjq.toast.Toaster
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.asRequestBody
import java.io.File
import java.util.Random
import kotlin.math.acos
import kotlin.math.cos
import kotlin.math.sin


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

    companion object {

        /**
         * 计算2个经纬度间距离,结果返回 米
         */
        fun measureLatLonDistance(
            startLat: Double, startLon: Double, endLat: Double, endLon: Double
        ): Double {
            val dis = if (AppUtils.isChina(AppUtils.SWITCH_MAP_TYPE)) {
                //百度地图计算两点之间的直线距离，单位：米，经纬度百度输出的GCJ02坐标，不需要转换
                DistanceUtil.getDistance(
                    com.baidu.mapapi.model.LatLng(startLat, startLon),
                    com.baidu.mapapi.model.LatLng(endLat, endLon)
                )
            } else {
                //mapbox计算2个经纬度间距离,结果返回 米
//                TurfMeasurement.distance(Point.fromLngLat(startLon, startLat),
//                        Point.fromLngLat(endLon, endLat), TurfConstants.UNIT_METERS)
                DistanceUtil.getDistance(
                    com.baidu.mapapi.model.LatLng(startLat, startLon),
                    com.baidu.mapapi.model.LatLng(endLat, endLon)
                )
            }

            return Utils.formatDecimal(dis).toDouble()
        }

        /**
         * 转换英制单位
         * @param type 0=in 1=lbs 2=mph 3=ft
         */
        fun metricConvertUnits(value: Float, type: Int, keepNum: Int = 1): Float {
            var convertValue = value
            val measureUnit = getMeasureSpUnit()
            if (measureUnit == ConstantInt.Type1) {
                when (type) {
                    ConstantInt.Type0 -> convertValue = cmToIn(value.toDouble()).toFloat()
                    ConstantInt.Type1 -> convertValue = kgToLbs(value.toDouble()).toFloat()
                    ConstantInt.Type2 -> convertValue = kmhToMph(value.toDouble()).toFloat()
                    ConstantInt.Type3 -> convertValue = mToFT(value.toDouble()).toFloat()
                    ConstantInt.Type4 -> convertValue = kmToMile(value.toDouble()).toFloat()
                }
            }

            return Utils.formatDecimal(convertValue, keepNum).toFloat()
        }

        /**
         * 转换公制单位
         * @param type 0=cm 1=kg 2=km/h 3=m
         */
        fun convertMetricUnits(value: Float, type: Int, keepNum: Int = 1): Float {
            var convertValue = value
            val measureUnit = getMeasureSpUnit()
            if (measureUnit == ConstantInt.Type1) {
                when (type) {
                    ConstantInt.Type0 -> convertValue = inToCm(value.toDouble()).toFloat()
                    ConstantInt.Type1 -> convertValue = lbsToKg(value.toDouble()).toFloat()
                }
            }

            return Utils.formatDecimal(convertValue, keepNum).toFloat()
        }


        /**
         * 获取单位
         */
        fun getMeasureSpUnit() = MMKVUtil.getInt(MMKVKey.MeasureUnit, 1)

        /**
         * 获取单位名称
         */
        fun getMeasureUnitName(context: Context): String {
            return if (getMeasureSpUnit() == ConstantInt.Type1) context.getString(R.string.txt_imperial)
            else context.getString(R.string.txt_metric)
        }

        /**
         * km/h转换mph
         */
        private fun kmhToMph(value: Double): Double {
            return value / 0.6213712
        }

        private fun mToFT(value: Double): Double {
            return value * 3.2808399
        }

        private fun kmToMile(value: Double): Double {
            return value * 0.621
        }

        private fun cmToIn(value: Double): Double {
            return value * 0.3937
        }

        fun inToCm(value: Double): Double {
            return value * 2.54
        }

        private fun kgToLbs(value: Double): Double {
            return value * 2.2065
        }

        fun lbsToKg(value: Double): Double {
            return value * 0.4532
        }

        /**
         * 获取宠物的体重身高范围
         * @param type 是身高还是体重 0身高 1体重
         * @param valueType 最大值还是最小值 0大 1小
         */
        fun getPetHeightAndWeightRangeValue(petType: Int, type: Int, valueType: Int): Int {
            var value = 0
            val measureUnit = getMeasureSpUnit()
            if (petType == ConstantInt.CatPetType) {
                //身高
                if (type == ConstantInt.HeightType) {
                    if (valueType == ConstantInt.MaxType) {
                        if (measureUnit == ConstantInt.Type1) value = 25
                        else if (measureUnit == ConstantInt.Type2) value = 65
                    } else if (valueType == ConstantInt.MinType) {
                        if (measureUnit == ConstantInt.Type1) value = 3
                        else if (measureUnit == ConstantInt.Type2) value = 7
                    }
                } else if (type == ConstantInt.WeightType) {
                    //1体重
                    if (valueType == ConstantInt.MaxType) {
                        if (measureUnit == ConstantInt.Type1) value = 30
                        else if (measureUnit == ConstantInt.Type2) value = 13
                    } else if (valueType == ConstantInt.MinType) {
                        if (measureUnit == ConstantInt.Type1) value = 1
                        else if (measureUnit == ConstantInt.Type2) value = 0
                    }
                }
            } else if (petType == ConstantInt.DogPetType) {
                //身高
                if (type == ConstantInt.HeightType) {
                    if (valueType == ConstantInt.MaxType) {
                        if (measureUnit == ConstantInt.Type1) value = 50
                        else if (measureUnit == ConstantInt.Type2) value = 130
                    } else if (valueType == ConstantInt.MinType) {
                        if (measureUnit == ConstantInt.Type1) value = 3
                        else if (measureUnit == ConstantInt.Type2) value = 7
                    }
                } else if (type == ConstantInt.WeightType) {
                    //1体重
                    if (valueType == ConstantInt.MaxType) {
                        if (measureUnit == ConstantInt.Type1) value = 200
                        else if (measureUnit == ConstantInt.Type2) value = 90
                    } else if (valueType == ConstantInt.MinType) {
                        if (measureUnit == ConstantInt.Type1) value = 1
                        else if (measureUnit == ConstantInt.Type2) value = 0
                    }
                }
            } else {
                //身高
                if (type == ConstantInt.HeightType) {
                    if (valueType == ConstantInt.MaxType) {
                        if (measureUnit == ConstantInt.Type1) value = 20
                        else if (measureUnit == ConstantInt.Type2) value = 50
                    } else if (valueType == ConstantInt.MinType) {
                        if (measureUnit == ConstantInt.Type1) value = 1
                        else if (measureUnit == ConstantInt.Type2) value = 1
                    }
                } else if (type == ConstantInt.WeightType) {
                    //1体重
                    if (valueType == ConstantInt.MaxType) {
                        if (measureUnit == ConstantInt.Type1) value = 45
                        else if (measureUnit == ConstantInt.Type2) value = 20
                    } else if (valueType == ConstantInt.MinType) {
                        if (measureUnit == ConstantInt.Type1) value = 1
                        else if (measureUnit == ConstantInt.Type2) value = 1
                    }
                }
            }
            return value
        }

        /**
         * 获取宠物的体重身高默认值
         * @param type 是身高还是体重 0身高 1体重
         */
        fun getPetHeightAndWeightDefaultValue(petType: Int, type: Int): Int {
            var value = 0
            val measureUnit = getMeasureSpUnit()
            if (petType == ConstantInt.CatPetType) {
                //身高
                if (type == ConstantInt.HeightType) {
                    if (measureUnit == ConstantInt.Type1) value = 10
                    else if (measureUnit == ConstantInt.Type2) value = 25
                } else if (type == ConstantInt.WeightType) {
                    //1体重
                    if (measureUnit == ConstantInt.Type1) value = 9
                    else if (measureUnit == ConstantInt.Type2) value = 4
                }
            } else if (petType == ConstantInt.DogPetType) {
                //身高
                if (type == ConstantInt.HeightType) {
                    if (measureUnit == ConstantInt.Type1) value = 20
                    else if (measureUnit == ConstantInt.Type2) value = 50
                } else if (type == ConstantInt.WeightType) {
                    //1体重
                    if (measureUnit == ConstantInt.Type1) value = 22
                    else if (measureUnit == ConstantInt.Type2) value = 10
                }
            } else {
                //身高
                if (type == ConstantInt.HeightType) {
                    if (measureUnit == ConstantInt.Type1) value = 1
                    else if (measureUnit == ConstantInt.Type2) value = 1
                } else if (type == ConstantInt.WeightType) {
                    //1体重
                    if (measureUnit == ConstantInt.Type1) value = 1
                    else if (measureUnit == ConstantInt.Type2) value = 1
                }
            }
            return value
        }

        /**
         * 获取单位
         * @param type 0=cm 1=kg 2=km/h 3=m 4=km
         */
        fun getMetricUnits(context: Context, type: Int): String {
            var unit = ""
            val measureUnit = getMeasureSpUnit()
            when (type) {
                ConstantInt.Type0 -> {
                    if (measureUnit == ConstantInt.Type2) unit = context.getString(R.string.txt_cm)
                    else if (measureUnit == ConstantInt.Type1) unit =
                        context.getString(R.string.txt_in)
                }

                ConstantInt.Type1 -> {
                    if (measureUnit == ConstantInt.Type2) unit = context.getString(R.string.txt_kg)
                    else if (measureUnit == ConstantInt.Type1) unit =
                        context.getString(R.string.txt_lb)
                }

                ConstantInt.Type2 -> {
                    if (measureUnit == ConstantInt.Type2) unit =
                        context.getString(R.string.txt_km_h)
                    else if (measureUnit == ConstantInt.Type1) unit =
                        context.getString(R.string.txt_mph)
                }

                ConstantInt.Type3 -> {
                    if (measureUnit == ConstantInt.Type2) unit = context.getString(R.string.txt_m)
                    else if (measureUnit == ConstantInt.Type1) unit =
                        context.getString(R.string.txt_ft)
                }

                ConstantInt.Type4 -> {
                    if (measureUnit == ConstantInt.Type2) unit = context.getString(R.string.txt_km)
                    else if (measureUnit == ConstantInt.Type1) unit =
                        context.getString(R.string.txt_distance_unit)
                }
            }
            return unit
        }

        /**
         * 计算两点之间距离
         * @param start
         * @param end
         * @return 米
         */
        fun getDistance(start: LatLng, end: LatLng): Double {
            val lat1 = Math.PI / 180 * start.latitude
            val lat2 = Math.PI / 180 * end.latitude
            val lon1 = Math.PI / 180 * start.longitude
            val lon2 = Math.PI / 180 * end.longitude
            //地球半径
            val r = 6371.393
            //两点间距离 km，如果想要米的话，结果*1000就可以了
            val d = acos(sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(lon2 - lon1)) * r
            return d * 1000
        }

        /**
         * 检查权限并获取权限
         */
        fun checkPermissions(
            activity: BaseActivity<*>,
            requestPermissionCallback: RequestPermissionCallback,
            permissionTag: String,
            vararg permissions: IPermission
        ) {
            XXPermissions.with(activity).permissions(permissions).request { _, deniedList ->
                val allGranted = deniedList.isEmpty()
                if (allGranted) {
                    LogUtil.e("获取${permissionTag}权限成功")
                    requestPermissionCallback.onRequestPermissionSuccess()
                } else {
                    val doNotAskAgain =
                        XXPermissions.isDoNotAskAgainPermissions(activity, deniedList)
                    if (doNotAskAgain) {
                        LogUtil.e("被永久拒绝授权，请手动授予定位权限")
                        // 如果是被永久拒绝就跳转到应用权限系统设置页面
                        XXPermissions.startPermissionActivity(activity, deniedList)
                    } else {
                        LogUtil.e("获取部分权限成功，但部分权限未正常授予")
                        requestPermissionCallback.onRequestPermissionFail()
                    }
                }

                //                        object : OnPermissionCallback {
                //                            override fun onGranted(
                //                                permissions: MutableList<IPermission>, all: Boolean
                //                            ) {
                //                                if (all) {
                //
                //                                } else {
                //                                    LogUtil.e("获取部分权限成功，但部分权限未正常授予")
                //                                    requestPermissionCallback.onRequestPermissionFail()
                //                                }
                //                            }
                //
                //                            override fun onDenied(
                //                                permissions: MutableList<IPermission>, doNotAskAgain: Boolean
                //                            ) {
                //                                if (doNotAskAgain) {
                //                                    LogUtil.e("被永久拒绝授权，请手动授予定位权限")
                //                                    // 如果是被永久拒绝就跳转到应用权限系统设置页面
                //                                    XXPermissions.startPermissionActivity(context, permissions)
                //                                } else {
                //                                    LogUtil.e("获取${permissionTag}权限失败")
                //                                    requestPermissionCallback.onRequestPermissionFail()
                //                                }
                //                            }
                //                        }
            }
        }


        /**
         * 上传调用的方法 ,传入本地文件路径,协程挂载方法
         */
        fun uploadFile(pathImg: String, fileType: String = "image/png"): MultipartBody.Part {
            val file = File(pathImg)
            val fileRQ = file.asRequestBody(fileType.toMediaTypeOrNull())
            return MultipartBody.Part.createFormData("file", file.name, fileRQ)
        }


//    var pattern: String {
//        switch self {
//            case .visa: return "^4[0-9]{12}(?:[0-9]{3})?$"
//            case .visaElectron: return "^(4026|417500|4508|4844|491(3|7))"
//            case .mastercard: return "^5[1-5][0-9]{14}$"
//            case .maestro: return "^(5018|5020|5038|6304|6759|676[1-3])"
//            case .americanExpress: return "^3[47][0-9]{13}$"
//            case .dinnersClub: return "^3(?:0[0-5]|[68][0-9])[0-9]{11}$"
//            case .discovery: return "^6(?:011|5[0-9]{2})[0-9]{12}$"
//            case .jcb: return "^(?:2131|1800|35\\d{3})\\d{11}$"
//            case .unknown:
//            return ""
//        }
//    }
        /**
         * 合法的信用卡类型
         */
        fun getCreditCardType(cardNumber: String): Int {
            //visa
            var regex = "^4[0-9]{12}(?:[0-9]{3})?$"
            if (Utils.isRegularExpression(cardNumber, regex)) {
                return R.drawable.ico_lay_visa_card
            }
            //visaElectron
            regex = "^(4026|417500|4508|4844|491(3|7))"
            if (Utils.isRegularExpression(cardNumber, regex)) {
                return R.drawable.ico_lay_visa_card
            }
            //mastercard
            regex = "^5[1-5][0-9]{14}$"
            if (Utils.isRegularExpression(cardNumber, regex)) {
                return R.drawable.ico_lay_mastercard
            }
            //maestro
            regex = "^(5018|5020|5038|6304|6759|676[1-3])"
            if (Utils.isRegularExpression(cardNumber, regex)) {
                return R.drawable.ico_lay_maestrocard
            }
            //americanExpress
            regex = "^3[47][0-9]{13}$"
            if (Utils.isRegularExpression(cardNumber, regex)) {
                return R.drawable.ico_lay_amexcard
            }
            //dinnersClub
            regex = "^3(?:0[0-5]|[68][0-9])[0-9]{11}$"
            if (Utils.isRegularExpression(cardNumber, regex)) {
                return R.drawable.ico_lay_newcard
            }
            //discovery
            regex = "^6(?:011|5[0-9]{2})[0-9]{12}$"
            if (Utils.isRegularExpression(cardNumber, regex)) {
                return R.drawable.ico_lay_discovercard
            }
            //jcb
            regex = "^(?:2131|1800|35\\d{3})\\d{11}$"
            if (Utils.isRegularExpression(cardNumber, regex)) {
                return R.drawable.ico_lay_newcard
            }
            //unknown类型卡片,不合法
            return 0
        }

        private const val CARD_NUMBER_FORMAT = "XXXX XXXX XXXX XXXX"
        private const val CARD_NUMBER_FORMAT_AMEX = "XXXX XXXXXX XXXXX"

        /**
         * 格式化卡号
         */
        fun formatCardNumber(cardNumber: String): String {
            val unformattedText = cardNumber.replace(" ", "")
            val sbFormattedNumber = StringBuilder()
            val format = if (cardNumber.length == 15) {
                CARD_NUMBER_FORMAT_AMEX
            } else {
                CARD_NUMBER_FORMAT
            }
            var j = 0
            for (i in format.indices) {
                if (j > unformattedText.length - 1) {
                    break
                }
                if (format[i] == 'X') {
                    sbFormattedNumber.append(unformattedText[j++])
                } else {
                    sbFormattedNumber.append(format[i])
                }
            }
            return sbFormattedNumber.toString()
        }

        /**
         * getParcelable 不同版本适配
         */
        fun <T> getParcelableAdaptive(intent: Intent, key: String, clazz: Class<T>): T? {
            return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                intent.extras?.getParcelable(key, clazz)
            } else {
                intent.extras?.getParcelable(key)
            }
        }

        /**
         * getParcelableArrayList 不同版本适配
         */
        fun <T : Parcelable?> getParcelableArrayListAdaptive(
            intent: Intent, key: String, clazz: Class<out T>
        ): ArrayList<T>? {
            return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                intent.extras?.getParcelableArrayList(key, clazz)
            } else {
                intent.extras?.getParcelableArrayList(key)
            }
        }

        /**
         * 获取AndroidManifest.xml中的meta-data值
         */
        fun getMetadata(context: Context, key: String): String {
            val app = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
                context.packageManager.getApplicationInfo(
                    context.packageName,
                    PackageManager.ApplicationInfoFlags.of(PackageManager.GET_META_DATA.toLong())
                )
            } else {
                context.packageManager.getApplicationInfo(
                    context.packageName, PackageManager.GET_META_DATA
                )
            }
            return app.metaData.getString(key) ?: ""
        }

        /**
         * 处理登录成功后的数据
         */
        fun dealLoginSuccessData(context: Context, userBean: UserBean) {
            LogUtil.e("处理登录成功后的数据:$userBean")
            //通知相关页面关闭
            XEventBus.post(EventName.FinishActivity)
            userBean.apply {
                MMKVUtil.putString(MMKVKey.UserId, userId)
                MMKVUtil.putString(MMKVKey.Email, email)
                MMKVUtil.putString(MMKVKey.Token, token)
                MMKVUtil.putString(MMKVKey.UserName, userName)
                MMKVUtil.putInt(MMKVKey.MeasureUnit, measurementUnitType)
                MMKVUtil.putInt(MMKVKey.isBindDevice, isBindDevice)
                MMKVUtil.putInt(MMKVKey.isBindPet, isBindPet)
                MMKVUtil.putInt(MMKVKey.isExistNewInvite, isExistNewInvite)
                MMKVUtil.putBoolean(MMKVKey.FirstOpen, false)
                val rand = Random()
                //极光推送设置别名
                JPushInterface.setAlias(context, rand.nextInt(1000), userId)
            }
        }

        /**
         * 退出登录
         */
        fun logOut(activity: BaseActivity<*>, lifecycleScope: LifecycleCoroutineScope) {
            val rand = Random()
            //此接口只能清除当前设备与目标 alias 的绑定关系
            // 想清除目标 alias 与所有设备的绑定关系,请想清除目标 alias 与所有设备的绑定关系
            // ,调用服务器接口https://docs.jiguang.cn/jpush/server/push/rest_api_v3_device
            JPushInterface.deleteAlias(activity, rand.nextInt(1000))
            XEventBus.post(EventName.LogOut)
            SRBleUtil.instance.cancelBleScan("已经在扫描蓝牙，退出登录取消扫描")
            BleManager.getInstance().disconnectAllDevice()
            lifecycleScope.launch {
                val email = MMKVUtil.getString(MMKVKey.Email)
                MMKVUtil.clearAll()
                //保存最后一次登录的邮箱
                MMKVUtil.putString(MMKVKey.Email, email)
                withContext(Dispatchers.IO) {
                    MyDatabase.deviceDao().deleteAll(MyDatabase.DEVICE_TABLE)
                    MyDatabase.creditCardDao().deleteAll(MyDatabase.CREDIT_CARD_TABLE)
                }
                activity.startActivityFinish(Intent(activity, SayHelloActivity::class.java))
            }
        }

        /**
         * 检测首次是否绑定设备和宠物
         */
        fun checkBindDeviceAndPetGoActivity(context: Context): Intent {
            val intent = Intent()
            val isExistNewInvite = MMKVUtil.getInt(MMKVKey.isExistNewInvite)
            if (isExistNewInvite != ConstantInt.NoShare) {
                intent.setClass(context, ShowInviteDeviceActivity::class.java)
                return intent
            }
            val isBindDevice = MMKVUtil.getInt(MMKVKey.isBindDevice)
            val isBindPet = MMKVUtil.getInt(MMKVKey.isBindPet)
            if (isBindDevice == ConstantInt.NoBind) {
                intent.setClass(context, AddNewTracker1Activity::class.java)
                intent.putExtra(ConstantString.isFirstBind, true)
            } else if (isBindPet == ConstantInt.NoBind) {
                intent.setClass(context, FirstSetPetTypeActivity::class.java)
                intent.putExtra(ConstantString.isFirstBind, true)
            } else {
                intent.setClass(context, HomeV2Activity::class.java)
            }
            return intent
        }

        /**
         * 检测是否有必要权限和开关
         */
        fun checkNeedPermissionsEnabled(context: Context): Boolean {
            val locationManager =
                context.getSystemService(Context.LOCATION_SERVICE) as LocationManager
            var hasPermissions = true
            //检测蓝牙权限和蓝牙开关
            if (!XXPermissions.isGrantedPermissions(
                    context, mutableListOf(
                        PermissionLists.getBluetoothScanPermission(),
                        PermissionLists.getBluetoothConnectPermission()
                    )
                ) || !SRBleUtil.instance.isBleEnable(context)
            ) {
                hasPermissions = false
            }
            if (hasPermissions) {
                //检查定位权限
                if (!XXPermissions.isGrantedPermissions(
                        context, mutableListOf(
                            PermissionLists.getAccessFineLocationPermission(),
                            PermissionLists.getAccessCoarseLocationPermission()
                        )
                    ) || !locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)
                ) {
                    hasPermissions = false
                }
            }
            if (hasPermissions) {
                //检测通知权限
                if (!XXPermissions.isGrantedPermissions(
                        context, mutableListOf(
                            PermissionLists.getPostNotificationsPermission(),
                            PermissionLists.getNotificationServicePermission()
                        )
                    )
                ) {
                    hasPermissions = false
                }
            }
            return hasPermissions
        }

        /**
         * 检查蓝牙权限和开关
         */
        fun checkBluetoothPermissionsEnabled(
            activity: BaseActivity<*>,
            successAuthorize: () -> Unit,
            isShowToast: Boolean = true,
            isCheckBleOpen: Boolean = true
        ) {
            checkPermissions(
                activity,
                object : RequestPermissionCallback {
                    override fun onRequestPermissionSuccess() {
                        //判断蓝牙是否打开
                        if (isCheckBleOpen && !SRBleUtil.instance.isBleEnable(activity)) {
                            SRBleUtil.instance.openBluetooth(activity)
                            return
                        }
                        successAuthorize()
                    }

                    override fun onRequestPermissionFail() {
                        if (isShowToast) Toaster.show(R.string.txt_permissions_fail_tips)
                    }
                },
                "checkBluetoothPermissionsEnabled,定位和蓝牙权限,Android12蓝牙扫描和连接权限",
                PermissionLists.getBluetoothScanPermission(),
                PermissionLists.getBluetoothConnectPermission(),
                PermissionLists.getAccessFineLocationPermission(),
                PermissionLists.getAccessCoarseLocationPermission()
            )
        }

        /**
         * 检查定位权限和GPS开关
         */
        fun checkLocationPermissionsGpsEnabled(
            activity: BaseActivity<*>, successAuthorize: () -> Unit, isShowToast: Boolean = true
        ) {
            val locationManager =
                activity.getSystemService(Context.LOCATION_SERVICE) as LocationManager
            checkPermissions(
                activity,
                object : RequestPermissionCallback {
                    override fun onRequestPermissionSuccess() {
                        //判断GPS是否打开
                        if (!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
                            val intent = Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)
                            activity.startActivity(intent)
                            return
                        }
                        successAuthorize()
                    }

                    override fun onRequestPermissionFail() {
                        if (isShowToast) Toaster.show(R.string.txt_permissions_fail_tips)
                    }
                },
                "checkLocationPermissionsGpsEnabled,定位权限",
                PermissionLists.getAccessFineLocationPermission(),
                PermissionLists.getAccessCoarseLocationPermission()
            )
        }

        /**
         * 套餐过期提示充值
         */
        fun checkPackageExpired(activity: BaseActivity<*>, deviceId: String) {
            LogUtil.e("套餐过期deviceId=$deviceId")
            CommonDialog2(
                activity,
                activity.getString(R.string.txt_subscription_expired),
                activity.getString(R.string.txt_card_recharge),
                object : BaseDialog.OnDialogOkListener {
                    override fun onOkClick(dialog: BaseDialog<*>) {
                        ViewModelProvider(activity)[SubscriptionManageViewModel::class.java].apply {
                            mSubscriptionsOrderLiveData.observe(activity) {
                                activity.dealRequestResult(it, object : GetResultCallback {
                                    override fun onResult(any: Any) {
                                        it.getOrNull()?.let { list ->
                                            for (l in list) {
                                                if (l.deviceId == deviceId) {
                                                    Intent(
                                                        activity,
                                                        SubscriptionPlanActivity::class.java
                                                    ).let { i ->
                                                        i.putExtra(ConstantString.LkSetMeal, l)
                                                        i.putExtra(
                                                            ConstantString.RechargeType,
                                                            ConstantInt.Type2
                                                        )
                                                        activity.startActivity(i)
                                                    }
                                                    break
                                                }
                                            }
                                        }
                                    }
                                })
                                mSubscriptionsOrderLiveData.removeObservers(activity)
                            }
                            getSubscriptionsOrder()
                        }
                    }
                }).show()
        }

        /**
         * 基础套餐权限控制
         */
        fun checkPackageLimit(activity: BaseActivity<*>, deviceId: String): Boolean {
            LogUtil.e("基础套餐权限控制deviceId=$deviceId")
            //先判断有没有过期
            val availableOrder = MMKVUtil.getInt(MMKVKey.AvailableOrder, 1)
            if (availableOrder == ConstantInt.Type0) {
                checkPackageExpired(activity, deviceId)
                return true
            }
            val mealType = MMKVUtil.getInt(MMKVKey.MealType)
            if (ConstantInt.BasicPackage == mealType) {
                PackageUpgradeDialog(activity, deviceId).show()
                return true
            }
            return false
        }

        /**
         * BleReportDataBean数据转换MapDeviceBean数据
         */
        fun bleReportDataToMapDevice(
            mapDeviceBean: MapDeviceBean, bleReportData: BleReportDataBean
        ) {
            bleReportData.apply {
                mapDeviceBean.let {
                    it.inSafeZone = inSafeZone
                    it.gpsSignal = gpsSignal
                    it.batteryLevel = batteryLevel
                    it.ledSwitch = ledSwitch
                    it.gnssInterval = gnssInterval
                    it.liveFlag = liveFlag
                    it.updateTime = updateTime
                    it.latLonUpdateTime = latLonUpdateTime
                    it.lteSignal = lteSignal
                    it.powerSwitch = powerSwitch
                    it.inNoGoZone = inNoGoZone
                    it.inWifiZone = inWifiZone
                    it.ledRedValue = ledRedValue
                    it.ledGreenValue = ledGreenValue
                    it.ledBlueValue = ledBlueValue
                }
            }
        }

        /**
         * 是否是超时上报了,按用户所设的上报间隔的2倍计算时长
         *
         * @param updateTime 10位时间戳
         */
        fun isTimeoutReport(updateTime: Long, gnssInterval: Int): Boolean {
            val now = System.currentTimeMillis() / 1000
            val updateSecond = now - updateTime
            return updateSecond > gnssInterval * 2
        }

        /***
         * 是否限制时间执行
         */
        fun isTimeLimit(cTime: Long, limitSecond: Int = 1): Boolean {
            return System.currentTimeMillis() - cTime < limitSecond * 1000
        }

        /**
         * 获取保存的地图模式 地图类型，0标准 1卫星地图
         */
        fun getMapTypeSp() = MMKVUtil.getInt(MMKVKey.MapType, ConstantInt.Type0)
        fun getShowFenceSp() = MMKVUtil.getBoolean(MMKVKey.ShowFence, true)

        fun getDeviceTypeImage(type: Int): Int {
            return when (type) {
                ConstantInt.Type2 -> R.drawable.icon_tracker_g40
                else -> R.drawable.icon_tracker_device_small
            }
        }

        /**
         * 获取LED是否可以控制
         */
        fun getLedControlState(mac: String, mapDeviceBean: MapDeviceBean): Boolean {
            var isControl: Boolean
            mapDeviceBean.apply {
                //是否超时上报
                val isTimeoutReport = isTimeoutReport(updateTime, gnssInterval)
                isControl = if (powerSwitch == ConstantInt.Type3) false
                else if (SRBleUtil.instance.isMacConnect(mac)) true
                else if (powerSwitch == ConstantInt.Type0 || powerSwitch == ConstantInt.Type2 || inWifiZone == ConstantInt.Type1 || isTimeoutReport) false
                else true
            }
            return isControl
        }

        /**
         * 复制内容到剪贴板
         */
        fun copyToClipboard(context: Context, text: String) {
            val clipboard = context.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
            val clip = ClipData.newPlainText("text", text)
            clipboard.setPrimaryClip(clip)
        }


        /**
         * 限制16个字母或8个中文
         * 截断到最大16单位
         * @param limitLetterLength 限制字母的个数
         */
        fun String.limitLetterChinese(limitLetterLength: Int): String {
            val sb = StringBuilder()
            for (c in this) {
                val temp = sb.toString() + c
                if (temp.calcLengthUnit() > limitLetterLength) break
                sb.append(c)
            }
            return sb.toString()
        }

        private fun CharSequence.calcLengthUnit(): Int {
            var count = 0
            for (c in this) {
                count += if (c.isChinese()) 2 else 1
            }
            return count
        }

        // 判断是否是中文
        private fun Char.isChinese(): Boolean {
            return this.code in 0x4E00..0x9FA5
        }


    }

    /**
     *请求获取权限成功失败回调
     */
    interface RequestPermissionCallback {
        fun onRequestPermissionSuccess()
        fun onRequestPermissionFail() {}
    }
}