package com.its.dsrc.xnetudp.thread;

import com.beanit.asn1dsrc.enums.eControlCommand;
import com.beanit.asn1dsrc.enums.eControlDeviceId;
import com.its.app.AppUtils;
import com.its.app.utils.SysUtils;
import com.its.dsrc.entity.TbRseCtlr;
import com.its.dsrc.global.AppRepository;
import com.its.dsrc.service.UnitSystService;
import com.its.dsrc.vo.NET;
import com.its.dsrc.entity.TbRseCtrlHs;
import com.its.dsrc.xnettcp.dsrc.process.service.ControlDeviceService;
import com.its.dsrc.xnetudp.protocol.CENTER_COMM_DEFINE;
import com.its.dsrc.xnetudp.protocol.CENTER_COMM_MESSAGE;
import com.its.dsrc.xnetudp.protocol.CENTER_DSRC_REQ_CONTROL;
import com.its.dsrc.xnetudp.service.CenterCommResponseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class CenterCommServerReceiver extends AbstractCenterCommServerReceiver {

    @Async("centerCommExecutor")
    public void run(CENTER_COMM_MESSAGE data) {
        if (data == null) {
            log.error("CenterCommServerReceiver: RECV Data Packet NULL");
            return;
        }
        if (data.getRecvId() != CENTER_COMM_DEFINE.INT_ID_DSRC_SERVER) {
            log.error("CenterCommServerReceiver: UDP RECV UNKNOWN SERVER ID: {}", data.getRecvId());
            return;
        }

        String reqIpAddr = data.getSenderIp();
        int reqPort = 4603;
        UnitSystService unitSystService = (UnitSystService) AppUtils.getBean(UnitSystService.class);
//        ConcurrentHashMap<String, voUnitSyst> untiSystMap = unitSystService.getUntiSystMap();
//        for (Map.Entry<String, voUnitSyst> e : untiSystMap.entrySet()) {
//            if (reqIpAddr.equals(e.getValue().getSYST_IP_1())) {
//                reqPort = e.getValue().getPRGM_PORT();
//                break;
//            }
//        }

        byte opCode = data.getOpCode();
        if (opCode == CENTER_COMM_DEFINE.INT_OP_DSRC_CONTROL_REQ) {

            CENTER_DSRC_REQ_CONTROL req = new CENTER_DSRC_REQ_CONTROL(data.getBody());
            log.info("DSRC REQ CONTROL: [{}] [{},{},{},{}], {}",
                    req.getCtlrNmbr(), req.getOperId(), req.getCmdTime(), req.getDeviceType(), req.getControlType(), Thread.currentThread().getName());

            int devcType = req.getDeviceType();
            int cntlType = req.getControlType();
            TbRseCtrlHs cntl = new TbRseCtrlHs();
            cntl.setReq(req);
            cntl.setReqIpAddress(data.getSender().getAddress().getHostAddress());
            cntl.setReqPort(data.getSender().getPort());
            cntl.setRSE_CTLR_NMBR(req.getCtlrNmbr());
            cntl.setCNTL_DT(SysUtils.getSysTime());
            cntl.setDEVC_TYPE(String.valueOf(devcType));
            cntl.setCNTL_TYPE(String.valueOf(cntlType));

            TbRseCtlr rseCtlr = AppRepository.getInstance().getCtlrMap().get(String.valueOf(req.getCtlrNmbr()).toString());
            if (rseCtlr == null) {
                log.info("DSRC REQ CONTROL Unknown DSRC ID: [{}] [{},{},{},{}]",
                        req.getCtlrNmbr(), req.getOperId(), req.getCmdTime(), req.getDeviceType(), req.getControlType());
                responseOperator(null, cntl, (byte)0x01);
                return;
            }
            if (rseCtlr.getChannel() == null || rseCtlr.getNetState() != NET.LOGINED) {
                // 여기 들어오면 안된다. 운영단말에서 통신이 정상인 것만 제어를 내릴수 있도록 한다.
                log.error("DSRC REQ CONTROL Not Connect: [{}] [{},{},{},{}]",
                        req.getCtlrNmbr(), req.getOperId(), req.getCmdTime(), req.getDeviceType(), req.getControlType());
                responseOperator(rseCtlr, cntl, (byte)0x01);
                return;
            }

            // 제어요청 패킷을 만든다
            eControlDeviceId controlDeviceId = eControlDeviceId.getByValue(devcType);
            eControlCommand commandType = eControlCommand.getByValue(cntlType);
            if (controlDeviceId == null || commandType == null) {
                log.error("DSRC REQ CONTROL Value Error: [{}] [{},{},{},{}]",
                        req.getCtlrNmbr(), req.getOperId(), req.getCmdTime(), req.getDeviceType(), req.getControlType());
                responseOperator(rseCtlr, cntl, (byte)0x01);
                return;
            }
            log.warn("{}, {}, controlDeviceId: {}, commandType: {}", rseCtlr.getID(), rseCtlr.getRSE_ID(), controlDeviceId.toString(), commandType.toString());
            boolean res = ControlDeviceService.getInstance().requestSubscriptionDeviceCommand(true, rseCtlr, rseCtlr.getChannel(), controlDeviceId.getValue(), commandType.getValue());
            if (res) {
                log.info("DSRC REQ CONTROL SEND OK: [{}] [{},{},{},{}]",
                        req.getCtlrNmbr(), req.getOperId(), req.getCmdTime(), req.getDeviceType(), req.getControlType());
                responseOperator(rseCtlr, cntl, (byte)0x00);
            } else {
                log.error("DSRC REQ CONTROL SEND Error: [{}] [{},{},{},{}]",
                        req.getCtlrNmbr(), req.getOperId(), req.getCmdTime(), req.getDeviceType(), req.getControlType());
                responseOperator(rseCtlr, cntl, (byte)0x01);
            }
        }
        else {
            log.error("UDP RECV UNKNOWN MESSAGE: {}", opCode);
        }
    }

    private int responseOperator(TbRseCtlr obj, TbRseCtrlHs cntl, byte error) {
        CenterCommResponseService responseService = (CenterCommResponseService) AppUtils.getBean(CenterCommResponseService.class);
        return responseService.response(obj, cntl, error);
    }
}
