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

import com.its.app.utils.NettyUtils;
import com.its.app.utils.SysUtils;
import com.its.pis.entity.TbVdsCtlr;
import com.its.pis.global.AppRepository;
import com.its.pis.xnettcp.vds.handler.VdsTcpClientIdleHandler;
import com.its.pis.xnettcp.vds.protocol.VdsProtocol;
import com.its.pis.xnettcp.vds.protocol.VdsReqFrameHead;
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.extern.slf4j.Slf4j;
import org.slf4j.MDC;

import java.nio.ByteBuffer;

@Slf4j
@ChannelHandler.Sharable
public class VdsTcpClientEncoder extends MessageToByteEncoder<Object> {

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

        String ipAddress = NettyUtils.getRemoteIpAddress(ctx.channel());
        Channel channel = ctx.channel();
        TbVdsCtlr obj = AppRepository.getInstance().getCtlrIpMap().get(ipAddress);
        if (obj == null) {
            log.error("VdsTcpClientEncoder.encode: Unknown Controller IP: {}. will be close.", ipAddress);
            VdsTcpClientIdleHandler.disconnectChannel(channel);
            return;
        }

        if (!channel.isOpen() || !channel.isActive()) {
            log.error("[{}]. SEND: VdsTcpClientEncoder.encode: isOpen: {}, isActive: {}. [{}]", obj.getVDS_CTLR_ID(), channel.isOpen(), channel.isActive(), obj.getLogKey());
            VdsTcpClientIdleHandler.disconnectChannel(channel);
            return;
        }

        if (!(msg instanceof ByteBuffer)) {
            log.error("[{}]. SEND: VdsTcpClientEncoder.encode: msg is not ByteBuffer. [{}]", obj.getVDS_CTLR_ID(), obj.getLogKey());
            VdsTcpClientIdleHandler.disconnectChannel(channel);
            return;
        }

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

        ByteBuffer buffer = (ByteBuffer)msg;
        byte[] sendBytes = buffer.array();
        outByteBuf.writeBytes(sendBytes);
        log.info("[{}]. SEND: {}, {} Bytes.", obj.getVDS_CTLR_ID(), VdsProtocol.getOpCodeName(sendBytes[VdsReqFrameHead.OPCODE_POS]), sendBytes.length);
        if (obj.isDump()) {
            log.info("[{}]. SEND: {}, {} Bytes. {}", obj.getVDS_CTLR_ID(), VdsProtocol.getOpCodeName(sendBytes[VdsReqFrameHead.OPCODE_POS]), sendBytes.length, SysUtils.byteArrayToHex(sendBytes));
        }

        MDC.remove(obj.getLogKey());
        MDC.clear();
    }
}
