package com.its.vms.xnettcp.vms.process.response.impl;

import com.its.app.AppUtils;
import com.its.app.utils.SysUtils;
import com.its.vms.domain.NET;
import com.its.vms.domain.VmsDownloadForm;
import com.its.vms.dto.TbVmsCtlrDto;
import com.its.vms.dto.TbVmsSymbLibDnldDto;
import com.its.vms.dto.VmsScheduleSymbDto;
import com.its.vms.process.DbmsData;
import com.its.vms.process.DbmsDataProcess;
import com.its.vms.process.DbmsDataType;
import com.its.vms.xnettcp.vms.process.response.VmsResponse;
import com.its.vms.xnettcp.vms.protocol.VmsFramePacket;
import com.its.vms.xnettcp.vms.protocol.VmsProtocolConst;
import com.its.vms.xnettcp.vms.protocol.enums.eVmsErrorCode;
import com.its.vms.xnettcp.vms.protocol.enums.eVmsOpCode;
import com.its.vms.xnettcp.vms.protocol.impl.dle.VmsDleFramePacket;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.nio.ByteBuffer;

@Slf4j
@RequiredArgsConstructor
public class VmsResDataDownload implements VmsResponse {

    private final TbVmsCtlrDto vmsObj;
    private final VmsFramePacket resFramePacket;
    private boolean success;
    private eVmsErrorCode error;

    @Override
    public boolean process() {
        /**
         * ACK/NAK 확인
         */
        byte[] body = this.resFramePacket.getBody();
        log.info("VmsResDataDownload.process: VMS {}, body length: {}.", this.vmsObj.getVmsCtlrNmbr(), body != null ? body.length : 0);
        if (body == null || body.length < 1) {
            log.error("VmsResDataDownload.process: VMS {}, body length error: {}.", this.vmsObj.getVmsCtlrNmbr(), body != null ? body.length : 0);
            return false;
        }

        ByteBuffer byteBuffer = ByteBuffer.wrap(body);
        byteBuffer.order(VmsDleFramePacket.BYTE_ORDER);
        this.success = byteBuffer.get() == VmsProtocolConst.VMS_ACK;
        if (!this.success) {
            this.error = eVmsErrorCode.ERROR_UNKNOWN;
            if (body.length > 1) {
                byte errorCode = byteBuffer.get();
                this.error = eVmsErrorCode.getValue(errorCode & 0xFF);
                if (this.error == null) {
                    log.error("VmsResDataDownload.process: VMS {}, Unknown error code: {}", this.vmsObj.getVmsCtlrNmbr(), String.format("%02X", errorCode & 0xFF));
                    this.error = eVmsErrorCode.ERROR_UNKNOWN;
                }
            }
        }
        else {
            this.error = eVmsErrorCode.ERROR_NONE;
        }
        log.info("{}", toString());

//        if (this.error != eVmsErrorCode.ERROR_NONE) {
//            return true;
//        }

        if (this.vmsObj.getDownloadFormId() != 0) {
            // 홍보폼을 다운로드 한 경우
            VmsDownloadForm downloadForm = this.vmsObj.getDownloadFormMap().get(this.vmsObj.getDownloadFormId());
            if (downloadForm != null) {
                // 이미 다운로드 되었음을 설정해 놓는다.
                downloadForm.setAlreadyDownload(true);
            }
        }
        if (this.vmsObj.getReqDnldSymbMap().size() == 0 || this.vmsObj.getDnldSymbLibNmbr() == 0) {
            // 다운로드 할 심벌라이브러리가 없는 경우 스케쥴 폼을 다운로드 한다.
            this.vmsObj.downloadFile();
        }
        else {
            if (this.vmsObj.getDnldSymbLibNmbr() != 0) {
                // 다운로드한 심벌라이브러리 번호가 존재하므로 심벌라리브러리 다운로드 정보를 업데이트 한다.
                VmsScheduleSymbDto dnldSymb = this.vmsObj.getReqDnldSymbMap().get(this.vmsObj.getDnldSymbLibNmbr());
                if (dnldSymb != null) {
                    TbVmsSymbLibDnldDto dnldDto = this.vmsObj.getDnldSymbMap().get(this.vmsObj.getDnldSymbLibNmbr());
                    if (dnldDto == null) {
                        dnldDto = TbVmsSymbLibDnldDto.builder()
                                .vmsCtlrNmbr(this.vmsObj.getVmsCtlrNmbr())
                                .dnldSymbLibNmbr(this.vmsObj.getDnldSymbLibNmbr())
                                .dnldDt(SysUtils.getSysTime())
                                .dnldCnt(1)
                                .symbLibNmbr(dnldSymb.getSymbLibNmbr())
                                .updtDt(dnldSymb.getUpdtDt())
                                .build();
                        this.vmsObj.getDnldSymbMap().put(dnldDto.getDnldSymbLibNmbr(), dnldDto);
                    }
                    else {
                        dnldDto.setDnldDt(SysUtils.getSysTime());
                        dnldDto.setDnldCnt(dnldDto.getDnldCnt() + 1);
                        dnldDto.setUpdtDt(dnldSymb.getUpdtDt());
                    }
                    this.vmsObj.getReqDnldSymbMap().remove(this.vmsObj.getDnldSymbLibNmbr());

                    DbmsDataProcess dbmsDataProcess = (DbmsDataProcess)AppUtils.getBean(DbmsDataProcess.class);
                    dbmsDataProcess.add(new DbmsData(DbmsDataType.DBMS_DATA_SYMB_DNLD, false, dnldDto.toEntity()));
                }
            }

            /**
             * 다운로드할 심벌 라이브러리가 존재하면 다운로드한다.
             */
            if (this.vmsObj.downloadSymbLib()) {
                // 더이상 다운로드 할 심벌 라이브러리가 없는 경우....
                if (this.vmsObj.getNetState() == NET.LOGIN_REQ) {
                    // 최초 접속후, 심벌 라이브러리를 다운로드 한 경우이기 때문에 네트워크 상태를 변경하고
                    // 스케쥴을 다운로드 한다.
                    this.vmsObj.setNetState(NET.LOGINED);
                    this.vmsObj.downloadForm();
                }
            }
        }
        return true;
    }

    public String toString() {
        StringBuilder data = new StringBuilder();
        data.append(String.format("RESPONSE-%s. VMS %d", eVmsOpCode.OP_VMS_DATA_DOWNLOAD, this.vmsObj.getVmsCtlrNmbr()));
        data.append(System.getProperty("line.separator"));
        data.append(String.format("Data Download: %s, NAK: %s", this.success, this.error));
        return data.toString();
    }

}
