package com.its.vds.xnettcp.vds.codec;

import com.its.app.utils.NettyUtils;
import com.its.vds.config.CommunicationConfig;
import com.its.vds.dto.TbVdsCtlrDto;
import com.its.vds.service.AppRepositoryService;
import com.its.vds.xnettcp.vds.handler.VdsServerIdleStateHandler;
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 VdsTcpServerEncoder 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();
        TbVdsCtlrDto obj = this.repoService.getIpAddrMap(ipAddress);
        if (obj == null) {
            log.error("SEND: VDS Unknown, VdsTcpServerEncoder.encode: Unknown Controller IP: {}. will be close.", ipAddress);
            VdsServerIdleStateHandler.disconnectChannel(null, channel);
            return;
        }

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

            if (!channel.isOpen() || !channel.isActive()) {
                log.error("SEND: VDS {}, VdsTcpServerEncoder.encode: {}, isOpen: {}, isActive: {}. [{}]", obj.getVdsCtlrNmbr(), ipAddress, channel.isOpen(), channel.isActive(), obj.getLogKey());
                VdsServerIdleStateHandler.disconnectChannel(obj, channel);
                return;
            }

            if (!(msg instanceof ByteBuffer)) {
                log.error("SEND: VDS {}, VdsTcpServerEncoder.encode: msg is not ByteBuffer. [{}]", obj.getVdsCtlrNmbr(), obj.getLogKey());
                VdsServerIdleStateHandler.disconnectChannel(null, channel);
                return;
            }

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

}
