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

import com.its.app.utils.NettyUtils;
import com.its.vds.dto.TbVdsCtlrDto;
import com.its.vds.service.AppRepositoryService;
import com.its.vds.xnettcp.vds.protocol.impl.VdsResFramePacket;
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 TcpServerByteBufMessageDecoder extends MessageToMessageDecoder<ByteBuf> {

    private final AppRepositoryService appRepositoryService;

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> list) throws Exception {
        try {
            if (byteBuf == null) {
                log.error("Receive: Packet frame packet error. length field data error");
                ctx.close();
                return;
            }

            // CONTROLLER KIND(0 1), ADDRESS(2 3, 4 5), FRAME SEQUENCE NO(6 7), OP CODE(8), DATA LENGTH(9 10 11 12), DATA(13 ...)
            final int readableBytes = byteBuf.readableBytes();
            if (readableBytes < 13) {
                log.error("Receive: Packet readableBytes too small: {}, required min size: {}, will be closed.", readableBytes, 13);
                ctx.close();
                return;
            }


            String ipAddress = NettyUtils.getRemoteIpAddress(ctx.channel());
            TbVdsCtlrDto vdsObj = this.appRepositoryService.getIpAddrMap(ipAddress);
            if (vdsObj == null) {
                log.error("Receive: Packet {} Bytes, But Unknown IpAddress {}, will be closed.", readableBytes, ipAddress);
                ctx.close();
                return;
            }
            byte[] packets = new byte[readableBytes];
            byteBuf.readBytes(packets);
            VdsResFramePacket framePacket = new VdsResFramePacket(vdsObj, packets, packets.length);
            list.add(framePacket);
        }
        catch (Exception e) {
            log.error("TcpServerByteBufMessageDecoder.decode: Exception: {}.", e.getMessage());
        }
    }

}
