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

import com.its.vds.xnettcp.vds.protocol.VdsFrameHead;
import com.its.vds.xnettcp.vds.protocol.VdsFramePacket;
import com.its.vds.xnettcp.vds.protocol.VdsFrameTail;
import com.its.vds.xnettcp.vds.protocol.enums.eVdsOpCode;
import lombok.extern.slf4j.Slf4j;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

@Slf4j
public class VdsAndongFramePacket implements VdsFramePacket {
    public static final ByteOrder BYTE_ORDER = ByteOrder.BIG_ENDIAN;

    protected VdsAndongFrameHead head;
    protected byte[]          body;

    public VdsAndongFramePacket(int group, int controller, short sequence, byte opCode) {
        this.head = new VdsAndongFrameHead(group, controller, sequence, opCode);
        this.body = null;
    }

    public VdsAndongFramePacket(byte[] packet, int msgLen) {
        this.body = null;
        if (packet == null || msgLen == 0) {
            this.head = new VdsAndongFrameHead(0, 0, (short) 0, 0);
            return;
        }

        this.head = new VdsAndongFrameHead(packet);

        int bodySize = msgLen - VdsAndongFrameHead.HEAD_SIZE;
        if (bodySize > 0) {
            this.body = new byte[bodySize];
            System.arraycopy(packet, VdsAndongFrameHead.HEAD_SIZE, this.body, 0, bodySize);
        }
    }

    @Override
    public void setBody(byte[] body) {
        this.body = body;
    }

    @Override
    public VdsFrameHead getHead() {
        return this.head;
    }

    /**
     * 요청 패킷을 ByteBuffer 로 변경하여 리턴
     * @return
     */
    @Override
    public ByteBuffer getByteBuffer() {
        return getBuffer();
    }

    @Override
    public String getOpCodeDesc() {
        eVdsOpCode opCode = eVdsOpCode.getValue((byte)(this.head.getOpCode() & 0xFF));
        if (opCode != null) {
            return opCode.toString();
        }
        return String.format("0x%02X.Unknown OpCode.", (byte)(this.head.getOpCode() & 0xFF));
    }

    @Override
    public int getOpCode() {
        return this.head != null ? this.head.getOpCode() : 0x00;
    }

    @Override
    public byte[] getBody() {
        return this.body;
    }

    @Override
    public VdsFrameTail getTail() {
        return null;
    }

    public ByteBuffer getBuffer() {
        int bodySize = 0;
        if (this.body != null) {
            bodySize = this.body.length;
        }

        this.head.setLength(bodySize);    // OpCode 1 자리 추가해야함.
        ByteBuffer byteBuffer = ByteBuffer.allocate(VdsAndongFrameHead.HEAD_SIZE + bodySize);
        byteBuffer.order(VdsAndongFramePacket.BYTE_ORDER);

        // HEAD
        byteBuffer.put(this.head.getBuffer());
        // BODY
        if (bodySize > 0) {
            byteBuffer.put(this.body);
        }
        return byteBuffer;
    }

}
