package com.tsi.comm.server.tcp.codec;

import com.tsi.comm.server.protocol.TsiCpuPacket;
import com.tsi.comm.server.protocol.TsiCvibProtocolSpec;
import com.tsi.comm.server.xnet.NettyUtils;
import com.tsi.common.utils.TimeUtils;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToMessageDecoder;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.List;

@Slf4j
@Component
@RequiredArgsConstructor
@ChannelHandler.Sharable
public class CvimServerByteBufMessageDecoder extends MessageToMessageDecoder<ByteBuf> {

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

        // 패킷을 cpu packet으로 변환하여 다음 핸들러로 전달
        final long msec = TimeUtils.currentTimeSeconds();
        final long nsec = System.nanoTime();

        if (byteBuf == null) {
            log.error("Receive: Packet frame packet error. length field data error");
            ctx.close();
            return;
        }

        // 패킷의 최소 유효성만 검사. (예: 최소 길이)
        final int readableBytes = byteBuf.readableBytes();
        if (readableBytes < TsiCvibProtocolSpec.SIZE_HEAD) {
            log.error("Receive: Packet readableBytes too small: {}, required min size: {}", readableBytes, TsiCvibProtocolSpec.SIZE_HEAD);
            ctx.close();
            return;
        }

        // 노드 ID 추출
        final long nodeId = byteBuf.getUnsignedInt(TsiCvibProtocolSpec.INDEX_NODE_ID);
        final long remoteIpAddress = NettyUtils.getRemoteIpAddressToLong(ctx.channel());
        final int remotePort = NettyUtils.getRemotePort(ctx.channel());

        // 프로세스 패킷 생성
        TsiCpuPacket packet = new TsiCpuPacket(nodeId, msec, nsec, remoteIpAddress, remotePort);
        packet.setBuf(new byte[readableBytes]);
        byteBuf.readBytes(packet.getBuf());
        packet.setObj(null);  // TsiNodeVo 객체를 저장

        // CvimServerPacketProcessHandler 로 TsiCpuPacket 전달
        out.add(packet);

        // Exception 이 발생하면 CvimServerPacketProcessHandler 의 exceptionCaught() 메소드가 호출됨
    }

}
