package com.its.vms.xnettcp.vms;

import com.its.app.utils.NettyUtils;
import com.its.vms.config.CommunicationConfig;
import com.its.vms.dto.TbVmsCtlrDto;
import com.its.vms.process.DbmsDataProcess;
import com.its.vms.service.AppRepositoryService;
import com.its.vms.xnettcp.vms.codec.VmsTcpServerDleStuffingDecoder;
import com.its.vms.xnettcp.vms.codec.VmsTcpServerEncoder;
import com.its.vms.xnettcp.vms.handler.VmsServerIdleStateHandler;
import com.its.vms.xnettcp.vms.handler.VmsServerPacketInboundHandler;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.TimeUnit;

@Slf4j
@RequiredArgsConstructor
public class VmsTcpCommServerInitializer extends ChannelInitializer<Channel> {

    private final CommunicationConfig config;
    private final DbmsDataProcess dbmsDataProcess;
    private final VmsServerPacketInboundHandler vmsServerPacketInboundHandler;
    private final VmsTcpServerEncoder vmsTcpServerEncoder;
    private final AppRepositoryService repoService;

    @Override
    protected void initChannel(Channel channel) throws Exception {
        String ipAddress  = NettyUtils.getRemoteIpAddress(channel);
        TbVmsCtlrDto obj = this.repoService.getIpAddrMap(ipAddress);
        if (obj == null) {
            log.error("VmsTcpCommServerInitializer.----initChannel: {}, Unknown ip address. will be closed.", ipAddress);
            channel.disconnect();
            channel.close();
        }
        else {
            IdleStateHandler tcpIdleStateHandler = new IdleStateHandler(
                    this.config.getReaderIdleTimeSeconds(),
                    this.config.getWriterIdleTimeSeconds(),
                    this.config.getAllIdleTimeSeconds(),
                    TimeUnit.SECONDS);

            ChannelPipeline pipeline = channel.pipeline();
            //pipeline.addLast(new LoggingHandler(LogLevel.INFO));
            pipeline.addLast("vmsTcpIdleStateHandler", tcpIdleStateHandler);
            pipeline.addLast("vmsServerIdleStateHandler", new VmsServerIdleStateHandler(obj, this.dbmsDataProcess, this.config));   // packet idle state handler, event handler
            if (obj.getProtocolVer() == 0) {
                pipeline.addLast("vmsServerDecoder", new VmsTcpServerDleStuffingDecoder(this.config, this.repoService, obj));  // Decoding handler
            }
            else {
                pipeline.addLast("vmsServerDecoder", new VmsTcpServerDleStuffingDecoder(this.config, this.repoService, obj));  // Decoding handler
            }
            pipeline.addLast("vmsServerPacketInboundHandler", this.vmsServerPacketInboundHandler); // packet distribute handler add
            pipeline.addLast("vmsServerEncoder", this.vmsTcpServerEncoder);  // Encoding handler
        }
    }

}
