/**
 * PacketDef.kt
 * SkyLink Android 端 - 网络协议定义
 *
 * 对应 C++ protocol.h 的 Kotlin 实现
 *
 * @author flowzl
 * @date 2026-01-19
 */

package com.skylink.app.network

import java.nio.ByteBuffer
import java.nio.ByteOrder
import kotlin.math.min

// ============================================================================
// 协议常量
// ============================================================================

/** 数据包魔数 */
const val SKYLINK_MAGIC: Short = 0xAA55.toShort()

/** UDP 最大包大小 */
const val MAX_UDP_PACKET_SIZE = 1472

/** 包头大小 */
const val PACKET_HEADER_SIZE = 50

/** 最大载荷大小 */
const val MAX_PAYLOAD_SIZE = MAX_UDP_PACKET_SIZE - PACKET_HEADER_SIZE

/** UDP 接收缓冲区大小 */
const val RX_BUFFER_SIZE = 65536

/** 最大分片数 */
const val MAX_CHUNKS = 1000

/** 帧超时时间 (毫秒) */
const val FRAME_TIMEOUT_MS = 5000L

// ============================================================================
// 数据类定义
// ============================================================================

/**
 * SkyLink UDP 包头
 *
 * 字段顺序和大小必须与 C++ protocol.h 的 PacketHeader 一致
 */
data class SkyLinkPacketHeader(
    val magic: Short,              // 0xAA55
    val frameId: Int,              // 帧ID (4 bytes)
    val totalChunks: Short,        // 总分片数 (2 bytes)
    val chunkIndex: Short,         // 当前分片索引 (2 bytes)
    val dataLen: Short,            // 载荷长度 (2 bytes)
    val timestamp: Double,         // 时间戳 (8 bytes)
    val lat: Double,               // 纬度 (8 bytes)
    val lon: Double,               // 经度 (8 bytes)
    val alt: Double,               // 海拔 (8 bytes)
    val crc16: Short,              // 校验码 (2 bytes)
    val reserve: Int               // 预留 (4 bytes)
) {
    companion object {
        /**
         * 从 ByteArray 解析包头
         */
        fun fromByteArray(data: ByteArray): SkyLinkPacketHeader? {
            if (data.size < PACKET_HEADER_SIZE) {
                return null
            }

            val buffer = ByteBuffer.wrap(data, 0, PACKET_HEADER_SIZE)
            buffer.order(ByteOrder.LITTLE_ENDIAN)  // ARM 平台使用小端序

            return try {
                SkyLinkPacketHeader(
                    magic = buffer.short,
                    frameId = buffer.int,
                    totalChunks = buffer.short,
                    chunkIndex = buffer.short,
                    dataLen = buffer.short,
                    timestamp = buffer.double,
                    lat = buffer.double,
                    lon = buffer.double,
                    alt = buffer.double,
                    crc16 = buffer.short,
                    reserve = buffer.int
                )
            } catch (e: Exception) {
                e.printStackTrace()
                null
            }
        }

        /**
         * 将包头转为 ByteArray
         */
        fun toByteArray(header: SkyLinkPacketHeader): ByteArray {
            val buffer = ByteBuffer.allocate(PACKET_HEADER_SIZE)
            buffer.order(ByteOrder.LITTLE_ENDIAN)

            buffer.putShort(header.magic)
            buffer.putInt(header.frameId)
            buffer.putShort(header.totalChunks)
            buffer.putShort(header.chunkIndex)
            buffer.putShort(header.dataLen)
            buffer.putDouble(header.timestamp)
            buffer.putDouble(header.lat)
            buffer.putDouble(header.lon)
            buffer.putDouble(header.alt)
            buffer.putShort(header.crc16)
            buffer.putInt(header.reserve)

            return buffer.array()
        }
    }

    /** 验证包头合法性 */
    fun isValid(): Boolean {
        return magic == SKYLINK_MAGIC &&
               chunkIndex < totalChunks &&
               dataLen > 0 &&
               dataLen <= MAX_PAYLOAD_SIZE
    }

    /** 获取载荷大小 */
    fun getPayloadSize(): Int = dataLen.toInt()
}

/**
 * 完整的 UDP 数据包
 */
data class SkyLinkPacket(
    val header: SkyLinkPacketHeader,
    val payload: ByteArray
) {
    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false

        other as SkyLinkPacket

        if (header != other.header) return false
        return payload.contentEquals(other.payload)
    }

    override fun hashCode(): Int {
        var result = header.hashCode()
        result = 31 * result + payload.contentHashCode()
        return result
    }

    /** 获取完整的包大小 */
    fun getTotalSize(): Int = PACKET_HEADER_SIZE + payload.size
}

/**
 * 完整的图像帧 (所有分片都已接收且解码)
 */
data class DecodedFrame(
    val frameId: Int,
    val imageData: ByteArray,      // JPEG 数据
    val timestamp: Double,
    val lat: Double,
    val lon: Double,
    val alt: Double,
    val receivedTime: Long = System.currentTimeMillis()
) {
    override fun equals(other: Any?): Boolean {
        if (this === other) return true
        if (javaClass != other?.javaClass) return false

        other as DecodedFrame

        if (frameId != other.frameId) return false
        if (!imageData.contentEquals(other.imageData)) return false
        if (timestamp != other.timestamp) return false
        if (lat != other.lat) return false
        if (lon != other.lon) return false
        if (alt != other.alt) return false
        if (receivedTime != other.receivedTime) return false

        return true
    }

    override fun hashCode(): Int {
        var result = frameId
        result = 31 * result + imageData.contentHashCode()
        result = 31 * result + timestamp.hashCode()
        result = 31 * result + lat.hashCode()
        result = 31 * result + lon.hashCode()
        result = 31 * result + alt.hashCode()
        result = 31 * result + receivedTime.hashCode()
        return result
    }
}

/**
 * 帧缓冲区 (用于重组分片)
 */
data class FrameBuffer(
    val frameId: Int,
    val totalChunks: Short,
    val chunks: MutableMap<Int, ByteArray> = mutableMapOf(),
    val timestamp: Double = 0.0,
    val lat: Double = 0.0,
    val lon: Double = 0.0,
    val alt: Double = 0.0,
    val receiveTimestamp: Long = System.currentTimeMillis()
) {
    /**
     * 检查是否所有分片都已接收
     */
    fun isComplete(): Boolean {
        // 使用计数器而不是遍历，O(1) 复杂度
        return chunks.size == totalChunks.toInt()
    }

    /**
     * 将所有分片合并为完整的 JPEG 数据
     */
    fun merge(): ByteArray {
        var totalLen = 0
        for (i in 0 until totalChunks) {
            val chunkLen = chunks[i.toInt()]?.size ?: 0
            totalLen += chunkLen
        }

        val result = ByteArray(totalLen)
        var offset = 0
        for (i in 0 until totalChunks) {
            val chunk = chunks[i.toInt()]
            if (chunk != null) {
                System.arraycopy(chunk, 0, result, offset, chunk.size)
                offset += chunk.size
            }
        }
        return result
    }

    /**
     * 检查是否已超时
     */
    fun isTimeout(): Boolean {
        return System.currentTimeMillis() - receiveTimestamp > FRAME_TIMEOUT_MS
    }
}

// ============================================================================
// 辅助函数
// ============================================================================

/**
 * 计算 CRC16 校验码
 */
fun calculateCrc16(data: ByteArray): Short {
    var crc = 0xFFFF
    for (byte in data) {
        crc = crc xor ((byte.toInt() and 0xFF) shl 8)
        for (j in 0 until 8) {
            crc = if (crc and 0x8000 != 0) {
                ((crc shl 1) xor 0x1021) and 0xFFFF
            } else {
                (crc shl 1) and 0xFFFF
            }
        }
    }
    return crc.toShort()
}

/**
 * 验证 SkyLink 数据包合法性
 */
fun isValidSkyLinkPacket(header: SkyLinkPacketHeader): Boolean {
    return header.isValid()
}
