package com.its.vms.xnettcp.vms.protocol.impl;

import com.its.app.utils.SysUtils;
import com.its.vms.dto.TbVmsCtlrDto;
import com.its.vms.xnettcp.vms.protocol.VmsFramePacket;
import com.its.vms.xnettcp.vms.protocol.VmsReqFramePacket;
import com.its.vms.xnettcp.vms.protocol.dto.*;
import com.its.vms.xnettcp.vms.protocol.enums.eVmsFormObjectKind;
import com.its.vms.xnettcp.vms.protocol.enums.eVmsOpCode;
import com.its.vms.xnettcp.vms.protocol.enums.eVmsProtocolVersion;
import com.its.vms.xnettcp.vms.protocol.impl.dle.VmsDleFramePacket;
import com.its.vms.xnettcp.vms.protocol.impl.std.VmsStdFramePacket;
import lombok.extern.slf4j.Slf4j;

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

/**
 * Download Schedule Form 요청
 */
@Slf4j
public class VmsReqDownloadForm extends VmsReqFramePacket {

    private final VmsFramePacket framePacket;

    public VmsReqDownloadForm(TbVmsCtlrDto vmsObj, VmsFormDataDto formData) {
        this.opCode = eVmsOpCode.OP_VMS_DOWNLOAD_FORM;
        this.packetNmbr = (short)this.opCode.getValue();
        byte opCode = (byte)this.opCode.getValue();
        if (vmsObj.getProtocolVer() == eVmsProtocolVersion.PROTOCOL_ANDONG.getValue()) {
            this.packetNmbr = vmsObj.getSeqNext();
            this.framePacket = new VmsStdFramePacket(vmsObj.getGroupNo().intValue(), vmsObj.getVmsCtlrNmbr().intValue(), this.packetNmbr, opCode);
        }
        else if (vmsObj.getProtocolVer() == eVmsProtocolVersion.PROTOCOL_EX_FIGURE.getValue()) {
            this.framePacket = new VmsDleFramePacket(vmsObj.getGroupNo().intValue(), vmsObj.getCtlrLocalNo(), opCode);
        }
        else {
            this.framePacket = new VmsDleFramePacket(vmsObj.getGroupNo().intValue(), vmsObj.getCtlrLocalNo(), opCode);
        }

        makeBody(formData);
    }

    public void makeBody(VmsFormDataDto formData) {
        int bodySize = 0;
        bodySize += 4;  // 다운로드 폼 헤더 크기
        for (int ii = 0; ii < formData.getFormCnt(); ii++) {
            bodySize += 6;  // 폼데이터 헤더 크기
            for (int jj = 0; jj < formData.getFormList().get(ii).getObjCnt(); jj++) {
                bodySize += 9;  // 오브젝트 데이터 헤더 크기
                bodySize += formData.getFormList().get(ii).getObjList().get(jj).getObjSize(); // 오브젝트 데이터 크기
            }
        }

        //log.info("VmsReqDownloadForm.makeBody: bodySize {}", bodySize);
        ByteBuffer byteBuffer = ByteBuffer.allocate(bodySize);
        byteBuffer.order(ByteOrder.BIG_ENDIAN);

        byteBuffer.putShort((short)(formData.getFormId() & 0xFFFF));    // 폼 ID
        byteBuffer.putShort((short)(formData.getFormCnt() & 0xFFFF));   // 전체 폼의 수
        for (int ii = 0; ii < formData.getFormCnt(); ii++) {
            VmsFormDto form = formData.getFormList().get(ii);
            byteBuffer.putShort((short)(form.getFormNo() & 0xFFFF));    // 폼 번호
            byteBuffer.put((byte)(form.getDispSec() & 0xFF));           // 폼 표출시간
            byteBuffer.put((byte)(form.getDispType() & 0xFF));          // 폼의 표출유형
            byteBuffer.put((byte)(form.getBkClr() & 0xFF));             // 폼 배경색
            byteBuffer.put((byte)(form.getObjCnt() & 0xFF));            // 표출할 오브젝트 전체 수

            for (int jj = 0; jj < formData.getFormList().get(ii).getObjCnt(); jj++) {
                VmsFormObj obj = form.getObjList().get(jj);

                byteBuffer.put((byte)(obj.getObjType() & 0xFF));            // 오브젝트 종류
                byteBuffer.putShort((short)(obj.getObjSize() & 0xFFFF));    // 오브젝트 데이터 크기
                byteBuffer.put((byte)(obj.getBlinking() & 0xFF));           // 점멸여부
                byteBuffer.putShort((short)(obj.getPosX() & 0xFFFF));       // 좌표 X
                byteBuffer.putShort((short)(obj.getPosY() & 0xFFFF));       // 좌표 Y
                byteBuffer.put((byte)(obj.getTxtBkClr() & 0xFF));           // 문자열 배경색 지정

                if (obj.getObjType() == eVmsFormObjectKind.OBJECT_TEXT.getValue()) {
                    VmsFormObjText txtObj = (VmsFormObjText)obj;
                    byteBuffer.put((byte)(txtObj.getClrR() & 0xFF));            // 사용 폰트 색상(R)
                    byteBuffer.put((byte)(txtObj.getClrG() & 0xFF));            // 사용 폰트 색상(G)
                    byteBuffer.put((byte)(txtObj.getClrB() & 0xFF));            // 사용 폰트 색상(B)
                    byteBuffer.put((byte)(txtObj.getFontSize() & 0xFF));        // 폰트 크기
                    byteBuffer.put((byte)(txtObj.getFontKind() & 0xFF));        // 폰트 종류
                    byteBuffer.put((byte)(txtObj.getFontBold() & 0xFF));        // 폰트 굵기
                    byteBuffer.put((byte)(txtObj.getReserved() & 0xFF));        // 기타, Reserved, 0x00
                    byteBuffer.put(SysUtils.stringToByteArr(txtObj.getText()));
                }
                else if (obj.getObjType() == eVmsFormObjectKind.OBJECT_BITMAP_ID.getValue()) {
                    VmsFormObjBitmapId idObj = (VmsFormObjBitmapId)obj;
                    byteBuffer.putShort((short)(idObj.getWidth() & 0xFFFF));    // 비트맵 표시 Width
                    byteBuffer.putShort((short)(idObj.getHeight() & 0xFFFF));   // 비트맵 표시 Height
                    byteBuffer.put((byte)(idObj.getType() & 0xFF));             // 그림파일 타입
                    byteBuffer.putShort((short)(idObj.getBitmapId() & 0xFFFF)); // 표출할 비트맵 ID
                }
                else {
                    VmsFormObjBitmap bmpObj = (VmsFormObjBitmap)obj;
                    byteBuffer.putShort((short)(bmpObj.getWidth() & 0xFFFF));   // 비트맵 표시 Width
                    byteBuffer.putShort((short)(bmpObj.getHeight() & 0xFFFF));  // 비트맵 표시 Height
                    byteBuffer.put((byte)(bmpObj.getType() & 0xFF));            // 그림파일 타입
                    byteBuffer.put((byte)(bmpObj.getReserved() & 0xFF));        // 기타, Reserved, 0x00
                    byteBuffer.put(bmpObj.getImage());                          // 표출할 비트맵 데이터
                }
            }
        }

        this.framePacket.setBody(byteBuffer.array());
    }

    @Override
    public ByteBuffer getByteBuffer() {
        return this.framePacket.getByteBuffer();
    }

}
