package org.framework.lazy.cloud.network.heartbeat.common.decoder;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.NettyByteBuf;
import org.wu.framework.core.exception.RuntimeExceptionFactory;

import java.util.List;

/**
 * ByteBuf 解码为 byte[]
 */
@Slf4j
public class TransferDecoder extends
        ByteToMessageDecoder {

    // 上一次可以读取到到数据长度
    private long latestReadableBytes = -1;

    private final int maxFrameLength; // 读取最大长度超出会异常
    private final int perPackageLimitLength;// 粘包时合并后到包最大大小

    public TransferDecoder(int maxFrameLength, int perPackageLimitLength) {
        this.maxFrameLength = maxFrameLength;
        this.perPackageLimitLength = perPackageLimitLength;
    }

    protected NettyByteBuf decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        if (in == null) {
            log.info("this byteBuf is null");
            return null;
        }
//        if (latestReadableBytes == -1) {
//
//            latestReadableBytes = in.readableBytes();
//            // 第一次什么也不做
//            return null;
//        }
//        // 第二次了哦
//        if (in.readableBytes() > latestReadableBytes && in.readableBytes() < perPackageLimitLength) {
//            // 继续粘包
//            latestReadableBytes = in.readableBytes();
//            log.info("粘包ing:{}",latestReadableBytes);
//            return null;
//        }
//        if (in.readableBytes() > maxFrameLength) {
//            RuntimeExceptionFactory.of("readableBytes is max then maxFrameLength:" + maxFrameLength);
//        }
//        log.info("粘包结束开始处理数据:{}",latestReadableBytes);

        byte[] bytes = new byte[in.readableBytes()];
        in.readBytes(bytes);
        NettyByteBuf nettyByteBuf = new NettyByteBuf();
        nettyByteBuf.setData(bytes);
        latestReadableBytes = -1;

        return nettyByteBuf;
    }

    /**
     * Decode the from one {@link ByteBuf} to an other. This method will be called till either the input
     * {@link ByteBuf} has nothing to read when return from this method or till nothing was read from the input
     * {@link ByteBuf}.
     *
     * @param ctx the {@link ChannelHandlerContext} which this {@link ByteToMessageDecoder} belongs to
     * @param in  the {@link ByteBuf} from which to read data
     * @param out the {@link List} to which decoded messages should be added
     * @throws Exception is thrown if an error occurs
     */
    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
        Object decoded = decode(ctx, in);
        if (decoded != null) {
            out.add(decoded);
        }
    }
}
