package com.iscs.bozzys.utils.ble

import com.iscs.bozzys.utils.crc16
import com.iscs.bozzys.utils.toByteArray
import java.nio.ByteBuffer
import java.nio.ByteOrder

object BleFrameExt {

    /**
     * 构建蓝牙设备获取设备token的操作
     */
    fun buildBLEGetTokenCMD(): BleFrame {
        return BleFrame(BleProtocol.REQ_GET_TOKEN, getUnixTime(), BleProtocol.RSP_GET_TOKEN)
    }

    /**
     * 构建蓝牙设备获取蓝牙设备电量
     */
    fun ByteArray.buildBLEGetPowerCMD(): BleFrame {
        return BleFrame(BleProtocol.REQ_POWER_STATUS, getUnixTime() + this, BleProtocol.RSP_POWER_STATUS)
    }

    /**
     * 构建蓝牙获取当前设备状态
     */
    fun ByteArray.buildBLEGetStatusCMD(): BleFrame {
        return BleFrame(BleProtocol.REQ_CURRENT_STATUS, getUnixTime() + this, BleProtocol.RSP_CURRENT_STATUS)
    }

    /**
     * 切换当前工作模式
     *
     * @param runMode 有效运行模式 WORK STBY
     */
    fun ByteArray.buildBLESwitchRunModeCMD(runMode: BleRunMode): BleFrame {
        var mode = 0x00
        if (runMode == BleRunMode.WORK) {
            mode = 0x01
        } else if (runMode == BleRunMode.STBY) {
            mode = 0x02
        }
        return BleFrame(
            BleProtocol.REQ_SWITCH_MODE,
            byteArrayOf(mode.toByte()) + getUnixTime() + this,
            BleProtocol.RSP_SWITCH_MODE
        )
    }

    /**
     * 构建用于对蓝牙设备进行关机的命令，因为设备即关机无任何响应需要处理
     */
    fun ByteArray.buildBLEPowerOffCMD(): BleFrame {
        return BleFrame(BleProtocol.REQ_POWER_OFF, byteArrayOf(0x02) + getUnixTime() + this, BleProtocol.RSP_POWER_OFF)
    }

    /**
     * 构建用于作业票下发的指令集合
     */
    fun ByteArray.buildBLETicketDataCMDList(json: String): List<BleFrame> {
        val cmds = ArrayList<BleFrame>()
        // 先将数据转换为字节数组
        val pkg = json.toByteArray()
        // 包大小
        val pkgSize = pkg.size
        // 分包数
        val pkgCount = (pkgSize + 128 - 1) / 128
        for (idx in 0 until pkgCount) {
            val endIdx = if ((idx + 1) == pkgCount) pkgSize else ((idx + 1) * 128)
            // 将包做切片操作
            val subPkg = pkg.copyOfRange(idx * 128, endIdx)
            // 封装数据包操作
            val data = pkgCount.toByteArray() + idx.toByteArray() + subPkg.crc16(
                0,
                subPkg.size
            ) + subPkg.size.toByteArray() + subPkg
            // 装包处理
            cmds.add(
                BleFrame(
                    BleProtocol.REQ_SEND_WORK_TICKET,
                    (data.size + 1).toByteArray(1) + 0x02.toByteArray(1) + data + getUnixTime() + this,
                    BleProtocol.RSP_SEND_WORK_TICKET,
                    BleProtocol.WRITE_UUID
                )
            )
        }
        return cmds
    }

    /**
     * 构建获取作业票信息命令
     */
    fun ByteArray.buildBLEGetTicketInfoCMD(idx: Int = 0, pkgTotal: Int = 0): BleFrame {
        if (idx > 0) {
            return BleFrame(
                BleProtocol.REQ_WORK_TICKET_RESULT_PART,
                idx.toByteArray() + pkgTotal.toByteArray() + byteArrayOf(0x00) + getUnixTime() + this,
                BleProtocol.RSP_WORK_TICKET_RESULT
            )
        }
        return BleFrame(BleProtocol.REQ_WORK_TICKET_RESULT, getUnixTime() + this, BleProtocol.RSP_WORK_TICKET_RESULT)
    }

    /**
     * 获取token
     */
    fun BleFrame.getToken(): ByteArray {
        if (this.rspCode.contentEquals(BleProtocol.RSP_GET_TOKEN)) {
            return this.data
        }
        return byteArrayOf()
    }

    /**
     * 获取当前运行模式
     */
    fun BleFrame.getRunMode(): BleRunMode {
        if (this.rspCode.contentEquals(BleProtocol.RSP_CURRENT_STATUS)) {
            return when (this.data[0]) {
                0x01.toByte() -> BleRunMode.WORK
                0x02.toByte() -> BleRunMode.STBY
                0x03.toByte() -> BleRunMode.FAILURE
                else -> BleRunMode.NONE
            }
        }
        return BleRunMode.NONE
    }

    /**
     * 获取当前设备电量
     */
    fun BleFrame.getPower(): Int {
        if (this.rspCode.contentEquals(BleProtocol.RSP_POWER_STATUS)) {
            return this.data[0].toInt()
        }
        return -1
    }

    /**
     * 获取当前工作模式切换是否成功
     */
    fun BleFrame.getSwitchRunModeResult(): Boolean {
        if (this.rspCode.contentEquals(BleProtocol.RSP_SWITCH_MODE)) {
            return this.data[1].toInt() == 1
        }
        return false
    }

    /**
     * 响应发送工作票结果
     *
     * @return 0-成功 1-失败 2-超时 13-idx超出范围
     */
    fun BleFrame.getSendTicketResult(): Int {
        if (this.rspCode.contentEquals(BleProtocol.RSP_SEND_WORK_TICKET)) {
            return this.data[4].toInt()
        }
        return 99
    }

    fun BleFrame.getTicketPackageInfo(): BleTicketDataPackage {
        if (this.rspCode.contentEquals(BleProtocol.RSP_WORK_TICKET_RESULT)) {
            // 解析数据
            val pkgCount = this.data[2] + this.data[3]
            val pkgIdx = this.data[4] + this.data[5]
            val pkgSize = this.data[8].toUByte() + this.data[9].toUByte()
            val pkgData = this.data.copyOfRange(10, pkgSize.toInt() + 10)
            // ISCSLog.i("getTicketPackageInfo", "包信息：总包数：$pkgCount, 当前包：$pkgIdx, 当前包大小：$pkgSize, 当前包数据：${pkgData.byteArrayToHexString("")}")
            return BleTicketDataPackage(pkgIdx, pkgSize.toInt(), pkgData, pkgCount)
        }
        return BleTicketDataPackage(0, 0, byteArrayOf(), 0)
    }

}

private fun getUnixTime(): ByteArray {
    val tempArr = (System.currentTimeMillis() / 1000).toByteArray()
    val timeStampArr = byteArrayOf(tempArr[0], tempArr[1], tempArr[2], tempArr[3])
    return timeStampArr
}

private fun Long.toByteArray(): ByteArray {
    return ByteBuffer.allocate(java.lang.Long.BYTES)
        .order(ByteOrder.LITTLE_ENDIAN)
        .putLong(this).array()
}