package com.nokia.sms.message;

import java.util.Arrays;

import com.nokia.common.io.ByteArrayUtil;
import com.nokia.sms.entity.CommandId;
import com.nokia.sms.exception.ParseException;

import lombok.Data;

/**
 * Message Length 4 Unsigned Integer 消息长度：消息包的总长度(字节)
 * Command ID 4 Unsigned Integer 消息类型：表明此条消息的类型，采用固定值
 * Sequence Number 4 Unsigned Integer
 * 此字段表示消息的序列号，它由请求发起端产生，是消息和它的应答之间的对应标志。数值在0到0XFFFFFFFF间必须保证严格单调的递增，当达到0XFFFFFFFF时，从0开始下一循环。
 */
@Data
public class MessageHeader {
    // 协议为无符号int 但是实际情况都不超过int
    private int messageLength;
    /**
     * Command_Id定义
     * SMIT_BIND 0x00000001 绑定请求
     * SMIT_BIND_RESP 0x80000001 绑定应答
     * SMIT_ACTIVE_TEST 0x0000000f 链路检测
     * SMIT_ACTIVE_TEST_RESP 0x8000000f 链路检测应答
     * SMIT_DELBLK 0x00000003 解除黑名单请求
     * SMIT_DELBLK_RESP 0x80000003 解除黑名单应答
     */
    private CommandId commandId;
    private long sequenceNumber;

    public byte[] toByteArray() {
        byte[] header = new byte[12];
        // messageLength
        System.arraycopy(ByteArrayUtil.toByteArray(messageLength), 0, header, 0, 4);
        // commandId
        System.arraycopy(ByteArrayUtil.toByteArray(commandId.value), 4, header, 4, 4);
        // sequenceNumber
        System.arraycopy(ByteArrayUtil.toByteArray(sequenceNumber), 4, header, 8, 4);
        return header;
    }

    public static MessageHeader parse(byte[] message) throws ParseException {
        if (message.length < 12) {
            throw new ParseException("message header 必须包含12个字节。");
        }
        // 获取前12个字节作为header
        byte[] header = Arrays.copyOf(message, 12);
        MessageHeader messageHeader = new MessageHeader();
        // messageLength
        messageHeader.setMessageLength(ByteArrayUtil.parseInteger(header, 0));
        // commandId
        long commandIdValue = ByteArrayUtil.parseUnsignedInteger(header, 4);
        CommandId commandId = CommandId.parse(commandIdValue);
        if (null == commandId) {
            throw new ParseException("无法识别 Command_Id : " + commandIdValue);
        }
        messageHeader.setCommandId(commandId);
        // sequenceNumber
        messageHeader.setSequenceNumber(ByteArrayUtil.parseUnsignedInteger(header, 8));
        return messageHeader;
    }
}
