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

import com.its.vds.domain.NET;
import com.its.vds.dto.TbVdsCtlrDto;
import com.its.vds.xnettcp.vds.process.TcpServerSendData;
import com.its.vds.xnettcp.vds.process.response.VdsResponse;
import com.its.vds.xnettcp.vds.protocol.VdsFramePacket;
import com.its.vds.xnettcp.vds.protocol.enums.eVdsOpCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

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

@Slf4j
@RequiredArgsConstructor
public class VdsResDataTraffic implements VdsResponse {

    private final TbVdsCtlrDto vdsObj;
    private final VdsFramePacket resFramePacket;
    private int door;       // Door Open/Close 상태, 0x00: Open, 0x01: Close, 0x09: Unknown
    private int power;      // 전원의 ON/OFF 상태, 0x00: On, 0x01: Off, 0x09: Unknown (Sign Board)
    private int fan;        // VDS Fan 동작 상태, 0x00: On, 0x01: Off, 0x09: Unknown
    private int heater;     // VDS Heater 동작 상태, 0x00: On, 0x01: Off, 0x09: Unknown
    private int formNo;     // 표출 폼 번호, 현재 표출중인 폼 번호 : 0～9999
    private int reboot;     // 표출 폼 번호, 0x00: 정상, 0x01: 재실행
    private int cboxTemp;   // 함체온도, 127 ～ -127, -128 : Unknown
    private int brightMode; // 화면의 밝기 - 휘도 모드, 0x00:주간, 0x01:야간, 0x02:Auto, 0x03:수동
    private int brightCurr; // 화면의 밝기 - 현재 휘도값, 0～100
    private int brightWeek; // 화면의 밝기 - 주간 휘도값, 0～100
    private int brightNght; // 화면의 밝기 - 야간 휘도값, 0～100
    private int dpTemp;     // 외부온도, -127 ～ 127, -128: Unknown
    private int dpHum;      // 외부습도,    0 ～ 100,  101: Unknown
    private int powerModuleStts = 0x02; // 0x00: 정상, 0x01: 에러, 0x02: Unknown
    private int moduleStts = 0x02;      // 0x00: 정상, 0x01: 불량, 0x02: Unknown
    private int cboxFan = 0x09;         // 0x00: On, 0x01: Off, 0x09: Unknown
    private int cboxHeather = 0x09;     // 0x00: On, 0x01: Off, 0x09: Unknown

    @Override
    public boolean process() {

        // 상태정보 최초 수신시
        if (this.vdsObj.getNetState() == NET.LOGIN_REQ) {
            if (this.vdsObj.getVdsCtlrNmbr() != this.resFramePacket.getHead().getControllerNo() &&
                this.vdsObj.getVdsCtlrLocalNo() != this.resFramePacket.getHead().getControllerNo()) {
                log.error("VdsResDataTraffic.process: Controller Number Error: VDS {}, NMBR {}, LOCAL {}, RECV {}.",
                        this.vdsObj.getVdsCtlrNmbr(), this.vdsObj.getVdsCtlrNmbr(), this.vdsObj.getVdsCtlrLocalNo(), this.resFramePacket.getHead().getControllerNo());
                return false;
            }
        }

        byte[] body = this.resFramePacket.getBody();
        log.info("VdsResDataTraffic.process: VDS {}, body length: {}.", this.vdsObj.getVdsCtlrNmbr(), body != null ? body.length : 0);
        if (body == null || body.length < 14) {
            log.error("VdsResDataTraffic.process: VDS {}, body length error: {}.", this.vdsObj.getVdsCtlrNmbr(), body != null ? body.length : 0);
            return false;
        }

        // Byte.toUnsignedInt(
        ByteBuffer byteBuffer = ByteBuffer.wrap(body);
        byteBuffer.order(ByteOrder.BIG_ENDIAN);
        this.door = byteBuffer.get() & 0xFF;        // Door Open/Close 상태, 0x00: Open, 0x01: Close, 0x09: Unknown
        this.power = byteBuffer.get() & 0xFF;       // 전원의 ON/OFF 상태, 0x00: On, 0x01: Off, 0x09: Unknown (Sign Board)
        this.fan = byteBuffer.get() & 0xFF;         // VDS Fan 동작 상태, 0x00: On, 0x01: Off, 0x09: Unknown
        this.heater = byteBuffer.get() & 0xFF;      // VDS Heater 동작 상태, 0x00: On, 0x01: Off, 0x09: Unknown
        this.formNo = byteBuffer.getShort() & 0xFFFF; // 표출 폼 번호, 현재 표출중인 폼 번호 : 0～9999
        this.reboot = byteBuffer.get() & 0xFF;      // 표출 폼 번호, 0x00: 정상, 0x01: 재실행
        this.cboxTemp = byteBuffer.get() & 0xFF;    // 함체온도, 127 ～ -127, -128 : Unknown
        this.brightMode = byteBuffer.get() & 0xFF;  // 화면의 밝기 - 휘도 모드, 0x00:주간, 0x01:야간, 0x02:Auto, 0x03:수동
        this.brightCurr = byteBuffer.get() & 0xFF;  // 화면의 밝기 - 현재 휘도값, 0～100
        this.brightWeek = byteBuffer.get() & 0xFF;  // 화면의 밝기 - 주간 휘도값, 0～100
        this.brightNght = byteBuffer.get() & 0xFF;  // 화면의 밝기 - 야간 휘도값, 0～100
        this.dpTemp = byteBuffer.get() & 0xFF;      // 외부온도, -127 ～ 127, -128: Unknown
        this.dpHum = byteBuffer.get() & 0xFF;       // 외부습도, 0 ～ 100, 101: Unknown

        this.cboxFan = 0x09;
        this.cboxHeather = 0x09;
        if (body.length >= 16) {
            this.powerModuleStts = byteBuffer.get() & 0xFF;    // 전원 모듈 상태, 0x00: 정상, 0x01: 에러, 0x02: Unknown
            this.moduleStts = byteBuffer.get() & 0xFF;         // 모듈 상태, 0x00: 정상, 0x01: 불량, 0x02: Unknown
            this.cboxFan = byteBuffer.get() & 0xFF;            // 함체 Fan 동작 상태, 0x00: On, 0x01: Off, 0x09: Unknown
            this.cboxHeather = byteBuffer.get() & 0xFF;        // 함체 Heater 동작 상태, 0x00: On, 0x01: Off, 0x09: Unknown
        }
        else {
            int tmpFan1 = (this.fan & 0x0F);
            int tmpFan2 = (this.fan & 0xF0) >> 4;
            int tmpHtr1 = (this.heater & 0x0F);
            int tmpHtr2 = (this.heater & 0xF0) >> 4;
            this.fan = tmpFan1;
            this.cboxFan = tmpFan2;
            this.heater = tmpHtr1;
            this.cboxHeather = tmpHtr2;
            this.powerModuleStts = this.power;    // 전원 모듈 상태, 0x00: 정상, 0x01: 에러, 0x02: Unknown
            this.moduleStts = this.power;         // 모듈 상태, 0x00: 정상, 0x01: 불량, 0x02: Unknown
        }

        if (this.vdsObj.getDebug().isDebug()) {
            log.info("{}", toString());
        }

//        if (this.vdsObj.getStts().updateStatus(door, power, fan, heater, formNo, reboot, cboxTemp,
//                brightMode, brightCurr, brightWeek, brightNght, dpTemp, dpHum,
//                powerModuleStts, moduleStts, cboxFan, cboxHeather)) {
//            // 상태정보가 변경되었으므로 상태정보 업데이트 하도록 한다.
//        }

        // 제어기 전원모듈상태 요청
        return this.vdsObj.addRequestData(new TcpServerSendData(eVdsOpCode.OP_VDS_DATA_VEHICLE, null));
    }

    public String toString() {
        StringBuilder data = new StringBuilder();
        data.append(String.format("RESPONSE-%s. VDS %d", eVdsOpCode.OP_VDS_DATA_VOLUME, this.vdsObj.getVdsCtlrNmbr()));
        data.append(System.getProperty("line.separator"));
        data.append(String.format("Door(0x%02X), ", this.door));
        data.append(String.format("Power(0x%02X), ", this.power));
        data.append(String.format("Fan(0x%02X), ", this.fan));
        data.append(String.format("Heater(0x%02X), ", this.heater));
        data.append(String.format("FormNo(%d), ", this.formNo));
        data.append(String.format("ReBoot(0x%02X), ", this.reboot));
        data.append(String.format("CboxTemp(%d), ", this.cboxTemp));
        data.append(String.format("B-Mode(0x%02X), ", this.brightMode));
        data.append(String.format("B-Curr(%d), ", this.brightCurr));
        data.append(String.format("B-Week(%d), ", this.brightWeek));
        data.append(String.format("B-Nght(%d), ", this.brightNght));
        data.append(String.format("DpTemp(%d), ", this.dpTemp));
        data.append(String.format("DpHum(%d), ", this.dpHum));
        data.append(String.format("PowerModuleStts(0x%02X), ", this.powerModuleStts));
        data.append(String.format("ModuleStts(0x%02X), ", this.moduleStts));
        data.append(String.format("CboxFan(0x%02X), ", this.cboxFan));
        data.append(String.format("CboxHeater(0x%02X)", this.cboxHeather));
        return data.toString();
    }

}
