package com.quyunshuo.module.home.service

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import android.net.wifi.WifiManager
import android.util.Log
import com.quyunshuo.androidbaseframemvvm.common.constant.Heartbeat
import com.hboxs.serialport.plc.message.MqttMessageBean
import com.hboxs.serialport.sbc.SBCHeartbeat
import com.quyunshuo.androidbaseframemvvm.common.constant.MqName
import org.eclipse.paho.android.service.MqttAndroidClient
import org.eclipse.paho.client.mqttv3.IMqttActionListener
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken
import org.eclipse.paho.client.mqttv3.IMqttToken
import org.eclipse.paho.client.mqttv3.MqttCallbackExtended
import org.eclipse.paho.client.mqttv3.MqttConnectOptions
import org.eclipse.paho.client.mqttv3.MqttException
import org.eclipse.paho.client.mqttv3.MqttMessage
import javax.inject.Inject
import javax.inject.Singleton

/**
 * 测试环境的设备管理系统
 */
@Singleton
class ManageMqtt @Inject constructor() {

    private var context: Context? = null
    private var TAG = "MQTT"
    private var client: MqttAndroidClient? = null //mqtt客户端
    private lateinit var options: MqttConnectOptions  //mqtt 的链接信息设置

    @Volatile
    var isMqConnected: Boolean = false


    //初始化，
    fun init(context: Context?) {
        this.context = context
        try {
            log("1")

            if (client != null) {
                return
            }
            log("1")
            //MQTT的连接设置
            options = MqttConnectOptions()
            //设置是否清空session,这里如果设置为false表示服务器会保留客户端的连接记录，这里设置为true表示每次连接到服务器都以新的身份连接
            options.isCleanSession = true
            //重连尝试
            options.isAutomaticReconnect = true
            // 设置超时时间 单位为秒
            options.connectionTimeout = 10
            // 设置会话心跳时间 单位为秒 服务器会每隔1.5*20秒的时间向客户端发送个消息判断客户端是否在线，但这个方法并没有重连的机制
            options.keepAliveInterval = 90

            client = MqttAndroidClient(
                context,
                "tcp://112.74.33.65:1883",
                Heartbeat.deviceId
            )//在管理里面显示的名称
            //设置连接的用户名
            options.userName = "sunzeeUser"
            //设置连接的密码
            options.password = "sunzeeUser@020".toCharArray()


            //设置回调
            client?.setCallback(object : MqttCallbackExtended {
                override fun connectComplete(reconnect: Boolean, serverURI: String) {
                    log("已连接mq" + Heartbeat.deviceId)
                    isMqConnected = true
                    //连接成功，我们要进行订阅
                    Heartbeat.deviceId?.let { subscribe(it) }
                }

                override fun connectionLost(cause: Throwable) {
                    log("已断开mq")
                    isMqConnected = false
                }

                override fun deliveryComplete(token: IMqttDeliveryToken) {
                    //publish后会执行到这里  发布
                    try {
                        log("发送成功：" + token.message.toString())
                    } catch (e: Exception) {
                        e.printStackTrace()
                    }
                }

                override fun messageArrived(topicName: String, message: MqttMessage) {
                    //subscribe后得到的消息会执行到这里面  订阅
                    //topicName 为主题
                    try {
                        //todo 收到消息，要进行一些处理的。 Eventbus
                        log("收到消息：$topicName     $message")
                        val str1: String = String(message.getPayload())

                        org.greenrobot.eventbus.EventBus.getDefault()
                            .post(
                                MqttMessageBean(
                                    topicName,
                                    MqName.RECEIVE,
                                    str1
                                )
                            )
                    } catch (e: Exception) {
                        log("异常:$e")
                    }
                }
            })
            connect()
        } catch (e: Exception) {
            e.printStackTrace()
        }
        val intentFilter = IntentFilter()
        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION)
        intentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION)
        intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION)
        intentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION)
        context?.registerReceiver(netWorkBroadCastReciver, intentFilter)
    }

    //进行链接
    private fun connect() {
        Thread(connect).start()
//        Schedulers.io().scheduleDirect(connect)
    }

    private val connect = Runnable {
        if (client != null && client!!.isConnected) {
            return@Runnable
        }
        try {
            log("连接Mq............")
            client?.connect(options, null, object : IMqttActionListener {
                override fun onSuccess(asyncActionToken: IMqttToken) {
                    log("Connection success")
                    //todo 是否连接成功？要重连的。
                }

                override fun onFailure(asyncActionToken: IMqttToken, exception: Throwable) {
                    log("Connection failure")
                    //todo 是否连接成功？要重连的。

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


    //订阅信息
    fun subscribe(topic: String, qos: Int = 1) {
        try {
            client?.subscribe(topic, qos, null, object : IMqttActionListener {
                override fun onSuccess(asyncActionToken: IMqttToken?) {
                    Log.d(TAG, "Subscribed to $topic")

                }

                override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                    Log.d(TAG, "Failed to subscribe $topic")
                }
            })
        } catch (e: MqttException) {
            e.printStackTrace()
        }
    }

    //发送消息
    /**
     * @param topic 主题 给这个主题发送消息
     *  @param qos 0最多一次不管是否收到，1最少一次可能会收到多次，2保证收到,且仅一次
     *  @param retained 发布后是否保留，即重新链接时会存在
     *  @param msg 消息
     */
    fun publish(topic: String, msg: String, qos: Int = 0, retained: Boolean = false) {
        try {
            val message = MqttMessage()
            message.payload = msg.toByteArray()
            message.qos = qos
            message.isRetained = retained //发布后是否保留，即重新链接时会存在
            client?.publish(topic, message, null, object : IMqttActionListener {
                override fun onSuccess(asyncActionToken: IMqttToken?) {
                    Log.d(TAG, "$msg published to $topic")
                    org.greenrobot.eventbus.EventBus.getDefault()
                        .post(
                            MqttMessageBean(
                                topic,
                                MqName.SENDSUCCESS,
                                ""
                            )
                        )
                }

                override fun onFailure(asyncActionToken: IMqttToken?, exception: Throwable?) {
                    Log.d(TAG, "Failed to publish $msg to $topic")
                    org.greenrobot.eventbus.EventBus.getDefault()
                        .post(
                            MqttMessageBean(
                                topic,
                                MqName.SENDFAILURE,
                                ""
                            )
                        )
                }
            })
        } catch (e: MqttException) {
            e.printStackTrace()
        }
    }

    //释放资源
    fun closeMqtt() {
        try {
            if (client != null) {
                client!!.disconnect()
                client = null
            }
        } catch (e: java.lang.Exception) {
            e.printStackTrace()
        }
        context?.unregisterReceiver(netWorkBroadCastReciver)
    }

    //打印log
    private fun log(msg: String) {
        Log.d(TAG, msg)
    }


    private var networkState = 100

    //断网重连查询
    fun isNetConnected(context: Context): Boolean {
        Log.d(TAG, "isNetConnected: ")
        val connectivity =
            context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
        if (connectivity != null) {
            val info = connectivity.activeNetworkInfo
            if (info != null) {
                if (info.type == networkState) {
                    return false
                }
                networkState = info.type
                if (info.type == (ConnectivityManager.TYPE_WIFI)) {
                    if (!isMqConnected) {

                        connect()
                    }
                    return true
                } else if (info.type == (ConnectivityManager.TYPE_MOBILE)) {
                    if (!isMqConnected) {
                        connect()
                    }
                    return true
                }
            }
        }

        return false
    }

    var netWorkBroadCastReciver = object : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent?) {
            isNetConnected(context)
            log("NetWorkBroadCastReciver: ")
        }
    }


}