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

import com.its.app.utils.NettyUtils;
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.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;

import java.nio.ByteBuffer;

@Slf4j
@RequiredArgsConstructor
@Component
@ChannelHandler.Sharable
public class VmsTcpServerEncoder extends MessageToByteEncoder<Object> {

    private final CommunicationConfig communicationConfig;
    private final AppRepositoryService repoService;

     @Override
    protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf outByteBuf) throws Exception {

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

        String logKey = String.valueOf(obj.getLogKey());
        try {
            MDC.put("id", logKey);

            if (!channel.isOpen() || !channel.isActive()) {
                log.error("SEND: VMS {}, VmsTcpServerEncoder.encode: {}, isOpen: {}, isActive: {}. [{}]", obj.getVmsCtlrNmbr(), ipAddress, channel.isOpen(), channel.isActive(), obj.getLogKey());
                VmsServerIdleStateHandler.disconnectChannel(obj, channel);
                return;
            }

            if (!(msg instanceof ByteBuffer)) {
                log.error("SEND: VMS {}, VmsTcpServerEncoder.encode: msg is not ByteBuffer. [{}]", obj.getVmsCtlrNmbr(), obj.getLogKey());
                VmsServerIdleStateHandler.disconnectChannel(null, channel);
                return;
            }

            ByteBuffer buffer = (ByteBuffer) msg;
            byte[] sendBytes = buffer.array();
            outByteBuf.writeBytes(sendBytes);
            log.info("SEND: VMS {}, VmsTcpServerEncoder.encode: {} Bytes.", obj.getVmsCtlrNmbr(), sendBytes.length);
        }
        finally {
            MDC.remove(logKey);
            MDC.clear();
        }
    }

}
