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

import com.tsi.app.common.app.AppUtils;
import com.tsi.app.common.xnet.NettyUtils;
import com.tsi.comm.server.config.TsiCvimServerConfig;
import com.tsi.comm.server.tcp.codec.CvimServerByteBufMessageDecoder;
import com.tsi.comm.server.tcp.codec.CvimServerEncoder;
import com.tsi.comm.server.tcp.handler.CvimServerInboundMessageHandler;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.timeout.IdleStateHandler;

public class CvimServerInitializer extends ChannelInitializer<Channel> {

    private final CvimServerByteBufMessageDecoder cvimServerByteBufMessageDecoder;
    private final CvimServerInboundMessageHandler cvimServerInboundMessageHandler;
    private final CvimServerEncoder cvimServerEncoder;
    private final TsiCvimServerConfig config;

    public CvimServerInitializer(TsiCvimServerConfig config) {
        this.cvimServerByteBufMessageDecoder = (CvimServerByteBufMessageDecoder) AppUtils.getBean(CvimServerByteBufMessageDecoder.class);
        this.cvimServerInboundMessageHandler = (CvimServerInboundMessageHandler) AppUtils.getBean(CvimServerInboundMessageHandler.class);
        this.cvimServerEncoder = (CvimServerEncoder) AppUtils.getBean(CvimServerEncoder.class);
        this.config = config;
    }

    @Override
    protected void initChannel(Channel channel) throws Exception {
        if (this.config.getReaderIdleTimeSeconds() < 5) {
            this.config.setReaderIdleTimeSeconds(5);
        }

        final String remoteIpAddress = NettyUtils.getRemoteIpAddress(channel);
        if (this.config.isInWhitelistIps(remoteIpAddress)) {
            // FOR L4, whitelist ips
            channel.disconnect();
            channel.close();
            return;
        }

        IdleStateHandler idleStateHandler = new IdleStateHandler(this.config.getReaderIdleTimeSeconds(), 0, 0);
        ChannelPipeline pipeline = channel.pipeline();
        pipeline.addLast("idleStateHandler", idleStateHandler);
        pipeline.addLast("frameDecoder", new LengthFieldBasedFrameDecoder(2048, 2, 2, -2, 0));
        pipeline.addLast("packetDecoder", this.cvimServerByteBufMessageDecoder);
        pipeline.addLast("packetInboundHandler", this.cvimServerInboundMessageHandler);
        pipeline.addLast("frameEncoder", this.cvimServerEncoder);
    }
}
