package com.usky.ems.protocol;

import lombok.Data;

/**
 * 网络层数据包
 * 格式：Head(2字节) + Type(1字节) + Length(4字节) + Data(变长)
 *
 * @author system
 * @since 2024-01-01
 */
@Data
public class NetworkPacket {

    /**
     * 消息头，固定值0x1F1F
     */
    public static final short HEAD = 0x1F1F;

    /**
     * 消息类型：身份认证
     */
    public static final byte TYPE_AUTH = 0x01;

    /**
     * 消息类型：心跳
     */
    public static final byte TYPE_HEARTBEAT = 0x02;

    /**
     * 消息类型：能耗数据
     */
    public static final byte TYPE_ENERGY_DATA = 0x03;

    /**
     * 消息类型
     */
    private byte type;

    /**
     * 数据体（加密后的字节数组）
     */
    private byte[] data;

    /**
     * 将数据包编码为字节数组
     *
     * @return 编码后的字节数组
     */
    public byte[] encode() {
        int dataLength = data != null ? data.length : 0;
        int totalLength = 2 + 1 + 4 + dataLength; // Head + Type + Length + Data
        
        byte[] packet = new byte[totalLength];
        int offset = 0;
        
        // Head (2字节，网络字节序，高位在前)
        packet[offset++] = (byte) ((HEAD >> 8) & 0xFF);
        packet[offset++] = (byte) (HEAD & 0xFF);
        
        // Type (1字节)
        packet[offset++] = type;
        
        // Length (4字节，网络字节序，高位在前)
        packet[offset++] = (byte) ((dataLength >> 24) & 0xFF);
        packet[offset++] = (byte) ((dataLength >> 16) & 0xFF);
        packet[offset++] = (byte) ((dataLength >> 8) & 0xFF);
        packet[offset++] = (byte) (dataLength & 0xFF);
        
        // Data
        if (data != null && dataLength > 0) {
            System.arraycopy(data, 0, packet, offset, dataLength);
        }
        
        return packet;
    }

    /**
     * 从字节数组解码数据包
     *
     * @param bytes 字节数组
     * @return 解码后的数据包
     */
    public static NetworkPacket decode(byte[] bytes) {
        if (bytes == null || bytes.length < 7) {
            throw new IllegalArgumentException("数据包长度不足");
        }
        
        int offset = 0;
        
        // 验证Head
        short head = (short) (((bytes[offset++] & 0xFF) << 8) | (bytes[offset++] & 0xFF));
        if (head != HEAD) {
            throw new IllegalArgumentException("无效的消息头: " + String.format("0x%04X", head));
        }
        
        NetworkPacket packet = new NetworkPacket();
        
        // Type
        packet.type = bytes[offset++];
        
        // Length
        int length = ((bytes[offset++] & 0xFF) << 24) |
                     ((bytes[offset++] & 0xFF) << 16) |
                     ((bytes[offset++] & 0xFF) << 8) |
                     (bytes[offset++] & 0xFF);
        
        // Data
        if (length > 0) {
            if (bytes.length < offset + length) {
                throw new IllegalArgumentException("数据包长度不足，期望: " + (offset + length) + ", 实际: " + bytes.length);
            }
            packet.data = new byte[length];
            System.arraycopy(bytes, offset, packet.data, 0, length);
        }
        
        return packet;
    }
}
