package com.narutohuo.xindazhou.ble.util

import com.narutohuo.xindazhou.ble.model.Command
import com.narutohuo.xindazhou.ble.model.Packet

/**
 * ByteArray 扩展函数
 */

/**
 * 将 ByteArray 按分包协议解析为 Packet 对象
 */
fun ByteArray.parsePacket(): Packet {
    require(this.size >= 13) { "分包字节数组长度不足，最少需要 13 字节（不含 data）" }
    
    var offset = 0
    val header = this[offset++]
    
    // businessId 为 4 字节（大端序）
    val businessId = ((this[offset].toLong() and 0xFF) shl 24) or
            ((this[offset + 1].toLong() and 0xFF) shl 16) or
            ((this[offset + 2].toLong() and 0xFF) shl 8) or
            (this[offset + 3].toLong() and 0xFF)
    offset += 4
    
    // totalPackets、packetSeq、dataLength 均为 2 字节（大端序）
    val totalPackets = ((this[offset].toInt() and 0xFF) shl 8 or
            (this[offset + 1].toInt() and 0xFF)).toUShort()
    offset += 2
    
    val packetSeq = ((this[offset].toInt() and 0xFF) shl 8 or
            (this[offset + 1].toInt() and 0xFF)).toUShort()
    offset += 2
    
    val dataLength = ((this[offset].toInt() and 0xFF) shl 8 or
            (this[offset + 1].toInt() and 0xFF)).toUShort()
    offset += 2
    
    // 检查 data 区长度是否匹配
    require(this.size >= offset + dataLength.toInt() + 3) {
        "实际字节数组长度不足 dataLength(${dataLength}) + responseStatus + checksum + tail"
    }
    
    val data = this.copyOfRange(offset, offset + dataLength.toInt())
    offset += dataLength.toInt()
    
    val responseStatus = this[offset++]
    val checksum = this[offset++]
    val tail = this[offset]
    
    return Packet(
        header = header,
        businessId = businessId.toUInt(),
        totalPackets = totalPackets,
        packetSeq = packetSeq,
        dataLength = dataLength,
        data = data,
        responseStatus = responseStatus,
        checksum = checksum,
        tail = tail
    )
}

/**
 * 将 ByteArray 按指令协议解析为 Command 对象
 */
fun ByteArray.parseCommand(): Command {
    require(this.size >= 7) { "指令字节数组长度不足，最少需要 7 字节（不含 data）" }
    
    var offset = 0
    val address = this[offset++]
    val protocolVersion = this[offset++]
    val timezone = this[offset++]
    val encryptionFlag = this[offset++]
    val operatingSystem = this[offset++]
    
    // dataLength 为 2 字节（大端序）
    val dataLength = ((this[offset].toInt() and 0xFF) shl 8 or
            (this[offset + 1].toInt() and 0xFF)).toUShort()
    offset += 2
    
    // 检查 data 区长度是否匹配
    require(this.size >= offset + dataLength.toInt() + 1) {
        "实际字节数组长度不足 dataLength(${dataLength}) + checksum"
    }
    
    val data = this.copyOfRange(offset, offset + dataLength.toInt())
    offset += dataLength.toInt()
    
    val checksum = this[offset]
    
    return Command(
        address = address,
        protocolVersion = protocolVersion,
        timezone = timezone,
        encryptionFlag = encryptionFlag,
        operatingSystem = operatingSystem,
        dataLength = dataLength,
        data = data,
        checksum = checksum
    )
}

/**
 * ByteArray 转十六进制字符串
 */
@OptIn(ExperimentalStdlibApi::class)
fun ByteArray.toHexString(): String {
    return this.joinToString("") { "%02X".format(it) }
}

/**
 * 十六进制字符串转 ByteArray
 */
@OptIn(ExperimentalStdlibApi::class)
fun String.hexToByteArray(): ByteArray {
    require(this.length % 2 == 0) { "Hex string length must be even" }
    val result = ByteArray(this.length / 2)
    for (i in result.indices) {
        val idx = i * 2
        result[i] = ((hexCharToInt(this[idx]) shl 4) + hexCharToInt(this[idx + 1])).toByte()
    }
    return result
}

private fun hexCharToInt(c: Char): Int = when (c) {
    in '0'..'9' -> c - '0'
    in 'a'..'f' -> c - 'a' + 10
    in 'A'..'F' -> c - 'A' + 10
    else -> throw IllegalArgumentException("Invalid hex char: $c")
}

/**
 * Int 转偶数位十六进制字符串
 */
fun Int.toEvenHex(): String {
    var hex = Integer.toHexString(this)
    if (hex.length % 2 != 0) {
        hex = "0" + hex
    }
    return hex
}

