package  org.ts.ddcs.net;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel;
import lombok.extern.slf4j.Slf4j;

/**
 * UDP网络连接
 * @author dylan
 */
@Slf4j
public class DataChannelUdpWithNio {

    private String channelKey;
    private String bindAgreeement;

    private boolean nioChannelRunning = false;
    /*
    监听端口
     */
    private int port = 0;
    private EventLoopGroup bossGroup = null;

    public DataChannelUdpWithNio(String key, String agreement){
        this.channelKey = key;
        this.bindAgreeement = agreement;
    }

    public DataChannelUdpWithNio(String key){
        this.channelKey = key;
    }

    public DataChannelUdpWithNio colseChannel() {
        this.nioChannelRunning = false;
        if (null != bossGroup) {
            bossGroup.shutdownGracefully();
            bossGroup = null;
        }
        log.info("******************** 关闭 NIO ********************");
        return this;
    }

    public DataChannelUdpWithNio openChannel(int port) {
        this.nioChannelRunning = true;
        this.port = port;
        log.info("******************** 启动 NIO ********************");
        return this;
    }

    public void async() {
        if (!this.nioChannelRunning) {
            log.error("调用 Async() 发生错误:未打开通道");
            return;
        }
        new DataChannelUdpWithNio.AcceptThread().start();
    }

    private class AcceptThread extends Thread {

        @Override
        public void run() {
            bossGroup = new NioEventLoopGroup();
            try {
                Bootstrap b = new Bootstrap();
                b.group(bossGroup)
                        .channel(NioDatagramChannel.class)
                        .option(ChannelOption.SO_BROADCAST, true)
                        .handler(new UdpDataHandler(channelKey,bindAgreeement));
                ChannelFuture f = b.bind(port).sync().channel().closeFuture().await();
                f.channel().closeFuture().sync();
            } catch (InterruptedException e) {
                log.error(e.getMessage());
            } finally {
                if (null != bossGroup) {
                    bossGroup.shutdownGracefully();
                }
            }
        }
    }
}
