package com.dlc.exam.mqtt

import android.content.Context
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.widget.Toast
import com.dlc.exam.common.CommonUtils
import com.dlc.exam.common.Constants
import com.dlc.exam.dummy.DummyData
import com.dlc.exam.mqtt.entity.*
import com.dlc.exam.mqtt.event.*
import com.dlc.exam.sp.EnvConfig
import com.dlc.exam.sp.EnvSp
import com.google.gson.Gson
import com.rc.core.log.RcLog
import org.eclipse.paho.client.mqttv3.MqttMessage
import org.greenrobot.eventbus.EventBus

/**
 * info
 *
 * @author ReiChin_
 */
class MqttManager private constructor() {

    companion object {
        val instance: MqttManager by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
            MqttManager()
        }
    }

    private val mHandler = Handler()
    private val mGson = Gson()

    private lateinit var clientId: String
    private lateinit var mMqttWorker: MqttWorker
    private lateinit var androidId: String
    private lateinit var appContext: Context

    fun initMqtt(androidId: String, appContext: Context) {
        RcLog.info("[MQTT] MqttManager init start.")
        this.clientId = "mqtt_exam${if (Constants.Mock.MQTT_CLIENT_TEST) "_test" else ""}#$androidId"
        this.androidId = androidId
        this.appContext = appContext
        mMqttWorker = MqttWorker(
            Constants.MqttConfig.SERVER_URI,
            clientId,
            Constants.MqttConfig.U_NAME,
            Constants.MqttConfig.U_PWD
        )
        mMqttWorker.setListener(object : MqttWorker.Listener {

            override fun onConnectSuccess() {
                RcLog.info("[MQTT] MqttManager 连接成功.")
                //  连接成功后，订阅主题
                val topics = arrayOf(
                    Constants.MqttConfig.Topic.HEART,
                    Constants.MqttConfig.Topic.APP_UPDATE.plus(androidId),
                    Constants.MqttConfig.Topic.ENV_UPDATE.plus(androidId),
                    Constants.MqttConfig.Topic.BANNER_IMG
                )
                // 订阅主题
                mMqttWorker.subscribe(topics, 0)
                // 发送心跳
                mHandler.removeCallbacks(mRunSendHeartBeat)
                mHandler.postDelayed(mRunSendHeartBeat, 2000)

                if (Constants.Mock.MQTT_TEST) {
                    mDummyHandler.removeCallbacks(mDummySendRunnable)
                    mHandler.postDelayed(mDummySendRunnable, 2000)
                }
            }

            override fun messageArrived(topic: String?, message: MqttMessage?) {
//                RcLog.info("[MQTT] MqttManager 收到消息,topic=${topic}, message=${message}")
                dispatchMessage(topic, message.toString())
            }
        })
    }

    fun connect() {
        mMqttWorker.connect()
    }

    /**
     * 释放单例, 及其所引用的资源
     */
    @Synchronized
    fun release() {
        try {
            mDummyHandler.removeCallbacksAndMessages(null)
            mHandler.removeCallbacksAndMessages(null)
            mMqttWorker.setListener(null)
            mMqttWorker.release()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    /**
     * 发送心跳
     */
    private val mRunSendHeartBeat = object : Runnable {
        override fun run() {
            val heartBeatEntry = HeartBeatEntity()
                .apply {
                    type = "heart"
                    macno = clientId
                    time = (System.currentTimeMillis() / 1000).toInt()
                }

            val message = mGson.toJson(heartBeatEntry)
            mMqttWorker.publish(Constants.MqttConfig.Topic.HEART, message, 0)
            mHandler.postDelayed(this, 30000)
        }
    }

    /**
     * 分发消息
     *
     * @param topic
     * @param message
     */
    private fun dispatchMessage(topic: String?, message: String) {
        try {
            when (topic) {
                Constants.MqttConfig.Topic.APP_UPDATE.plus(androidId) -> {
                    val entity = mGson.fromJson(message, UpdateEntity::class.java)
                    EventBus.getDefault().post(UpdateEvent(entity.data))
                }
                Constants.MqttConfig.Topic.ENV_UPDATE.plus(androidId) -> {
                    // 更新配置信息
                    if (updateEnvConfig(message)) {
                        object : Handler(Looper.getMainLooper()) {
                            override fun handleMessage(msg: Message) {
                                Toast.makeText(appContext, "配置更新，请重新登录", Toast.LENGTH_SHORT).show()
                                CommonUtils.restartApp(appContext)
                                removeCallbacksAndMessages(null)
                            }
                        }.sendEmptyMessageDelayed(1, 1000)
                    }
                }
                Constants.MqttConfig.Topic.BANNER_IMG -> {
                    // 轮播图/企业文化图更新
//                    EventBus.getDefault().post(BannerEvent())
                }
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    private fun updateEnvConfig(message: String): Boolean {
        val entity = mGson.fromJson(message, EnvEntity::class.java)
        val data = entity.data ?: return false

        // 服务器新环境
        if (data.baseUrl.isNullOrEmpty()) return false

        // 文件浏览环境
        if (data.fileBrowserBaseUrl.isNullOrEmpty()) return false

        // MQTT新环境
        if (data.mqttUrl.isNullOrEmpty()) return false

        // MQTT账号
        if (data.mqttName.isNullOrEmpty()) return false

        // MQTT密码
        if (data.mqttPwd.isNullOrEmpty()) return false

        val settingPwd = EnvSp.loadEnv(appContext)?.settingPwd ?: Constants.Mock.SETTING_PWD

        val newEnv = if (!data.baseUrl.endsWith("/")) "${data.baseUrl}/" else data.baseUrl
        val newFileBrowserEnv =
            if (!data.fileBrowserBaseUrl.endsWith("/")) "${data.fileBrowserBaseUrl}/" else data.fileBrowserBaseUrl
        val envConfig = EnvConfig(newEnv, newFileBrowserEnv, data.mqttUrl, data.mqttName, data.mqttPwd, settingPwd)
        EnvSp.saveEnv(appContext, envConfig)

        return true
    }

    private val mDummyHandler = Handler()
    private val mDummySendRunnable = object : Runnable {
        override fun run() {
            val appUpdateMsg = mGson.toJson(DummyData.dummyUpdateEntity())
            mMqttWorker.publish(Constants.MqttConfig.Topic.APP_UPDATE.plus(androidId), appUpdateMsg, 0)
            val evnUpdateMsg = mGson.toJson(DummyData.dummyEnvEntity())
            mMqttWorker.publish(Constants.MqttConfig.Topic.ENV_UPDATE.plus(androidId), evnUpdateMsg, 0)
            mMqttWorker.publish(Constants.MqttConfig.Topic.BANNER_IMG, "", 0)
            mHandler.postDelayed(this, 3000)
        }
    }

}