package com.zksy.environment.config;

import com.zksy.environment.utils.ServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.MessageToMessageDecoder;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Slf4j
@Configuration
public class NtServer {

    @Value("${netty.port:8084}")
    private int port;

    private ServerSocketChannel serverSocketChannel;

    private EventLoopGroup boss;

    private EventLoopGroup worker;

    @PostConstruct
    private void startServer() {
        log.info("进入程序....");
        Thread thread = new Thread(() -> {
            //服务端要建立两个group，一个负责接收客户端的连接，一个负责处理数据传输
            //连接处理group
            boss = new NioEventLoopGroup(1);
            //事件处理group
            worker = new NioEventLoopGroup();
            ServerBootstrap bootstrap = new ServerBootstrap();
            // 绑定处理group
            bootstrap.group(boss, worker).channel(NioServerSocketChannel.class)
                    //保持连接数
                    .option(ChannelOption.SO_BACKLOG, 300)
                    //有数据立即发送
                    .option(ChannelOption.TCP_NODELAY, true)
                    //保持连接
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    // 设置心跳检测
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel sc) throws Exception {
                            ChannelPipeline p = sc.pipeline();
                            // 添加心跳检测处理器
                            p.addLast(new IdleStateHandler(0, 0, 180, TimeUnit.SECONDS)); // 每3分钟检查一次空闲状态
                            p.addLast(new ServerHandler());
                        }
                    });

            //绑定端口，同步等待成功
            ChannelFuture future;
            try {
                future = bootstrap.bind(port).sync();
                if (future.isSuccess()) {
                    serverSocketChannel = (ServerSocketChannel) future.channel();
                    log.info("服务端启动成功，端口：" + port);
                } else {
                    log.info("服务端启动失败！");
                }

                //等待服务监听端口关闭
                future.channel().closeFuture().sync();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //退出，释放线程池资源
                if (boss != null) {
                    boss.shutdownGracefully();
                }
                if (worker != null) {
                    worker.shutdownGracefully();
                }
            }
        });
        thread.start();
    }

    /**
     * 释放资源
     */
    @PreDestroy
    public void destroy() {
        if (boss != null) {
            boss.shutdownGracefully();
        }
        if (worker != null) {
            worker.shutdownGracefully();
        }
    }
}