package com.quyunshuo.module.home.service

import android.app.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.os.Bundle
import android.os.Handler
import android.os.IBinder
import android.os.Message
import android.util.Log
import com.hboxs.serialport.plc.message.MqttMessageBean
import com.quyunshuo.androidbaseframemvvm.base.utils.SpUtils
import com.quyunshuo.androidbaseframemvvm.base.utils.commons.StringUtils
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.SavaAddress
import com.quyunshuo.androidbaseframemvvm.common.enums.ConnectStateEnum
import com.quyunshuo.androidbaseframemvvm.common.util.ToastUtil
import com.quyunshuo.androidbaseframemvvm.common.util.UiUtil
import com.quyunshuo.androidbaseframemvvm.common.util.XLogUtil
import com.quyunshuo.module.home.receiver.MqttHelper
import com.quyunshuo.module.home.utils.PeriodicTask
import com.rabbitmq.client.AMQP
import com.rabbitmq.client.Channel
import com.rabbitmq.client.Connection
import com.rabbitmq.client.ConnectionFactory
import com.rabbitmq.client.DefaultConsumer
import com.rabbitmq.client.Envelope
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.io.IOException
import java.util.concurrent.TimeUnit
import javax.inject.Inject

@AndroidEntryPoint
class MqService : Service(), PeriodicTask.Callback {
    private val TAG = "MQService"
    lateinit var factory: ConnectionFactory
    private val userName = "admin"
    private val passWord = "admin"
    private val hostName = "112.74.63.148"
    private val portNum = 5672

    @Inject
    lateinit var mqServiceViewModel: MqServiceViewModel

    @Inject
    lateinit var mqttHelper: MqttHelper

    //    private String hostName = "192.168.0.184";//

    private var queueName: String = Heartbeat.deviceId!! //队列

    @Volatile
    var connect: Boolean = false
    val handler: Handler = object : Handler() {
        override fun handleMessage(msg: Message) {
            mqServiceViewModel.getMtMessage(msg)
        }
    }
    private lateinit var periodicTask: PeriodicTask

    private var mNetWorkBroadCastReciver: NetWorkBroadCastReciver? = null


    override fun onBind(intent: Intent?): IBinder? {
        return null
    }

    override fun onCreate() {
        super.onCreate()
        Log.d(TAG, "onCreate......")
        EventBus.getDefault().register(this)
        //连接设置
        setupConnectionFactory()
        //开启消费者线程
        //subscribe(incomingMessageHandler);
        basicConsume(1)
        Log.d(TAG, "oncrect里么的线程开启了")
        mNetWorkBroadCastReciver = NetWorkBroadCastReciver()
        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)
        registerReceiver(mNetWorkBroadCastReciver, intentFilter)
        mqttHelper.register(this)
        CoroutineScope(Dispatchers.IO).launch {
            delay(10000)
            //  mqttHelper.sendData("asdfasdf")
            Log.d(TAG, "mqttHelper.sendData: ")

        }
        periodicTask = PeriodicTask.Builder()
            .initialDelay(0, TimeUnit.SECONDS) // 立即开始
            .interval(5, TimeUnit.HOURS)      // 5秒间隔
            .retryCount(1)                      // 失败重试2次
            .build()

        // 启动任务
        periodicTask.start(this)
    }

    override fun onDestroy() {
        super.onDestroy()
        periodicTask.stop()
        unregisterReceiver(mNetWorkBroadCastReciver)
        EventBus.getDefault().unregister(this)
    }

    /**
     * 连接设置
     */
    private fun setupConnectionFactory() {
        factory = ConnectionFactory()
        factory.host = hostName
        factory.port = portNum
        factory.username = userName
        factory.password = passWord
        factory.isAutomaticRecoveryEnabled = true
    }

    private var addTime = 0

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        if (intent != null) {
            val extras = intent.extras
            if (extras != null) {
                val first = extras.getInt("connect")
                if (first == 1) { //5分钟来一次。
                    basicConsume(6)
                }
            }
        }
        val connectState = SpUtils.getString(MMKVName.CONNECT_STATE, ConnectStateEnum.DEFAULT.name)
        Log.d(TAG, "onStartCommand......$connectState")
        if (connectState == ConnectStateEnum.DEFAULT.name) { //如果说是第一次，则表示还没有创建
            initView()
        } else { //如果说是第二次，则可以直接打开。因为已经创建出来了。
            initView1()
        }

        //消费者服务线程
        return super.onStartCommand(intent, flags, startId)
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun event(message: MqttMessageBean) {
        Log.d("backinfo","message.topicType："+message.topicType)
        Log.d("backinfo","Heartbeat.deviceId："+Heartbeat.deviceId)

        when (message.topicType) {
            MqName.SENDPRICE -> {
                SpUtils.putBoolean(MMKVName.IS_UPDATE_PRODUCT, true)
                XLogUtil.d("修改价格：" + message.content)
                if (mqttHelper.isMqConnected()) {
                    Log.d("backinfo", "要发送修改设备价格的数据：" + message.content)
                    mqttHelper.sendData(message.topic, message.content)
                } else {
                    ToastUtil.switchToastStyleToWarn(UiUtil.getStringRes(com.quyunshuo.androidbaseframemvvm.base.R.string.base_mqtt_con_state))
                }


            }

            MqName.RECEIVE -> {
                mqServiceViewModel.getMQTTMessage(message.content)
            }

            MqName.SENDSUCCESS -> {
                if (message.topic == MqName.updatePrice) {
                    SpUtils.putBoolean(MMKVName.IS_UPDATE_PRODUCT, false)
                }

            }

            MqName.onoffstatus -> {
                mqServiceViewModel.updateEqeStatus()
            }

            MqName.DOSUGAR -> {
                mqServiceViewModel.makingmarshmallows(message.content)
            }
        }
    }

    //旧方法
    private fun initView() {
        var data = SpUtils.getString(MMKVName.QUEUE_DATA, "") as String //连接设备id
        Log.d(TAG, "data initView: $data")
        //        String updateMaterialStatus = (String) SharedPreferencesUtils.getParam(Name.SEPARATE_SUCCESS, "");  //脱离系统
        val updateMaterialStatus = SpUtils.getString(MMKVName.MANAGER_ID, "") as String
        if (("" == updateMaterialStatus)) { //因为脱离系统了，那么就清空，重新创建
            data = ""
        }
        val machineType: String =
            SpUtils.getString(MMKVName.MACHINE_TYPE, SavaAddress.MACHINE_TYPE)!!
        Log.d(TAG, "$data: mq getAddQueue: $machineType")
        // SharedPreferencesUtils.setParam(Name.QUEUE_DATA, data);
        if (("" == Heartbeat.deviceId)) {
            //如果没有id，肯定是新机器，无创建过队列，直接 return;
            Log.d(TAG, "mq1,没有id,直接跳出")
            return
        } else {
            Log.d(TAG, "mq1,有id的情况")
            if ((data == "success")) {
                //创建过队列。
                Log.d(TAG, "mq1,创建过队列，开启过线程，直接退出")
                return
            } else {
                if (addTime > 0) {
                    return
                } else {
                    Log.d(TAG, "mq1,没有创建过队列，没有开启过线程，现在开始创建和开启")
                    addTime = 1
                    mqServiceViewModel.getAddQueue() //创建mq
                    mqServiceViewModel.getChannel() //修改通道
                }
            }
        }
        Log.d(TAG, "mq,这里都会执行")
        //开启消费者线程
        //subscribe(incomingMessageHandler);
        if (!connect) {
            basicConsume(2)
        }
    }

    private fun initView1() {
        val data = SpUtils.getString(MMKVName.QUEUE_DATA, "") as String //连接设备id
        Log.d(TAG, "1data initView: $data")
        val machineType: String =
            SpUtils.getString(MMKVName.MACHINE_TYPE, SavaAddress.MACHINE_TYPE)!!
        Log.d(TAG, "$data: mq getAddQueue: $machineType")
        // SharedPreferencesUtils.setParam(Name.QUEUE_DATA, data);
        if (("" == XLogUtil.getDeviceId())) {
            //如果没有id，肯定是新机器，无创建过队列，直接 return;
            Log.d(TAG, "mq,没有id,直接跳出")
            return
        } else {
            Log.d(TAG, "mq,有id的情况")
            if ((data == "success")) {
                //创建过队列。
                Log.d(TAG, "mq,创建过队列，开启过线程，直接退出")
                return
            } else {
                if (addTime > 0) {
                    return
                } else {
                    Log.d(TAG, "mq,没有创建过队列，没有开启过线程，现在开始创建和开启")
                    addTime = 1
                    mqServiceViewModel.getAddQueue() //创建mq
                    mqServiceViewModel.getChannel() //修改通道
                }
            }
        }
        Log.d(TAG, "mq,这里都会执行")
        //开启消费者线程
        //subscribe(incomingMessageHandler);
        if (!connect) {
            basicConsume(2)
        }
    }


    /**
     * 收消息（从发布者那边订阅消息）
     */
    private fun basicConsume(id: Int) {
        Log.d(TAG, "basicConsume: $id")
        Thread {
            if (connect) {
                return@Thread
            }
            synchronized(handler) {
                if (connect) {
                    return@Thread
                }
                if (SpUtils.getString(
                        MMKVName.CONNECT_STATE,
                        ConnectStateEnum.DEFAULT.name
                    ) == ConnectStateEnum.DEFAULT.name
                ) {
                    queueName = Heartbeat.deviceId!!
                } else {
                    queueName = XLogUtil.getDeviceId()
                }
                try {
                    //1. 连接
                    val connection: Connection = factory.newConnection()

                    //2. 通道
                    val channel: Channel = connection.createChannel()

                    //3. 定义消费者
                    // 实现Consumer的最简单方法是将便捷类DefaultConsumer子类化。可以在basicConsume 调用上传递此子类的对象以设置订阅：
                    channel.basicConsume(
                        queueName,
                        false,
                        object : DefaultConsumer(channel) {
                            @Throws(IOException::class)
                            override fun handleDelivery(
                                consumerTag: String?,
                                envelope: Envelope,
                                properties: AMQP.BasicProperties?,
                                body: ByteArray?,
                            ) {
                                super.handleDelivery(
                                    consumerTag,
                                    envelope,
                                    properties,
                                    body
                                )
                                //获取发送过来的数据
                                val msg: String = String((body)!!, charset("utf-8"))
                                Log.d(TAG, "msg->$msg")
                                val deliveryTag: Long = envelope.getDeliveryTag()
                                Log.d(TAG, "deliveryTag->$deliveryTag")

                                //3. 手动确认消息
                                channel.basicAck(deliveryTag, false)
                                //4. 在这里，可以添加处理消息的代码
                                val uimsg: Message =
                                    handler.obtainMessage()//从message池中获取msg对象更高效
                                val bundle: Bundle = Bundle()
                                bundle.putString("msg", msg)
                                uimsg.setData(bundle)
                                handler.sendMessage(uimsg)
                            }
                        })
                    connect = true
                    Log.d(TAG, "basicConsume run: $connect")
                } catch (e: Exception) {
                    networkState = 100
                    e.printStackTrace()
                    Log.d(TAG, "basicConsume: IOException" + e.message)
                }
            }
        }.start()
    }


    //接收网络状态改变的广播
    inner class NetWorkBroadCastReciver() : BroadcastReceiver() {
        override fun onReceive(context: Context, intent: Intent) {
            isNetConnected(context)
        }


    }

    private var networkState = 100

    fun isNetConnected(context: Context): Boolean {
        val connectivity: ConnectivityManager =
            context.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager
        val info = connectivity.activeNetworkInfo ?: return false
        if (info.type == networkState) {
            return false
        }
        networkState = info.type
        if (info.type == (ConnectivityManager.TYPE_WIFI)) {
            if (!connect) {
                Log.d(TAG, "isNetConnectedTYPE_WIFI: 执行了一次。")
                basicConsume(3)
            }
            return true
        } else if (info.type == (ConnectivityManager.TYPE_MOBILE)) {
            if (!connect) {
                Log.d(TAG, "isNetConnectedTYPE_MOBILE: 执行了一次。")
                basicConsume(4)
            }
            return true
        }
        return false
    }

    override fun onNext(attemptCount: Int) {

        if (SpUtils.getBoolean(MMKVName.IS_UPDATE_PRODUCT, false) == true) {
            var productStr = SpUtils.getString(MMKVName.PRODUCT_DATA, "")
            if (StringUtils.isNotNullOrEmpty(productStr)) {
                if (mqttHelper.isMqConnected()) {
                    Log.d("backinfo", "开始发送更改价格")
                    productStr?.let { mqttHelper.sendData(MqName.updatePrice, it) }
                }
            }
        }

    }

    override fun onError(throwable: Throwable) {

    }

}