package com.abbidot.tracker.util

import android.content.Context
import com.abbidot.baselibrary.util.AppUtils
import com.abbidot.baselibrary.util.LogUtil
import com.clj.fastble.utils.HexUtil
import com.easysocket.EasySocket
import com.easysocket.config.EasySocketOptions
import com.easysocket.connection.action.SocketStatus
import com.easysocket.entity.OriginReadData
import com.easysocket.entity.SocketAddress
import com.easysocket.interfaces.conn.ISocketActionListener


/**
 *Created  by .yzq on 2025/4/18/018.
 * @link
 * @description:
 */
class SocketUtilManage {

    private val iP = "3.101.8.36"
//    private val iP = "192.168.0.69"

    //默认国外服务器端口
    private var port = 8868

    @OptIn(ExperimentalUnsignedTypes::class)
    private val crcTable = ushortArrayOf(
        0x0000u,
        0xCC01u,
        0xD801u,
        0x1400u,
        0xF001u,
        0x3C00u,
        0x2800u,
        0xE401u,
        0xA001u,
        0x6C00u,
        0x7800u,
        0xB401u,
        0x5000u,
        0x9C01u,
        0x8801u,
        0x4400u
    )

    /**
     * 初始化EasySocket
     */
    fun initEasySocket(context: Context) {
        if (AppUtils.isChina()) {
            //国内socket端口号
            port = 9168
        }
        //socket配置
        val options = EasySocketOptions.Builder().setSocketAddress(SocketAddress(iP, port))
            .setMaxWriteBytes(300)
            // 强烈建议定义一个消息协议，方便解决 socket黏包、分包的问题
            // .setReaderProtocol(new DefaultMessageProtocol()) // 默认的消息协议
            .build()
        //初始化EasySocket
        EasySocket.getInstance().createConnection(options, context).setDebug(AppUtils.isDebug())

        //监听socket相关行为
        EasySocket.getInstance().subscribeSocketAction(object : ISocketActionListener {
            override fun onSocketConnSuccess(socketAddress: SocketAddress?) {
                LogUtil.e("socket连接成功")
            }

            override fun onSocketConnFail(socketAddress: SocketAddress?, isNeedReconnect: Boolean) {
                LogUtil.e("socket连接失败,是否需要重连:$isNeedReconnect")
            }

            override fun onSocketDisconnect(
                socketAddress: SocketAddress?, isNeedReconnect: Boolean
            ) {
                LogUtil.e("socket断开连接,是否需要重连:$isNeedReconnect")
            }

            override fun onSocketResponse(
                socketAddress: SocketAddress?, originReadData: OriginReadData?
            ) {
                LogUtil.d("socket监听器收到对象数据=" + originReadData?.bodyString)
            }

            override fun onSocketResponse(socketAddress: SocketAddress?, readData: String?) {
                LogUtil.d("socket监听器收到字符串数据=$readData")
            }

            override fun onSocketResponse(socketAddress: SocketAddress?, readData: ByteArray?) {
                val data = HexUtil.formatHexString(readData, true)
                LogUtil.e("socket监听器收到字节数组数据=$data")
            }
        })
    }

    /**
     * 单字节 CRC16 计算
     */
    @OptIn(ExperimentalUnsignedTypes::class)
    private fun crcGet16(crc: UShort, byte: UByte): UShort {
        var currentCrc = crc.toInt()
        val lowerNibble = byte.toInt() and 0x0F
        val upperNibble = (byte.toInt() shr 4) and 0x0F

        // 处理低 4 位
        var tmp = crcTable[currentCrc and 0x0F].toInt()
        currentCrc = (currentCrc shr 4) and 0x0FFF
        currentCrc = currentCrc xor tmp xor crcTable[lowerNibble].toInt()

        // 处理高 4 位
        tmp = crcTable[currentCrc and 0x0F].toInt()
        currentCrc = (currentCrc shr 4) and 0x0FFF
        currentCrc = currentCrc xor tmp xor crcTable[upperNibble].toInt()

        return currentCrc.toUShort()
    }

    /**
     * 计算 CRC16（处理字节数组）
     */
    private fun crcCalc16(data: ByteArray): UShort {
        // 初始值（初始 CRC 为 0）
        var crc = 0
        data.forEach { byte ->
            crc = crcGet16(crc.toUShort(), byte.toUByte()).toInt()
        }
        return crc.toUShort()
    }

    /**
     * 大端序转换:0x3C (高字节) 0x30 (低字节)
     */
    private fun UShort.toBytesBE(): ByteArray = byteArrayOf(
        (this.toInt() shr 8).toByte(), this.toByte()
    )

    /**
     * 小端序转换:0x30 (低字节) 0x3C (高字节)
     */
    private fun UShort.toBytesLE(): ByteArray = byteArrayOf(
        this.toByte(), (this.toInt() shr 8).toByte()
    )

    /**
     * 发送一个的消息，
     */
    fun sendMessage(mac: String, msgID: Byte, msgData: MutableList<Byte>) {
        try {
//            val data = byteArrayOf(0x01, 0x03, 0x00, 0x01)
//            //输出 15408
//            val crc16 = crcCalc16(data)
//            // 输出 0x3c30
//            val bytes = crc16.toBytesBE()
//            LogUtil.e("CRC16:  ${HexUtil.formatHexString(bytes, true)},$crc16")

            val macList = mac.split(":")
            val macLen = macList.size
            val macByteArray = ByteArray(macLen)
            for (i in 0 until macLen) {
                macByteArray[i] = macList[i].toInt(16).toByte()
            }
            val deviceIdByteArray = byteArrayOf(
                macByteArray[macLen - 1],
                macByteArray[macLen - 2],
                macByteArray[macLen - 3],
                macByteArray[macLen - 4]
            )

            val cmdList = mutableListOf<Byte>()
            //Device ID ,4 Bytes
            cmdList.addAll(deviceIdByteArray.toMutableList())
            //BLE MAC地址,6 Bytes
            cmdList.addAll(macByteArray.toMutableList())
            //Seq No.：包顺序号，2 Bytes
            cmdList.add(0)
            cmdList.add(1)
            //后续消息数：1 Byte
            cmdList.add(0)
            //消息ID：MsgID，1 Byte
            cmdList.add(msgID)
            //消息数据：Msg Data
            cmdList.addAll(msgData.toMutableList())
            val packetLength = 19 + msgData.size
            //包长：从包起始符到包结束符整个数据包的长度，1 Byte
            cmdList.add(0, packetLength.toByte())
            val crc = crcCalc16(cmdList.toByteArray())
            val crc16ByteArray = crc.toBytesBE()
            //校验值：CRC16，2 Bytes
            cmdList.addAll(crc16ByteArray.toMutableList())
            //包结束符：字符‘#’，1 Byte
            cmdList.add('#'.code.toByte())
            //包起始符：字符‘@’，1 Byte
            cmdList.add(0, '@'.code.toByte())
            val cmdByteArray = cmdList.toByteArray()

            val cmdByteArrayFormat = HexUtil.formatHexString(cmdByteArray, true)
            LogUtil.e("$mac==${cmdList.size}个字节,$cmdByteArrayFormat")

            val socketStatus = EasySocket.getInstance().defconnection.connectionStatus
            //socket状态已连接
            if (socketStatus == SocketStatus.SOCKET_CONNECTED) {
                //发送
                EasySocket.getInstance().upMessage(cmdByteArray)
            }
        } catch (e: Exception) {
            LogUtil.e("socket 发消息异常：${e.message}")
        }
    }

    fun destroy() {
        try {
            //destroyConnection()代表销毁整个连接状态，跟disconnect()不一样，如果此时要进行socket连接需要重新创建一个连接
            EasySocket.getInstance().destroyConnection()
            //注销监听socket相关行为
            EasySocket.getInstance().defOptions.reconnectionManager.detach()
            LogUtil.e("socket销毁连接")
        } catch (e: Exception) {
            LogUtil.e("socket销毁连接异常：${e.message}")
        }
    }
}