package com.narutohuo.xindazhou.ble.util

import com.narutohuo.xindazhou.ble.config.BLEConstants
import com.narutohuo.xindazhou.ble.model.BLEEncryptedData
import com.narutohuo.xindazhou.ble.model.Command
import kotlin.experimental.xor

/**
 * BLE数据包解析器
 * 
 * 负责解析从设备接收的数据包
 * 处理解密、校验、数据提取等
 */
class BLEPacketParser {
    
    /**
     * 解析完整数据包（包含包头包尾）
     * 
     * @param packet 接收到的数据包（包含包头包尾）
     * @param encryptKey 解密密钥（16字节），如果为null则不解密
     * @return 解析后的Command对象，如果解析失败返回null
     */
    fun parseFullPacket(packet: ByteArray, encryptKey: ByteArray? = null): Command? {
        // 1. 校验包头包尾
        if (packet.isEmpty() || packet[0] != BLEConstants.PACKET_HEAD) {
            return null
        }
        if (packet[packet.size - 1] != BLEConstants.PACKET_TAIL) {
            return null
        }
        
        // 2. 提取数据包内容（去掉包头包尾）
        val packetContent = packet.sliceArray(1 until packet.size - 1)
        
        // 3. 解析数据包内容
        return parsePacket(packetContent, encryptKey)
    }
    
    /**
     * 解析数据包（不包含包头包尾）
     * 
     * @param packet 接收到的数据包（不包含包头包尾）
     * @param encryptKey 解密密钥（16字节），如果为null则不解密
     * @return 解析后的Command对象，如果解析失败返回null
     */
    fun parsePacket(packet: ByteArray, encryptKey: ByteArray? = null): Command? {
        if (packet.size < 7) {
            return null
        }
        
        var offset = 0
        
        // 地址
        val address = packet[offset++]
        
        // 协议版本
        val protocolVersion = packet[offset++]
        
        // 时区
        val timezone = packet[offset++]
        
        // 加密标志
        val encryptionFlag = packet[offset++]
        
        // 操作系统
        val operatingSystem = packet[offset++]
        
        // 数据长度（2字节，大端序）
        val dataLength = ((packet[offset].toInt() and 0xFF) shl 8) or
                        (packet[offset + 1].toInt() and 0xFF)
        offset += 2
        
        // 检查数据长度
        if (packet.size < offset + dataLength + 1) {
            return null
        }
        
        // 提取加密数据
        val encryptedData = packet.sliceArray(offset until offset + dataLength)
        offset += dataLength
        
        // 校验位
        val checksum = packet[offset]
        
        // 校验校验位
        if (!verifyChecksum(packet, checksum)) {
            return null
        }
        
        // 解密数据（如果需要）
        val decryptedData = if (encryptKey != null && encryptionFlag == BLEConstants.ENCRYPT_FLAG_ENCRYPTED) {
            try {
                BLECrypto.decrypt(encryptedData, encryptKey)
            } catch (e: Exception) {
                return null
            }
        } else {
            encryptedData
        }
        
        return Command(
            address = address,
            protocolVersion = protocolVersion,
            timezone = timezone,
            encryptionFlag = encryptionFlag,
            operatingSystem = operatingSystem,
            dataLength = dataLength.toUShort(),
            data = decryptedData,
            checksum = checksum
        )
    }
    
    /**
     * 解析数据加密区
     * 按照协议：时间戳（4字节）+ 功能码（1字节）+ 指令类型（1字节）+ 应用数据
     * 
     * @param data 解密后的数据加密区
     * @return 解析后的BLEEncryptedData对象
     */
    fun parseEncryptedData(data: ByteArray): BLEEncryptedData? {
        if (data.size < 6) {
            return null
        }
        
        var offset = 0
        
        // 时间戳（4字节，大端序）
        val timestamp = ((data[offset].toInt() and 0xFF) shl 24) or
                       ((data[offset + 1].toInt() and 0xFF) shl 16) or
                       ((data[offset + 2].toInt() and 0xFF) shl 8) or
                       (data[offset + 3].toInt() and 0xFF)
        offset += 4
        
        // 功能码
        val functionCode = data[offset++]
        
        // 指令类型
        val instructionType = data[offset++]
        
        // 应用数据
        val applicationData = data.sliceArray(offset until data.size)
        
        return BLEEncryptedData(
            timestamp = timestamp.toLong(),
            functionCode = functionCode,
            instructionType = instructionType,
            applicationData = applicationData
        )
    }
    
    /**
     * 校验校验位
     * 从地址开始（跳过包头），到校验位前一位
     */
    private fun verifyChecksum(packet: ByteArray, expectedChecksum: Byte): Boolean {
        var checksum: Byte = 0x00
        // 从地址开始，到校验位前一位
        for (i in 0 until packet.size - 1) {
            checksum = checksum.xor(packet[i])
        }
        return checksum == expectedChecksum
    }
}

