package com.narutohuo.xindazhou.ble.util

import java.util.Arrays
import kotlin.experimental.xor

/**
 * BLE分包处理器
 * 
 * 处理数据包的分包和组包
 * 根据新大洲本田蓝牙协议文档的分包协议（第3节）
 */
class BLEPacketSplitter(
    /**
     * 包头（默认0x0A）
     */
    private val header: Byte = 0x0A.toByte(),
    
    /**
     * 包尾（默认0x0D）
     */
    private val footer: Byte = 0x0D.toByte(),
    
    /**
     * 单个包最大业务数据长度（不含协议头尾）
     * 建议 ≤ 20（符合 BLE 单次写入限制）
     */
    private val maxPayloadPerPacket: Int = 20
) {
    
    /**
     * 生成分包列表
     * 
     * @param rawData 待发送的完整指令数据（不包含分包协议头尾）
     * @param businessId 业务标识（4字节），最后一个字节会在调用时被设置为0x01（请求）或0x02（响应）
     * @param isRequest true → 请求（业务ID 低两位 01），false → 响应（业务ID 低两位 02）
     * @return List<ByteArray> 每个元素即为一个完整的 BLE 分包
     */
    fun split(
        rawData: ByteArray,
        businessId: ByteArray,
        isRequest: Boolean = true
    ): List<ByteArray> {
        // 业务ID 低两位：01 请求，02 响应
        val idLow: Byte = if (isRequest) 0x01 else 0x02
        
        // 复制 businessId 并设置最后一位
        val fullBusinessId = businessId.copyOf()
        if (fullBusinessId.size >= 4) {
            fullBusinessId[3] = idLow
        }
        
        // 计算总包数
        val totalPackets = (rawData.size + maxPayloadPerPacket - 1) / maxPayloadPerPacket
        require(totalPackets <= 255) { "单次发送的包数不能超过 255（单字节表示）" }
        
        val packets = mutableListOf<ByteArray>()
        
        for (seq in 0 until totalPackets) {
            // 取出本包的数据片段
            val start = seq * maxPayloadPerPacket
            val end = minOf(start + maxPayloadPerPacket, rawData.size)
            val payload = rawData.sliceArray(start until end)
            
            // 构造单包
            // 包体长度 = 1(header) + 4(businessId) + 2(total) + 2(seq) + 2(len) + N(data) + 1(responseStatus) + 1(checksum) + 1(footer)
            val packet = ByteArray(14 + payload.size)
            var idx = 0
            packet[idx++] = header                     // 包头
            packet[idx++] = fullBusinessId[0]          // 业务ID
            packet[idx++] = fullBusinessId[1]          // 业务ID
            packet[idx++] = fullBusinessId[2]          // 业务ID
            packet[idx++] = fullBusinessId[3]          // 业务ID
            // 总包数（大端序）
            packet[idx++] = (totalPackets shr 8).toByte()
            packet[idx++] = totalPackets.toByte()
            // 包序号（大端序）
            packet[idx++] = (seq shr 8).toByte()
            packet[idx++] = seq.toByte()
            // 数据长度（大端序）
            packet[idx++] = (payload.size shr 8).toByte()
            packet[idx++] = payload.size.toByte()
            // 数据区
            payload.copyInto(packet, destinationOffset = idx)
            idx += payload.size
            packet[idx++] = 0x00.toByte()             // 应答状态（发送时设为0，接收时填充）
            // 包校验（异或所有前面的字节，不包含包头）
            packet[idx++] = calculateXorChecksum(packet, 1, idx)
            // 包尾
            packet[idx] = footer
            
            packets.add(packet)
        }
        
        return packets
    }
    
    /**
     * 生成仅携带 ACK/REX 状态的响应包
     * 
     * @param requestSeq 请求报文的序号（从收到的报文中解析）
     * @param businessId 原业务标识（4 字节），低两位会被强制置为 0x02（响应）
     * @param value 收到的请求包数据（用于校验）
     * @return 完整的 BLE 响应报文
     */
    fun createResponsePacket(requestSeq: Int, businessId: ByteArray, value: ByteArray): ByteArray {
        // 业务 ID 低两位改为 0x02（响应）
        val responseBusinessId = businessId.copyOf()
        if (responseBusinessId.size >= 4) {
            responseBusinessId[3] = 0x02
        }
        val totalPackets = 1               // 只发一包
        val payloadLen = 0                 // 无业务数据
        
        // 包体长度 = header(1) + businessId(4) + total(2) + seq(2) + len(2) + status(1) + checksum(1) + footer(1) = 14
        val packet = ByteArray(14)
        var idx = 0
        packet[idx++] = header
        packet[idx++] = responseBusinessId[0]
        packet[idx++] = responseBusinessId[1]
        packet[idx++] = responseBusinessId[2]
        packet[idx++] = responseBusinessId[3]
        
        // total‑packets（大端序）
        packet[idx++] = (totalPackets shr 8).toByte()
        packet[idx++] = totalPackets.toByte()
        
        // seq‑number（保持请求的 seq，大端序）
        packet[idx++] = (requestSeq shr 8).toByte()
        packet[idx++] = requestSeq.toByte()
        
        // payload length = 0（大端序）
        packet[idx++] = (payloadLen shr 8).toByte()
        packet[idx++] = payloadLen.toByte()
        
        // 计算校验和（从收到的包中提取）
        val checkSumArray = Arrays.copyOfRange(value, 1, value.size - 3)
        val calculatedChecksum = calculateXorChecksum(checkSumArray, 1, checkSumArray.size)
        val receivedChecksum = value[value.size - 2]
        
        // 状态位：如果校验通过则为0x01（ACK），否则为0x02（REX）
        val status: Byte = if (calculatedChecksum == receivedChecksum) {
            0x01.toByte()
        } else {
            0x02.toByte()
        }
        packet[idx++] = status
        
        // checksum（异或 Header 之后到状态位）
        packet[idx++] = calculateXorChecksum(packet, 1, idx)
        
        // footer
        packet[idx] = footer
        return packet
    }
    
    /**
     * 简单的异或校验
     */
    private fun calculateXorChecksum(buf: ByteArray, start: Int, endExclusive: Int): Byte {
        var chk: Byte = 0x00
        for (i in start until endExclusive) {
            chk = chk.xor(buf[i])
        }
        return chk
    }
}

