package com.common.bluetooth

import android.content.Context
import android.content.SharedPreferences
import android.text.TextUtils
import android.util.Log.d
import android.util.Log.e
import com.common.bluetooth.bean.*

/**
 * 蓝牙工具类
 *
 * @author wangym
 * @since 2021-10-27
 */
object BtUtils {
    const val TAG = "BtUtils"

    /**
     * sp文件名称
     */
    const val SP_NAME = "config"

    /**
     * MAC地址的KEY
     */
    const val MAC_KEY = "mac"

    enum class EVENT_TYPE(val type: String, val index: String) {
        /**
         * 点击事件
         */
        EVENT_CLICK("click", "1"),

        /**
         * 拖动事件
         */
        EVENT_DRAG("drag", "2"),

        /**
         * 模式切换事件
         */
        EVENT_SWITCH("switch", "3")
    }

    /**
     * 分割符号
     */
    private const val SPLIT = '|'

    /**
     * 完整包开始标记
     */
    private const val PACKAGE_FULL_START = '*'

    /**
     * 完整包结尾标记
     */
    private const val PACKAGE_FULL_END = '#'

    /**
     * 键盘输入事件
     */
    private const val INPUT_KEYBOARD = "1"

    /**
     * 交互事件
     */
    private const val EVENT_INTERACTIVE = "1"

    /**
     * 联想词事件
     */
    private const val EVENT_ASSOCIATE = "2"

    /**
     * 待联想词事件
     */
    private const val EVENT_ASSOCIATE_SOURCE = "3"

    /**
     * 输入事件
     */
    private const val EVENT_INPUT_SOURCE = "4"

    /**
     * 符号英文
     */
    const val MOD_F_EN = "1"

    /**
     * 数字英文
     */
    const val MOD_N_EN = "2"

    /**
     * 输入英文
     */
    const val MOD_I_EN = "3"

    /**
     * 符号中文
     */
    const val MOD_F_CN = "4"

    /**
     * 数字中文
     */
    const val MOD_N_CN = "5"

    /**
     * 输入中文
     */
    const val MOD_I_CN = "6"

    /**
     * 中间包
     */
    private var tempMsg: ByteArray? = null

    /**
     * 将交互事件转化为传输的数据
     * 第1位 包起始
     * 第2位 输入类型 1：键盘 2：鼠标
     * 第3位 事件分类 1：交互事件 2：联想词 3:待联想词 4:输入事件
     * 第4位 事件类型 1：click 2：drag 3：switch
     * 第5位开始 事件内容
     * 最后一位 包结束
     *
     * @param type 事件类型
     * @param content 事件内容
     *
     * @return 实际传输的数据
     */
    fun getSendMsgByEvent(type: EVENT_TYPE, content: String): String {
        // 默认是 完整包 键盘事件 交互事件
        var result = PACKAGE_FULL_START + INPUT_KEYBOARD + EVENT_INTERACTIVE
        // 添加事件类型
        result += type.index
        // 添加事件内容
        result += content
        // 添加完整包结尾
        result += PACKAGE_FULL_END
        return result
    }

    /**
     * 将待联想词事件转化为传输的数据
     * 第1位 包起始
     * 第2位 输入类型 1：键盘 2：鼠标
     * 第3位 事件分类 1：交互事件 2：联想词 3:待联想词 4:输入事件
     * 第4位开始 事件内容
     * 最后一位 包结束
     *
     * @param content 事件内容
     *
     * @return 实际传输的数据
     */
    fun getSendMsgByAssociateSourceEvent(content: String): String {
        // 默认是 完整包 键盘事件 待联想词事件
        var result = PACKAGE_FULL_START + INPUT_KEYBOARD + EVENT_ASSOCIATE_SOURCE
        // 添加事件内容
        result += content
        // 添加完整包结尾
        result += PACKAGE_FULL_END
        return result
    }

    /**
     * 将待联想词事件转化为传输的数据
     * 第1位 包起始
     * 第2位 输入类型 1：键盘 2：鼠标
     * 第3位 事件分类 1：交互事件 2：联想词 3:待联想词 4:输入事件
     * 第4位开始 事件内容
     * 最后一位 包结束
     *
     * @param content 事件内容
     *
     * @return 实际传输的数据
     */
    fun getSendMsgByInputSourceEvent(content: String): String {
        // 默认是 完整包 键盘事件 输入事件
        var result = PACKAGE_FULL_START + INPUT_KEYBOARD + EVENT_INPUT_SOURCE
        // 添加事件内容
        result += content
        // 添加完整包结尾
        result += PACKAGE_FULL_END
        return result
    }

    /**
     * 将联想词事件转化为传输的数据
     * 第1位 包起始
     * 第2位 输入类型 1：键盘 2：鼠标
     * 第3位 事件分类 1：交互事件 2：联想词 3:待联想词 4:输入事件
     * 第4位开始 联想词列表
     * 最后一位 包结束
     *
     * @param associateList 联想词列表
     * @return 实际传输的数据
     */
    fun getSendMsgByAssociateEvent(associateList: List<String>): String {
        // 默认是 完整包 键盘事件 交互事件
        var result = PACKAGE_FULL_START + INPUT_KEYBOARD + EVENT_ASSOCIATE
        // 添加联想词
        for (item in associateList.withIndex()) {
            if (item.index == associateList.size - 1) {
                result += item.value
            } else {
                result = result + item.value + SPLIT
            }
        }
        result += PACKAGE_FULL_END
        return result
    }

    /**
     * 根据传输过来的数据转化成对应对象
     *
     * @param receiveMsg 接收的数据
     *
     * @return 接收到的数据对象
     */
    fun getEventFromSendMsg(receiveMsg: ByteArray): Any? {
        d(TAG, "getEventFromSendMsg get msg = ${String(receiveMsg)}")
        val msg = String(receiveMsg)
        // 判断是否是包的起始
        if (msg[0] == PACKAGE_FULL_START) {
            // 收到包起始，清理之前的中间包
            tempMsg = null
            // 检查是否是完整包
            return if (msg[msg.lastIndex] == PACKAGE_FULL_END) {
                // 完整包直接进行解析
                val finalString = String(receiveMsg)
                return analysisMsg(finalString.substring(1, finalString.lastIndex))
            } else {
                // 等待后续的分包
                d(TAG, "getEventFromSendMsg wait packages1")
                tempMsg = receiveMsg
                null
            }
        } else if (msg[msg.lastIndex] == PACKAGE_FULL_END) {
            // 拼接成完整包直接进行解析
            tempMsg = byteArrayMerger(tempMsg!!, receiveMsg)
            // 如果最终拼接出来的包是完整的包直接进行解析
            return if (String(tempMsg!!)[0] == PACKAGE_FULL_START) {
                val finalString = String(tempMsg!!)
                return analysisMsg(finalString.substring(1, finalString.lastIndex))
            } else {
                // 存在包丢失的情况，直接丢弃
                e(TAG, "got package lost ,ignore cur package")
                null
            }
        } else {
            // 等待后续的分包
            tempMsg = byteArrayMerger(tempMsg!!, receiveMsg)
            d(TAG, "getEventFromSendMsg wait packages2")
            return null
        }
    }

    /**
     * 解析接收到的数据
     *
     * @param msg 数据
     *
     * @return 接收到数据的结构类型
     */
    private fun analysisMsg(msg: String): Any? {
        d(TAG, "start analysisMsg")
        d(TAG, "analysisMsg = $msg")
        if (TextUtils.isEmpty(msg)) {
            e(TAG, "got error input event : null")
            return null
        }
        if (msg[0].toString() != INPUT_KEYBOARD) {
            e(TAG, "got error input event : ${msg[0]}")
            return null
        }
        // 判断是否复合基本要求，基本要求为3字节
        if (msg.length < 3) {
            e(TAG, "got error input event msg : $msg")
            return null
        }
        // 判断事件分类
        if (msg[1].toString() == EVENT_INTERACTIVE) {
            // 交互事件
            // 判断需要解析的内容是否正常，交互事件，最小长度为4字节
            if (msg.length < 4) {
                e(TAG, "got error input EVENT_INTERACTIVE : $msg")
                return null
            }
            val keyEvent = KeyboardEvent()
            val event = BaseEvent(msg[2].toString(), msg.substring(3))
            keyEvent.event.add(event)
            return keyEvent
        } else if (msg[1].toString() == EVENT_ASSOCIATE) {
            // 联想词事件
            val assEvent = AssociateEvent()
            val temp = msg.substring(2)
            val list = temp.split(SPLIT)
            for (item in list.withIndex()) {
                val assItem = AssociateItem(item.value, item.index + 1)
                assEvent.associate.add(assItem)
            }
            return assEvent
        } else if (msg[1].toString() == EVENT_ASSOCIATE_SOURCE) {
            // 待联想词事件
            return AssociateSourceEvent(msg.substring(2))
        } else if (msg[1].toString() == EVENT_INPUT_SOURCE) {
            // 输入事件
            return InputSourceEvent(msg.substring(2))
        } else {
            e(TAG, "got error msg")
            return null
        }
    }

    /**
     * 保存连接的MAC
     *
     * @param mac 设备MAC
     * @param context 上下文
     */
    fun saveConnectMac(context: Context, mac: String) {
        val sharedPreferences: SharedPreferences =
            context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE)
        val edit = sharedPreferences.edit()
        edit.putString(MAC_KEY, mac)
        edit.apply()
    }

    /**
     * 获取连接的MAC
     *
     * @param context 上下文
     * @return 保存的设备MAC
     */
    fun getConnectMac(context: Context): String? {
        val sharedPreferences: SharedPreferences =
            context.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE)
        return sharedPreferences.getString(MAC_KEY, "")
    }

    /**
     * 合并byte[]
     */
    fun byteArrayMerger(bt1: ByteArray, bt2: ByteArray): ByteArray {
        val bt3 = ByteArray(bt1.size + bt2.size)
        System.arraycopy(bt1, 0, bt3, 0, bt1.size)
        System.arraycopy(bt2, 0, bt3, bt1.size, bt2.size)
        return bt3
    }
}