package com.jpsoft.shinestar.lapi;

import com.jpsoft.shinestar.lapi.handler.*;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.*;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.handler.timeout.ReadTimeoutHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PreDestroy;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class LapiTcpServer {
    @Autowired
    private PersonVerificationHandler personVerificationHandler;

    @Autowired
    private HeartReportHandler heartReportHandler;

    @Autowired
    private ResponseDataHandler responseDataHandler;

    @Value("${server.port}")
    private Integer port;

    private Channel serverChannel;

    private final int READ_TIME_OUT = 300;

    public void start(int port){
        NioEventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();

        ServerBootstrap b = new ServerBootstrap();

        b.group(bossGroup,workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer(){
                    @Override
                    protected void initChannel(Channel channel) throws Exception {

                        //通道空闲超时时间
                        channel.pipeline().addLast(new IdleStateHandler(READ_TIME_OUT, READ_TIME_OUT, READ_TIME_OUT, TimeUnit.SECONDS));

                        channel.pipeline().addLast(new HttpEncoder());
                        channel.pipeline().addLast(new HttpDecoder());
                        channel.pipeline().addLast("aggregator", new HttpObjectAggregator(10 * 1024 * 1024));

                        //保活超时时间
                        channel.pipeline().addLast(new ReadTimeoutHandler(READ_TIME_OUT));

                        channel.pipeline().addLast(new ParseHttpHandler());
                        channel.pipeline().addLast(heartReportHandler);
                        channel.pipeline().addLast(personVerificationHandler);
                        channel.pipeline().addLast(responseDataHandler);
                    }
                });

        ChannelFuture channelFuture = b.bind("0.0.0.0",port);
        serverChannel = channelFuture.channel();

        channelFuture.addListener((future)-> {
            if(future.isSuccess()){
                log.warn(String.format("netty 已监听%d端口",port));
            }
        });
    }

    @PreDestroy
    public void stop(){
        if (serverChannel!=null && serverChannel.isOpen()){
            serverChannel.close();
        }
    }
}
