// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.server.core.io.transport;

import io.netty.bootstrap.AbstractBootstrap;
import java.util.concurrent.TimeUnit;
import java.net.SocketAddress;
import io.netty.channel.ChannelFuture;
import java.net.InetSocketAddress;
import io.netty.channel.ServerChannel;
import io.netty.channel.ChannelHandler;
import com.hypixel.hytale.server.core.io.netty.HytaleChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.Channel;
import java.util.logging.Level;
import com.hypixel.hytale.server.core.io.netty.NettyUtil;
import io.netty.bootstrap.ServerBootstrap;
import javax.annotation.Nonnull;
import io.netty.channel.EventLoopGroup;
import com.hypixel.hytale.logger.HytaleLogger;

public class TCPTransport implements Transport
{
    private static final HytaleLogger LOGGER;
    @Nonnull
    private final EventLoopGroup bossGroup;
    @Nonnull
    private final EventLoopGroup workerGroup;
    private final ServerBootstrap bootstrap;
    
    public TCPTransport() throws InterruptedException {
        this.bossGroup = NettyUtil.getEventLoopGroup(1, "ServerBossGroup");
        this.workerGroup = NettyUtil.getEventLoopGroup("ServerWorkerGroup");
        final Class<? extends ServerChannel> serverChannel = NettyUtil.getServerChannel();
        TCPTransport.LOGGER.at(Level.INFO).log("Using Server Channel: %s...", serverChannel.getSimpleName());
        this.bootstrap = ((AbstractBootstrap<ServerBootstrap, C>)((AbstractBootstrap<ServerBootstrap, C>)((AbstractBootstrap<ServerBootstrap, Channel>)new ServerBootstrap().group(this.bossGroup, this.workerGroup)).channel(serverChannel)).option(ChannelOption.SO_BACKLOG, 256)).option(ChannelOption.SO_REUSEADDR, true).childHandler(new HytaleChannelInitializer()).validate();
        this.bootstrap.register().sync();
    }
    
    @Nonnull
    @Override
    public TransportType getType() {
        return TransportType.TCP;
    }
    
    @Override
    public ChannelFuture bind(final InetSocketAddress address) throws InterruptedException {
        return this.bootstrap.bind(address).sync();
    }
    
    @Override
    public void shutdown() {
        TCPTransport.LOGGER.at(Level.INFO).log("Shutting down bossGroup...");
        try {
            this.bossGroup.shutdownGracefully(0L, 1L, TimeUnit.SECONDS).await(1L, TimeUnit.SECONDS);
        }
        catch (final InterruptedException e) {
            TCPTransport.LOGGER.at(Level.SEVERE).withCause(e).log("Failed to await for listener to close!");
            Thread.currentThread().interrupt();
        }
        TCPTransport.LOGGER.at(Level.INFO).log("Shutting down workerGroup...");
        try {
            this.workerGroup.shutdownGracefully(0L, 1L, TimeUnit.SECONDS).await(1L, TimeUnit.SECONDS);
        }
        catch (final InterruptedException e) {
            TCPTransport.LOGGER.at(Level.SEVERE).withCause(e).log("Failed to await for listener to close!");
            Thread.currentThread().interrupt();
        }
    }
    
    static {
        LOGGER = HytaleLogger.forEnclosingClass();
    }
}
