package com.narutohuo.xindazhou.ble.model

import kotlin.experimental.xor

/**
 * 指令协议数据类
 * 
 * 按照协议文档"数据下行"结构定义（不包含包头包尾，因为分包协议会处理）
 */
data class Command(
    /**
     * 地址（1字节）
     * APP地址为0x0F，仪表地址为0x0A，中控地址为0x05
     */
    val address: Byte,
    
    /**
     * 协议版本（1字节）
     * 初始v1.0 0x01
     */
    val protocolVersion: Byte,
    
    /**
     * 时区（1字节）
     * 单位小时
     */
    val timezone: Byte,
    
    /**
     * 加密标志（1字节）
     * 0x00=不加密，0x01=加密
     */
    val encryptionFlag: Byte,
    
    /**
     * 操作系统（1字节）
     * Android:0x01, iOS:0x02
     */
    val operatingSystem: Byte,
    
    /**
     * 数据长度（2字节，无符号短整型）
     * 数据加密区长度
     */
    val dataLength: UShort,
    
    /**
     * 数据区（dataLength 大小的字节数组）
     * 存放加密数据（时间戳+功能码+指令类型+应用数据）
     */
    val data: ByteArray,
    
    /**
     * 校验和（1字节）
     * 异或校验，从地址到数据区结束
     */
    val checksum: Byte
) {
    /**
     * 计算校验和（按字节异或）
     */
    fun computeChecksum(): Byte {
        var sum: Byte = 0
        sum = sum xor address
        sum = sum xor protocolVersion
        sum = sum xor timezone
        sum = sum xor encryptionFlag
        sum = sum xor operatingSystem
        sum = sum xor (dataLength.toInt() and 0xFF).toByte()
        sum = sum xor ((dataLength.toInt() shr 8) and 0xFF).toByte()
        data.forEach { sum = sum xor it }
        return sum
    }
    
    /**
     * 校验当前对象的 checksum 是否正确
     */
    fun isValid(): Boolean = checksum == computeChecksum()
    
    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false

        other as Command

        if (address != other.address) return false
        if (protocolVersion != other.protocolVersion) return false
        if (timezone != other.timezone) return false
        if (encryptionFlag != other.encryptionFlag) return false
        if (operatingSystem != other.operatingSystem) return false
        if (dataLength != other.dataLength) return false
        if (!data.contentEquals(other.data)) return false
        if (checksum != other.checksum) return false

        return true
    }

    override fun hashCode(): Int {
        var result = address.toInt()
        result = 31 * result + protocolVersion.toInt()
        result = 31 * result + timezone.toInt()
        result = 31 * result + encryptionFlag.toInt()
        result = 31 * result + operatingSystem.toInt()
        result = 31 * result + dataLength.hashCode()
        result = 31 * result + data.contentHashCode()
        result = 31 * result + checksum.toInt()
        return result
    }
}

