package com.its.vds.xnettcp.vds.protocol.impl.andong;

import com.google.common.primitives.Bytes;
import com.its.vds.xnettcp.vds.protocol.VdsFrameHead;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Data
public class VdsAndongFrameHead implements VdsFrameHead {

    public static final int HEAD_SIZE = 13;

    private byte kind1 = (byte)'M';
    private byte kind2 = (byte)'S';
    private short group;          // short
    private short controller;     // short
    private short sequence;     // short
    private int opCode;         // byte
    private int length;         // int

    public VdsAndongFrameHead(int group, int controller, short sequence, int opCode) {
        this.group = (short)group;
        this.controller = (short)controller;
        this.sequence = sequence;
        this.opCode = opCode;
        this.length = 0;
    }

    public VdsAndongFrameHead(byte[] headBytes) {
        if (headBytes != null && headBytes.length >= VdsAndongFrameHead.HEAD_SIZE) {
            ByteBuffer byteBuffer = ByteBuffer.wrap(headBytes);
            byteBuffer.order(ByteOrder.BIG_ENDIAN);
            this.kind1 = byteBuffer.get();
            this.kind2 = byteBuffer.get();
            this.group = (short)(byteBuffer.getShort() & 0xFFFF);
            this.controller = (short)(byteBuffer.getShort() & 0xFFFF);
            this.sequence = (short)(byteBuffer.getShort() & 0xFFFF);
            this.opCode = (byte)(byteBuffer.get() & 0xFF);
            this.length = byteBuffer.getInt();
        }
        else {
            log.error("VdsAndongFrameHead: create failed, headBytes error");
        }
    }

    public byte[] getBuffer() {
        List<Byte> list = new ArrayList<>();

        list.add(this.kind1);
        list.add(this.kind2);
        list.add((byte)(((this.group      & 0xFF00) >>  8) & 0xFF));
        list.add((byte)(((this.group      & 0x00FF)      ) & 0xFF));

        list.add((byte)(((this.controller & 0xFF00) >>  8) & 0xFF));
        list.add((byte)(((this.controller & 0x00FF)      ) & 0xFF));

        list.add((byte)(((this.sequence   & 0xFF00) >>  8) & 0xFF));
        list.add((byte)(((this.sequence   & 0x00FF)      ) & 0xFF));

        list.add((byte)(this.opCode & 0xFF));

        list.add((byte)(((this.length & 0xFF000000) >> 24) & 0xFF));
        list.add((byte)(((this.length & 0x00FF0000) >> 16) & 0xFF));
        list.add((byte)(((this.length & 0x0000FF00) >>  8) & 0xFF));
        list.add((byte)(((this.length & 0x000000FF)      ) & 0xFF));

        return Bytes.toArray(list);
    }

    @Override
    public int getGroupNo() {
        return this.group;
    }

    @Override
    public int getControllerNo() {
        return this.controller;
    }
}
