package com.pwt.netty.server;

import cn.hutool.core.thread.NamedThreadFactory;
import com.pwt.common.constant.CacheConstants;
import com.pwt.common.utils.CacheMap;
import com.pwt.netty.initializer.NettyServerChannelInitializer;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;

/**
 * @author linyun
 * @version V1.0
 * @Title: NettyServer
 * @Description: netty服务端
 * @date 2022/11/01
 **/
@Component
@Slf4j
@ChannelHandler.Sharable
public class NettyServer {

    /**
     * NioEventLoop并不是一个纯粹的I/O线程，它除了负责I/O的读写之外 创建了两个NioEventLoopGroup，
     * 它们实际是两个独立的Reactor线程池。 一个用于接收客户端的TCP连接，
     * 另一个用于处理I/O相关的读写操作，或者执行系统Task、定时任务Task等。
     */
    private final EventLoopGroup bossGroup = new NioEventLoopGroup(1, new NamedThreadFactory("socketBossGroup", true));
    private final EventLoopGroup workerGroup = new NioEventLoopGroup(2, new NamedThreadFactory("socketWorker", true));
    private Channel channel;

    /**
     * 启动服务
     *
     * @return
     * @throws Exception
     */
    public ChannelFuture start() throws Exception
    {

        ChannelFuture channelFuture = null;
        String systemIp = (String) CacheMap.get(CacheConstants.PWT_CONFIG_KEY + "systemIp");
//        int systemPort = (int) CacheMap.get(CacheConstants.PWT_CONFIG_KEY + "systemPort");
        int systemPort = 3100;
        try
        {
            // ServerBootstrap负责初始化netty服务器，并且开始监听端口的socket请求
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .localAddress(new InetSocketAddress(systemIp, systemPort))
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childHandler(new NettyServerChannelInitializer());
            // 绑定端口
            channelFuture = b.bind();
            channelFuture.syncUninterruptibly();
            log.info("======NettyServer启动成功!!!=========");
            // 等待关闭
            channel = (Channel) channelFuture.channel();
        } catch (Exception e)
        {
            e.printStackTrace();
        } finally
        {
            if (channelFuture != null && channelFuture.isSuccess())
            {
                log.info("Netty server listening " + systemIp + " on port " + systemPort + " and ready for connections...");
            } else
            {
                log.error("Netty server start up Error!");
            }
        }
        return channelFuture;
    }

    /**
     * 停止服务
     */
    public void destroy()
    {
        log.info("Shutdown Netty Server...");
        if (channel != null)
        {
            channel.close();
        }
        workerGroup.shutdownGracefully();
        bossGroup.shutdownGracefully();
        log.info("Shutdown Netty Server Success!");
    }
}
