package com.fr.tx.common.netty.wbs;

import java.net.InetSocketAddress;

import javax.swing.JTextArea;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.util.concurrent.ImmediateEventExecutor;

/**
 * netty服务主入口
 * @author Allen
 * @date 2016年12月9日
 */
public final class WebSocketServer {


    private final ChannelGroup group = new DefaultChannelGroup(
        ImmediateEventExecutor.INSTANCE);

    private final EventLoopGroup workerGroup = new NioEventLoopGroup();

    private Channel channel;

    private JTextArea jta;
    
    private String port;
    private String ipAddress;
    
    public WebSocketServer(JTextArea jta,String port,String ipAddress) {
        this.jta = jta;
        this.port = port;
        this.ipAddress = ipAddress;
    }

    private final ChannelFuture core(InetSocketAddress address) {
        ServerBootstrap boot = new ServerBootstrap();
        boot.group(workerGroup).channel(NioServerSocketChannel.class);
        boot.childHandler(new ChannelInitializer<Channel>() {

            @Override
            protected void initChannel(Channel channel) throws Exception {
                // 编码模块
                channel.pipeline().addLast("http-codec", new HttpServerCodec());
                // 大数据内容写入模块
                channel.pipeline().addLast("http-chunked", new ChunkedWriteHandler());
                // 组装Http头信息保证完整性
                channel.pipeline().addLast("aggregator", new HttpObjectAggregator(65536));
                // 上下文判断
                channel.pipeline().addLast("handler", new MyWebSocketServerHandler(jta));
            }
        }).option(ChannelOption.SO_BACKLOG, 128)
          .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
          .childOption(ChannelOption.SO_KEEPALIVE, true)
          .childOption(ChannelOption.TCP_NODELAY, true);
        ChannelFuture f = boot.bind(address).syncUninterruptibly();
        channel = f.channel();
        return f;
    }


    /**
     * channel Group回收
     * @author Allen
     * @date 2016年12月13日
     */
    private void recovery() {

        if (channel != null)
            channel.close();
        group.close();
        workerGroup.shutdownGracefully();
    }


    /**
      * 启动
     * @author Allen
     * @date 2016年12月13日
     */
    public final void run() {
		ChannelFuture f = core(new InetSocketAddress(ipAddress,
		        Integer.parseInt(port)));
		// 系统异常则进行回收
		Runtime.getRuntime().addShutdownHook(new Thread() {
		    @Override
		    public void run() {
		        recovery();
		    }
		});
		f.channel().closeFuture().syncUninterruptibly();
    }

}