package com.quyunshuo.module.home.utils

import android.content.Context
import android.media.AudioManager
import android.util.Log
import com.google.gson.Gson
import com.hboxs.serialport.plc.message.MqttMessageBean
import com.hboxs.serialport.plc.thread.ThreadSettingParam
import com.hboxs.serialport.sbc.SBCHeartbeat
import com.hboxs.serialport.sbc.VBoxMessage
import com.hboxs.serialport.sbc.frame.VboxCommand
import com.qiniu.android.http.ResponseInfo
import com.qiniu.android.storage.FileRecorder
import com.qiniu.android.storage.KeyGenerator
import com.qiniu.android.storage.UpCancellationSignal
import com.qiniu.android.storage.UpCompletionHandler
import com.qiniu.android.storage.UploadManager
import com.qiniu.android.storage.UploadOptions
import com.quyunshuo.androidbaseframemvvm.base.BaseApplication
import com.quyunshuo.androidbaseframemvvm.base.utils.JsonUtils
import com.quyunshuo.androidbaseframemvvm.base.utils.SpUtils
import com.quyunshuo.androidbaseframemvvm.base.utils.commons.StringUtils
import com.quyunshuo.androidbaseframemvvm.common.bean.PaySucessBean
import com.quyunshuo.androidbaseframemvvm.common.constant.Heartbeat
import com.quyunshuo.androidbaseframemvvm.common.constant.MMKVName
import com.quyunshuo.androidbaseframemvvm.common.constant.MqName
import com.quyunshuo.androidbaseframemvvm.common.constant.event.ApiMessageEvent
import com.quyunshuo.androidbaseframemvvm.common.enums.AlarmClockEnum
import com.quyunshuo.androidbaseframemvvm.common.enums.ConnectStateEnum
import com.quyunshuo.androidbaseframemvvm.common.util.AlarmManagerUtil
import com.quyunshuo.androidbaseframemvvm.common.util.ToastUtil
import com.quyunshuo.androidbaseframemvvm.common.util.UiUtil
import com.quyunshuo.module.home.R
import com.quyunshuo.module.home.bean.AlarmClockBean
import com.quyunshuo.module.home.fragment.fragment.pay.PaySuccessBean
import com.quyunshuo.module.home.getui.BaseBean
import com.quyunshuo.module.home.getui.MqttBaseBean
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import org.json.JSONObject
import java.io.File
import java.io.IOException
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Calendar
import javax.inject.Inject


class RemotePushUtil @Inject constructor() {
    private val TAG = "RemotePushUtil"

    @Inject
    lateinit var threadSettingParam: ThreadSettingParam

    init {
        registerToEventBus()

    }


    // 手动注册方法
    fun registerToEventBus() {
        EventBus.getDefault().register(this)

    }

    // 手动注销方法
    fun unregisterFromEventBus() {
        EventBus.getDefault().unregister(this)
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun event(messageEvent: VBoxMessage) {

        disposeData(messageEvent)
    }

    /*
        @Subscribe(threadMode = ThreadMode.MAIN)
        fun event(messageEvent: Message) {
            when (messageEvent.type) {
                Message.Type.ack -> {
                    ack(messageEvent)
                }

                Message.Type.response -> {}
                Message.Type.connected -> {}
                Message.Type.disconnected -> {}
                Message.Type.sendError -> {}
                Message.Type.nak -> {}
            }
        }*/
    fun disposeData(messageEvent: VBoxMessage) {
        when (messageEvent.cmd) {
            VboxCommand.CMD_HEARTBEAT -> {
                Log.d("settingview", "HEARTBEAT:" + messageEvent.data)
                if (SBCHeartbeat.devCode.startsWith("01")) {
                    //   _powerOncomplete.value = true
                    threadSettingParam.stopSetM3()
                } else if (SBCHeartbeat.devCode.startsWith("02")) {
                    //   _powerOncomplete.value = true
                    threadSettingParam.stopSetM3()

                }
            }

            else -> {}
        }


    }

    /* private fun ack(messageEvent: Message) {
         val name = messageEvent.name
         Log.d(TAG, "ack: " + name)
         when (name) {
             PlcSettingAddressEnum.M3.address -> {
                 threadSettingParam.stopSetM3()
                 CoroutineScope(Dispatchers.IO).launch {
                     delay(3000)
                     threadSettingParam.startRstM3()
                 }
             }

             PlcSettingAddressEnum.RM3.address -> {
                 threadSettingParam.stopRstM3()
             }

             else -> {}
         }
     }
 */
    fun getMqttMessage(msg: String) {
        Log.d(TAG, "MqttMessage:" + msg)
        if (StringUtils.isNullOrEmpty(msg)){
            return
        }
        var kindStr = JsonUtils.getValue(msg, "dataContent", String::class.java)
        var DataBean = JsonUtils.getBean(kindStr, MqttBaseBean::class.java)
        var msgId = JsonUtils.getValue(msg, "msgId", String::class.java)
        Log.d(TAG, "11111111111111:" + JsonUtils.getJSONString(DataBean))
        val kind: String = DataBean.kind
        when (kind) {
            MqName.log -> {
                uploadLog(DataBean)
            }
        }
    }

    fun getMessage(msg: android.os.Message) {
        val message = msg.data.getString("msg")
        Log.d(TAG, "11111111111111:" + message)
        if (StringUtils.isNullOrEmpty(message)){
            return
        }

        var kindStr = JsonUtils.getValue(message, "kind", String::class.java)
        Log.d(TAG, "11111111111111:" + kindStr)

        val gson = Gson()
        val baseBean: BaseBean = gson.fromJson(message, BaseBean::class.java)

        Log.d(TAG, baseBean.kind + ":BJQXUserlogin getMessage: " + message + baseBean)
        // JsonUtils.getObjectByKey(message, "kind", "")
        val kind: String = baseBean.kind
        when (kind) {
            MqName.UPDATE_PRODUCTS_SHOW -> {}
            MqName.PAY_SUCCESS -> {
                paySuccess(gson, baseBean, kind)
            }

            MqName.BLOCK -> {
                devBlock(kind, baseBean.kind_data)
            }


            MqName.IS_SLEEP -> {
                devSleep(kind, baseBean.kind_data)
            }

            MqName.ADMIN_PWD -> {
                SpUtils.putString(kind, baseBean.kind_data)
            }

            MqName.GUEST_PWD -> {
                SpUtils.putString(kind, baseBean.kind_data)

            }

            MqName.PHONE -> {
                savePhone(baseBean.kind_data)
            }

            MqName.VOLUME -> {
                setVolume(baseBean.kind_data)
            }

            MqName.UPDATE_LOGO -> {
                SpUtils.putString(kind, baseBean.kind_data)
            }

            MqName.RESTART_ANDROID -> {
                restartAndroid()
            }

            MqName.STATUS_TYPE -> {
                statusType(gson, baseBean, kind)
            }

            MqName.TUO_JI -> {
                deviceTuoji(kind)

            }

            MqName.ALARM_CLOCK -> {
                alarmClock(gson, baseBean)
            }

            MqName.EQESTATUS -> {
                openOrCloseDev(baseBean)
            }

            MqName.PUSHTIMERULE -> {
                pushtimeRule(baseBean, kind)
            }

            MqName.log -> {
                //远程上传日志文件
                uploadLogApi(baseBean.kind_data)
            }

            MqName.onoffstatus -> {
                EventBus.getDefault().post(MqttMessageBean("onoffstatus", "onoffstatus", ""))

            }

            MqName.DOSUGAR -> {
                EventBus.getDefault()
                    .post(MqttMessageBean(MqName.DOSUGAR, MqName.DOSUGAR, baseBean.kind_data))

            }

            else -> {}
        }
    }


    /**
     * 保存管理员密码
     *
     * @param gson
     * @param baseBean
     * @param type     管理员类型
     */
    private fun savePas(gson: Gson, baseBean: BaseBean, type: String) {
        val json: String = baseBean.kind_data
        val s = gson.fromJson(json, String::class.java)
        SpUtils.put(type, s)
    }

    fun uploadLog(mqtt: MqttBaseBean) {
        try {
            var filePath = "/storage/emulated/0/logdata/${mqtt.kind_data}.txt"
            val uploadManager = UploadManager()
            val uploadFile: File = File(filePath)
            val uploadFileKey: String =  mqtt.key
                .trim()
            val options = UploadOptions(null, null, false,
                { key, percent ->
                }, { // 当需要取消时，此处返回 true，SDK 内部会多次检查返回值，当返回值为 true 时会取消上传操作
                    false
                })
            uploadManager.put(uploadFile,uploadFileKey,mqtt.token,object : UpCompletionHandler {
                override fun complete(key: String?, info: ResponseInfo?, response: JSONObject?) {
                    Log.d(TAG, "complete：" +  JsonUtils.getJSONString(info))
                    if (info != null && info.isOK()) {
                        // 上传成功
                    } else {
                        Log.d(TAG, "失败：" +  JsonUtils.getJSONString(info))
                        // 上传失败
                    }
                }

            },options)
        } catch (e: IOException) {
            Log.e("QiniuLab", e.message!!)
        }
    }




    /**
     * 远程上传日志文件
     *
     * @param kindData
     */
    fun uploadLogApi(kindData: String) {

        /* val configuration: Configuration = Builder()
             .zone(zone) // 配置上传区域
             .putThreshold(4 * 1024 * 1024) // 分片上传阈值：4MB，大于 4MB 采用分片上传，小于 4MB 采用表单上传
             .useConcurrentResumeUpload(true) // 开启分片上传
             .recorder(recorder) // 文件分片上传时断点续传信息保存，表单上传此配置无效
             .resumeUploadVersion(Configuration.RESUME_UPLOAD_VERSION_V2) // 使用分片 V2
             .build()*/


        /*   Thread {
               val file = File("/storage/emulated/0/logdata/$kindData.txt")

               if (file.exists()) {
                   Log.e("backinfo", "文件存在")
                   if (file.isFile) {
                       var input: DataInputStream? = null
                       var out: OutputStream? = null
                       var conn: HttpURLConnection? = null
                       var ins: InputStream? = null
                       var outStream: ByteArrayOutputStream? = null
                       try {
                           val url =
                               URL("https://app.sunzee.com.cn/" + "/api/app_equipment/index/sendLog.htm?fileName=" + kindData)

                           conn = url.openConnection() as HttpURLConnection
                           // 发送POST请求必须设置如下两行
                           conn!!.doOutput = true
                           conn!!.useCaches = false
                           conn!!.requestMethod = "POST"
                           conn!!.setRequestProperty("Content-Type", "text/html")
                           conn!!.setRequestProperty("Cache-Control", "no-cache")
                           conn!!.setRequestProperty("Charsert", "UTF-8")
                           conn!!.connect()
                           conn!!.connectTimeout = 10000
                           out = conn!!.outputStream
                           input = DataInputStream(FileInputStream(file))

                           var bytes = 0
                           val buffer = ByteArray(1024)
                           while ((input.read(buffer).also { bytes = it }) != -1) {
                               out.write(buffer, 0, bytes)
                           }

                           out.flush()

                           // 返回流
                           if (conn!!.responseCode == HttpURLConnection.HTTP_OK) {
                               ins = conn!!.inputStream
                               outStream = ByteArrayOutputStream()
                               val data = ByteArray(1024)
                               var count = -1
                               while ((ins.read(data, 0, 1024).also { count = it }) != -1) {
                                   outStream.write(data, 0, count)

                               }
                           } else {

                           }
                       } catch (e: java.lang.Exception) {
                           e.printStackTrace()

                       } finally {
                           if (input != null) {
                               try {
                                   input.close()
                               } catch (e: IOException) {
                                   e.printStackTrace()
                               }
                           }
                           if (out != null) {
                               try {
                                   out.close()
                               } catch (e: IOException) {
                                   e.printStackTrace()
                               }
                           }
                           if (ins != null) {
                               try {
                                   ins.close()
                               } catch (e: IOException) {
                                   e.printStackTrace()
                               }
                           }
                           if (outStream != null) {
                               try {
                                   outStream.close()
                               } catch (e: IOException) {
                                   e.printStackTrace()
                               }
                           }
                           conn?.disconnect()
                       }
                   }
               } else {
                   Log.d("backinfo", "文件不存在")
               }
           }.start()*/
    }

    private fun pushtimeRule(baseBean: BaseBean, kind: String) {
        if (baseBean.kind_data == null) {
            ToastUtil.switchToastStyleToWarn("广告规则数据无效")
            return
        }
        EventBus.getDefault().post(ApiMessageEvent(kind, baseBean.kind_data))
    }

    private fun openOrCloseDev(baseBean: BaseBean) {
        val kind_data: String = baseBean.kind_data
        //没有关机
        if (kind_data == "1") {
            //开机
            threadSettingParam.startSetM3("01")
        } else if (kind_data == "0") {
            threadSettingParam.startSetM3("00")
        }

    }

    private fun alarmClock(gson: Gson, baseBean: BaseBean) {
        Log.d(TAG, "alarmClock: $baseBean")
        val kindData: String = baseBean.kind_data //拿到数据
        val alarmClock: AlarmClockBean = gson.fromJson(kindData, AlarmClockBean::class.java)
        val type: String = alarmClock.type //是休眠，还是开关机
        val weekTimes: ArrayList<String> = alarmClock.data //获取字符串时间。

        when (type) {
            AlarmClockEnum.OPEN_SLEEP.code -> {
                Heartbeat.openSleepNumber =
                    setAlarmClock(400, weekTimes, type, Heartbeat.openSleepNumber)
            }

            AlarmClockEnum.CLOSE_SLEEP.code -> {
                Heartbeat.openSleepNumber =
                    setAlarmClock(500, weekTimes, type, Heartbeat.closeSleepNumber)
            }

            AlarmClockEnum.OPEN_DEV.code -> {
                Heartbeat.openSleepNumber =
                    setAlarmClock(300, weekTimes, type, Heartbeat.offTimeNumber)
            }

            AlarmClockEnum.CLOSE_DEV.code -> {
                Heartbeat.openSleepNumber =
                    setAlarmClock(200, weekTimes, type, Heartbeat.bootTimeNumber)
            }

            else -> {}
        }

    }

    private fun deviceTuoji(kind: String) {
        SpUtils.putString(
            MMKVName.CONNECT_STATE,
            ConnectStateEnum.DEFAULT.name
        )
        Heartbeat.managerId = ""
        SpUtils.putString(MMKVName.MANAGER_ID, Heartbeat.managerId!!)
        EventBus.getDefault().post(ApiMessageEvent(kind, ""))
        Log.d(
            TAG,
            "getMessage: " + SpUtils.getString(
                MMKVName.CONNECT_STATE,
                ConnectStateEnum.DEFAULT.name
            )
        )
    }

    private fun restartAndroid() {
        try {
            val proc = Runtime.getRuntime().exec(arrayOf("su", "-c", "reboot"))
            proc.waitFor()
        } catch (ex: java.lang.Exception) {
            ex.printStackTrace()
        }
    }

    private fun setVolume(data: String) {
        try {
            val i: Int = data.toInt()
            if (i >= 0 && i <= 15) {
                val am =
                    BaseApplication.context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
                am.setStreamVolume(AudioManager.STREAM_MUSIC, i, 0)
                Log.d(TAG, "setVolume: $i")
            }
        } catch (e: Exception) {
        }
    }

    private fun savePhone(data: String) {
        if (data.contains(":")) {
            //获取：后的数据(广告规则id)
            val contactsWay: String = data.substring(data.lastIndexOf(":") + 1, data.length)
            //去掉：的值
            val contactsName: String = data.substring(0, data.lastIndexOf(":"))
            Log.d(TAG, "savePhone1: " + contactsName)
            Log.d(TAG, "savePhone2: " + contactsWay)
            SpUtils.putString(MMKVName.CONTACTS_WAY, contactsWay)
            SpUtils.putString(MMKVName.CONTACTS_NAME, contactsName)
        }


    }

    private fun devBlock(kind: String, data: String) {
        EventBus.getDefault().post(ApiMessageEvent(kind, data))
    }

    private fun devSleep(kind: String, data: String) {
        Log.d(TAG, "devSleep: " + kind + "：" + data)
        EventBus.getDefault().post(ApiMessageEvent(kind, data))
    }

    //推送 支付成功
    private fun paySuccess(gson: Gson, baseBean: BaseBean, kind: String) {
        val json: String = baseBean.kind_data
        val paySucessBean: PaySucessBean = gson.fromJson(json, PaySucessBean::class.java)
        //LogUtils.logWrite("第一步：存儲信息,支付成功")
        EventBus.getDefault().post(
            ApiMessageEvent(
                kind, PaySuccessBean(
                    UiUtil.getStringRes(
                        R.string.base_two_code
                    ), paySucessBean.sn
                )
            )
        )
    }

    /**
     * 初始化回调
     *
     * @param gson
     * @param baseBean
     * @param kind
     */
    private fun statusType(gson: Gson, baseBean: BaseBean, kind: String) {
        val json: String = baseBean.kind_data
        val s = gson.fromJson(json, String::class.java)
        if (s == "rejected") {
            //拒绝
            SpUtils.putString(MMKVName.CONNECT_STATE, ConnectStateEnum.DISCONNECTED.name)
        } else if (s == "agreed") {
            //申请通过
            SpUtils.putString(MMKVName.CONNECT_STATE, ConnectStateEnum.CONNECTED.name)
            SpUtils.putString(MMKVName.MANAGER_ID, Heartbeat.managerId!!)
        } else if (s == "agreed1") {
            //申请通过
            SpUtils.putString(MMKVName.CONNECT_STATE, ConnectStateEnum.CONNECTED.name)
            SpUtils.putString(MMKVName.MANAGER_ID, Heartbeat.managerId!!)
            EventBus.getDefault().post(ApiMessageEvent(kind + "1", ""))
        }
        EventBus.getDefault().post(ApiMessageEvent(kind, ""))
    }

    @Throws(ParseException::class)
    fun setAlarmClock(
        number: Int,
        weekTimes: ArrayList<String>,
        type: String,
        alarmNumber: Int,
    ): Int {
        var numberCount = 0;
        Log.d(
            TAG,
            "AlarmClock2onNext alarmNumber:$alarmNumber;setAlarmClock: $number"
        )
        for (i in number until alarmNumber) { //清除所有的闹钟
            AlarmManagerUtil.cancelAlarm(BaseApplication.context, AlarmManagerUtil.ALARM_ACTION, i)
            Log.d(
                TAG,
                "AlarmClock2onNext alarmNumber:$alarmNumber;setAlarmClock: $i"
            )
        }
        for (weekTime: String in weekTimes) {
            val weekTimeArray = weekTime.split(",:".toRegex()).dropLastWhile { it.isEmpty() }
                .toTypedArray()
            val weeks = weekTimeArray[0].split(",".toRegex()).dropLastWhile { it.isEmpty() }
                .toTypedArray() //星期
            val times = weekTimeArray[1].split(":".toRegex()).dropLastWhile { it.isEmpty() }
                .toTypedArray() //时间
            var hour = ""
            var minute: String = ""
            var msg = ""
            if ("1" == type) { //只有关机的才需要。
                if (times[1].toInt() < 5) { //如果小于5，我们需要做好计算才行。00：00：00
                    //小于5，则
                    //  times[0]-1：
                    //  times[1]：4-5=-1,60-1=59,是正确的。
                    if (times[0].toInt() < 1) {
                        hour = (times[0].toInt() - 1 + 24).toString() + ""
                        Log.d(TAG, "setAlarmClock: 小于1")
                    } else {
                        hour = (times[0].toInt() - 1).toString() + ""
                        Log.d(TAG, "setAlarmClock: 大于1")
                    }
                    minute = (times[1].toInt() - 5 + 60).toString() + ""
                    Log.d(TAG, "setAlarmClock: 小于5")
                } else {
                    hour = times[0]
                    minute = (times[1].toInt() - 5).toString() + ""
                    Log.d(TAG, "setAlarmClock: 大于5")
                }
                val now = Calendar.getInstance()
                val sdf = SimpleDateFormat("HH:mm:ss")
                //设置时间
                val date1 = sdf.parse(
                    times[0] + ":" +
                            times[1] + ":" +
                            times[2]
                )
                Log.d(TAG, "setAlarmClock: $date1")
                //当前时间
                val date2 = sdf.parse(
                    (now[Calendar.HOUR_OF_DAY].toString() + ":" +
                            now[Calendar.MINUTE] + ":" +
                            now[Calendar.SECOND])
                )
                Log.d(TAG, "setAlarmClock: $date2")

                if (date1.compareTo(date2) > 0) {
                    Log.d(
                        TAG,
                        "Date1 时间在 Date2 之后"
                    ) //没过
                    val nowDate = date1.time //当前时间
                    val startDateTime = date2.time //真实时间
                    val diffSeconds = ((nowDate - startDateTime) / 1000).toInt()
                    Log.d(
                        TAG,
                        "setAlarmClock: $diffSeconds"
                    )
                    if (diffSeconds >= 360) {
                        times[0] = hour
                        times[1] = minute
                        msg = "show"
                        Log.d(
                            TAG, times[0] + "setAlarmClock: 弹窗" + times[1]
                        )
                    } else {
                        //不弹窗
                        Log.d(
                            TAG,
                            "Date1 时间在 Date2 之前"
                        ) //没过
                        Log.d(TAG, "setAlarmClock1: 不弹窗")
                    }
                } else { //过了
                    println("程序怎么会运行到这里?正常应该不会")
                    Log.d(TAG, "setAlarmClock1: 不弹窗")
                }
            }
            for (i in weeks.indices) {
                AlarmManagerUtil.setAlarm(
                    BaseApplication.context,
                    2,
                    times[0].toInt(),
                    times[1].toInt(),
                    times[2].toInt(),
                    i + number,
                    weeks[i].toInt(),
                    type + msg
                )
            }
            numberCount = number + weeks.size //累积。
        }
        Log.d(TAG, "setAlarmClock: $numberCount")
        return numberCount
    }
}