package com.its.dsrc.xnettcp.center.handler;

import com.its.app.AppUtils;
import com.its.app.utils.NettyUtils;
import com.its.dsrc.dao.mapper.RseCtlrMapper;
import com.its.dsrc.entity.TbRseCtlr;
import com.its.dsrc.entity.TbRseCtrlHs;
import com.its.dsrc.global.AppRepository;
import com.its.dsrc.xnettcp.center.protocol.CenterProtocol;
import com.its.dsrc.xnettcp.center.protocol.CenterReqFramePacket;
import com.its.dsrc.xnettcp.center.protocol.CenterResProtocol;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.nio.ByteBuffer;

@Slf4j
@Component
@ChannelHandler.Sharable
public class CenterTcpServerInboundHandler extends ChannelInboundHandlerAdapter {

    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        RseCtlrMapper mapper = (RseCtlrMapper) AppUtils.getBean(RseCtlrMapper.class);
        String ipAddress = NettyUtils.getRemoteIpAddress(ctx.channel());
        if (!(msg instanceof CenterReqFramePacket)) {
            log.error("[{}] | Received Data is not CenterReqFramePacket Object", NettyUtils.getRemoteIpAddress(ctx.channel()));
            return;
        }
        CenterReqFramePacket centerReqHead = (CenterReqFramePacket)msg;
        byte opCode = centerReqHead.getHead().getOpCode();
        byte[] body = centerReqHead.getBody();
        if (body == null) {
            return;
        }
        ByteBuffer msgBuffer = ByteBuffer.wrap(body);
        msgBuffer.order(CenterProtocol.byteOrder);
        if (opCode == CenterProtocol.INT_OP_DSRC_CONTROL_REQ) {
            long ctlrNmbr = msgBuffer.getLong();
            long ctrlSeq = msgBuffer.getLong();
            int devcType = msgBuffer.getInt();
            int cntlType = msgBuffer.getInt();

            TbRseCtrlHs ctrlHs = new TbRseCtrlHs();
            ctrlHs.setCtrlSeq(ctrlSeq);
            ctrlHs.setDevcType(String.valueOf(devcType));
            ctrlHs.setCntlType(String.valueOf(cntlType));
            ctrlHs.setRspsType("0");

            TbRseCtlr obj = AppRepository.getInstance().getCtlrMap().get(String.valueOf(ctlrNmbr));
            if (obj == null) {
                log.error("CenterTcpServerInboundHandler: Center Request Unknown RSE: [{}]", ctlrNmbr);
                ctrlHs.setRspsType("9");  // 알수없는제어기
                ByteBuffer sendBuffer = CenterResProtocol.getResponse(opCode, (byte)(0xFF));
                ChannelFuture f = ctx.channel().writeAndFlush(sendBuffer);
                f.awaitUninterruptibly();
                if (f.isDone() || f.isSuccess()) {
                    log.info("CenterTcpServerInboundHandler: Response OK. Center Request Unknown RSE: [{}]", ctlrNmbr);
                } else {
                    log.error("CenterTcpServerInboundHandler: Response Failed. Center Request Unknown RSE: [{}]", ctlrNmbr);
                }
                mapper.updateRseCtrlHs(ctrlHs);
                return;
            }

            // 제어요청 패킷을 만든다
            int result = obj.reset(devcType, devcType, ctrlHs);
            if (result == 1) {
                log.error("CenterTcpServerInboundHandler: Center Request RSE Not Connect: [{}]", obj);
                ByteBuffer sendBuffer = CenterResProtocol.getResponse(opCode, (byte)(0xFE));
                ctrlHs.setRspsType("8");  // 통신불량
                ChannelFuture f = ctx.channel().writeAndFlush(sendBuffer);
                f.awaitUninterruptibly();
                if (f.isDone() || f.isSuccess()) {
                    log.info("CenterTcpServerInboundHandler: Response OK. Center Not Connect RSE: [{}]", ctlrNmbr);
                } else {
                    log.error("CenterTcpServerInboundHandler: Response Failed. Center Not Connect RSE: [{}]", ctlrNmbr);
                }
                mapper.updateRseCtrlHs(ctrlHs);
                return;
            }
            if (result == 2) {
                log.error("RSE REQ RESET CONTROL Value Error: [{}] [{},{}]", ctlrNmbr, devcType, cntlType);
                ByteBuffer sendBuffer = CenterResProtocol.getResponse(opCode, (byte)(0xFD));
                ctrlHs.setRspsType("7");  // 통신불량
                ChannelFuture f = ctx.channel().writeAndFlush(sendBuffer);
                f.awaitUninterruptibly();
                if (f.isDone() || f.isSuccess()) {
                    log.info("CenterTcpServerInboundHandler: Response OK. Center Not Connect RSE: [{}]", ctlrNmbr);
                } else {
                    log.error("CenterTcpServerInboundHandler: Response Failed. Center Not Connect RSE: [{}]", ctlrNmbr);
                }
                mapper.updateRseCtrlHs(ctrlHs);
                return;
            }

            if (result == 0) {
                log.info("RSE REQ CONTROL SEND OK: [{}] [{},{}]", ctlrNmbr, devcType, cntlType);
                ctrlHs.setRspsType("0");  // 성공, 리셋응답없을수 있으므로 먼저 성공으로 입력한다.
            } else {
                log.error("RSE REQ CONTROL SEND Error: [{}] [{},{}]", ctlrNmbr, devcType, cntlType);
                ByteBuffer sendBuffer = CenterResProtocol.getResponse(opCode, (byte)(0xFC));
                ctrlHs.setRspsType("6");  // 데이터전송실패
                ChannelFuture f = ctx.channel().writeAndFlush(sendBuffer);
                f.awaitUninterruptibly();
                if (f.isDone() || f.isSuccess()) {
                    log.info("CenterTcpServerInboundHandler: Response OK. Center Not Connect RSE: [{}]", ctlrNmbr);
                } else {
                    log.error("CenterTcpServerInboundHandler: Response Failed. Center Not Connect RSE: [{}]", ctlrNmbr);
                }
            }
            mapper.updateRseCtrlHs(ctrlHs);
        }

    }

}
