package com.its.vms.xnettcp.vms.codec;

import com.its.app.utils.NettyUtils;
import com.its.app.utils.SysUtils;
import com.its.vms.config.CommunicationConfig;
import com.its.vms.dto.TbVmsCtlrDto;
import com.its.vms.service.AppRepositoryService;
import com.its.vms.xnettcp.vms.handler.VmsServerIdleStateHandler;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;

import java.util.List;

@Slf4j
@RequiredArgsConstructor
public class VmsTcpServerDecoder extends ByteToMessageDecoder {

    private final CommunicationConfig communicationConfig;
    private final AppRepositoryService repoService;

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> list) {

        String ipAddress = NettyUtils.getRemoteIpAddress(ctx.channel());
        Channel channel = ctx.channel();
        TbVmsCtlrDto obj = this.repoService.getIpAddrMap(ipAddress);
        if (obj == null) {
            log.error("TcpServerDecoder.decode: Unknown Controller IP: {}. will be close.", ipAddress);
            VmsServerIdleStateHandler.disconnectChannel(null, channel);
            return;
        }

        MDC.put("id", obj.getLogKey());

        if (!channel.isOpen() || !channel.isActive()) {
            log.error("TcpServerDecoder.decode: {}, isOpen: {}, isActive: {}. [{}]", ipAddress, channel.isOpen(), channel.isActive(), obj.getLogKey());
            VmsServerIdleStateHandler.disconnectChannel(obj, channel);
            return;
        }

        int readableBytes = byteBuf.readableBytes();
        log.debug("RECV_0: [{}]. ReadableBytes: {} Bytes, ReaderIndex: {}", ipAddress, readableBytes, byteBuf.readerIndex());
        if (readableBytes == 0) {
            log.error("RECV: {}. byteBuf.readableBytes() == 0. [{]{}]", ipAddress, obj.getLogKey());
            return;
        }
        log.debug("RECV: Decoder: {}. [Readable:{}, RIDX:{}-WIDX:{}]", ipAddress, readableBytes, byteBuf.readerIndex(), byteBuf.writerIndex());

        if (this.communicationConfig.isDumpRecv()) {
            byte[] debugBytes = new byte[byteBuf.readableBytes()];
            byteBuf.getBytes(byteBuf.readerIndex(), debugBytes);
            log.debug("RECV: [{}], {} Bytes. {}", ipAddress, debugBytes.length, SysUtils.byteArrayToHex(debugBytes));
        }

//        int pktLength = 0;
//        int authLength= 0;
//        //int readerIndex = byteBuf.readerIndex();
//        while (readableBytes > VmsTcpServerDecoder.DSRC_ASN1_PACKET_MIN_SIZE) {
//
//            byteBuf.markReaderIndex();
//            byte[] inBytes = new byte[byteBuf.readableBytes()];
//            byteBuf.readBytes(inBytes);
//            DatexDataPacket datexDataPacket = new DatexDataPacket();
//            try {
//                try {
//                    pktLength = datexDataPacket.decode(new ByteArrayInputStream(inBytes, 0, inBytes.length));
//                }
//                catch(IOException e) {
//                    //log.warn("DsrcTcpServerDecoder.decode: RECV: decode error. {}, {}, inBytes: {}, pktLength: {}", ipAddress, e.getMessage(), inBytes, inBytes.length);
//                    break;
//                }
//
//                if (pktLength > readableBytes) {
//                    //log.warn("RECV: Decoder: {}. [pktLength > readableBytes]", ipAddress);
//                    //log.warn("RECV: Decoder: {}. [Readable:{}, RIDX:{}-WIDX:{}]. Packet Remain.", ipAddress, readableBytes, byteBuf.readerIndex(), byteBuf.writerIndex());
//                    break;
//                }
//
//                // 패킷 읽은 만큼 이동
//                byteBuf.readerIndex(pktLength);
//                byteBuf.markReaderIndex();
//                byteBuf.discardReadBytes();
//
//                BerOctetString berOctetString = datexDataPacket.getDatexData();
//                C2CAuthenticatedMessage c2c = new C2CAuthenticatedMessage();
//                authLength = c2c.decode(new ByteArrayInputStream(berOctetString.value, 0, berOctetString.value.length));
//                //log.info("RECV: Decoder: {}. ASN1 PACKET: {} Bytes, decodeLength: {} Bytes", ipAddress, pktLength, authLength);
//                //log.info("RECV: Decoder: {}, C2CAuth: {}", ipAddress, c2c);
//                obj.setLastRecvTime();
//                list.add(c2c);
//
//                readableBytes = byteBuf.readableBytes();
//            }
//            catch(Exception e) {
//                //log.error("TcpServerDecoder.decode: RECV: {}. Exception Error1: will be closed: {}. [{}]", ipAddress, e.toString(), obj.getLogKey());
//                VmsServerIdleStateHandler.disconnectChannel(obj, channel);
//            }
//        }
//        byteBuf.resetReaderIndex();
        MDC.remove(obj.getLogKey());
        MDC.clear();
    }
}
