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

import com.its.app.utils.NettyUtils;
import com.its.pis.domain.NET;
import com.its.pis.entity.TbVdsCtlr;
import com.its.pis.global.AppRepository;
import com.its.pis.xnettcp.center.protocol.CenterReqFramePacket;
import com.its.pis.xnettcp.center.protocol.CenterResProtocol;
import com.its.pis.xnettcp.vds.protocol.VdsProtocol;
import com.its.pis.xnettcp.vds.protocol.VdsReqFrameHead;
import com.its.pis.xnettcp.vds.protocol.VdsReqImage;
import com.its.pis.xnettcp.vds.protocol.VdsReqReset;
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;
import java.util.Map;

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

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

        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;
        VdsReqFrameHead vdsReqHead = new VdsReqFrameHead(centerReqHead.getBody());
        short groupNo = vdsReqHead.getGroupNo();
        short ctlrNo = vdsReqHead.getControllerNo();
        byte opCode = vdsReqHead.getOpCode();

        TbVdsCtlr obj = null;
        for (Map.Entry<String, TbVdsCtlr> e : AppRepository.getInstance().getCtlrMap().entrySet()) {
            TbVdsCtlr tmp = e.getValue();
            if (tmp.getVDS_CTLR_LOCAL_NO() == ctlrNo) {
                obj = tmp;
                break;
            }
        }
        if (obj == null) {
            log.error("CenterTcpServerInboundHandler: Center Request Unknown VDS: [{}]", ctlrNo);
            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 VDS: [{}]", ctlrNo);
            } else {
                log.error("CenterTcpServerInboundHandler: Response Failed. Center Request Unknown VDS: [{}]", ctlrNo);
            }
            return;
        }
        if (obj.getChannel() == null || obj.getNetState() == NET.CLOSED) {
            log.error("CenterTcpServerInboundHandler: Center Request VDS Not Connect: [{}]", obj);
            ByteBuffer sendBuffer = CenterResProtocol.getResponse(opCode, (byte)(0xFE));
            ChannelFuture f = ctx.channel().writeAndFlush(sendBuffer);
            f.awaitUninterruptibly();
            if (f.isDone() || f.isSuccess()) {
                log.info("CenterTcpServerInboundHandler: Response OK. Center Not Connect VDS: [{}]", ctlrNo);
            } else {
                log.error("CenterTcpServerInboundHandler: Response Failed. Center Not Connect VDS: [{}]", ctlrNo);
            }
            return;
        }

        if (opCode == VdsProtocol.vds_Reset) {
            ByteBuffer resultBuffer;
            VdsReqReset reqReset = new VdsReqReset((short)obj.getGROUP_NO(), (short)obj.getVDS_CTLR_LOCAL_NO());
            reqReset.makeCRC();
            ByteBuffer sendBuffer = reqReset.getByteBuffer();
            if (!obj.sendData(sendBuffer, 0, "vds_Reset")) {
                log.error("CenterTcpServerInboundHandler: Center Request VDS Reset Data Send Failed: [{}]", obj);
                resultBuffer = CenterResProtocol.getResponse(opCode, (byte)(0xFD));
            } else {
                resultBuffer = CenterResProtocol.getResponse(opCode, (byte)(0x00));
            }
            ChannelFuture f = ctx.channel().writeAndFlush(resultBuffer);
            f.awaitUninterruptibly();
            if (f.isDone() || f.isSuccess()) {
                log.info("CenterTcpServerInboundHandler: Response OK. VDS Reset: [{}]", ctlrNo);
            } else {
                log.error("CenterTcpServerInboundHandler: Response Failed. VDS Reset: [{}]", ctlrNo);
            }
        }
        else if (opCode == VdsProtocol.vds_Image) {
            int frameNo = 0;    // first image request
            byte cameraNo = (centerReqHead.getBody()[9] == (byte)0x00) ? (byte)0x01 : centerReqHead.getBody()[9];
            obj.setStopImageRequest(ctx.channel(), cameraNo, frameNo);
            VdsReqImage reqImage = new VdsReqImage((short)obj.getGROUP_NO(), (short)obj.getVDS_CTLR_LOCAL_NO());
            reqImage.setCameraNo(cameraNo);
            reqImage.setFrameNo(frameNo);
            reqImage.makeCRC();
            ByteBuffer sendBuffer = reqImage.getByteBuffer();
            if (!obj.sendData(sendBuffer, 0, "vds_Image")) {
                obj.setStopImageResponse();
                log.error("CenterTcpServerInboundHandler: Center Request VDS Image Data Send Failed: [{}]", obj);
            }
        }
        else {
            log.error("CenterTcpServerInboundHandler: Center Request Not Support: [{}]", opCode);
            return;
        }
    }

}
