package io.luna;

import io.luna.game.model.World;
import io.luna.net.LunaChannelHandlers;
import io.luna.net.LunaNetworkConstants;
import io.luna.task.AsyncTaskService;
import io.luna.util.StringUtils;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.ResourceLeakDetector;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

/**
 * Prepares the Netty networking implementation and the game logic service loop,
 * while simultaneously executing startup tasks in the background.
 * 
 * @author lare96 <http://github.org/lare96>
 */
public final class Server {

    /**
     * The logger that will print important information.
     */
    private final Logger logger = LogManager.getLogger(Server.class);

    /**
     * The asynchronous task service that will execute our startup tasks in the
     * background.
     */
    private final AsyncTaskService service = AsyncTaskService.newService();

    /**
     * A default access level constructor, to prevent instantiation from classes
     * outside of the {@code io.luna} package.
     */
    Server() {}

    /**
     * Creates the Luna server by initializing all of the individual modules.
     * 
     * @throws Exception
     *             If any errors occur while creating any of the individual
     *             modules.
     */
    public void create() throws Exception {
        logger.info("Luna is being initialized...");

        initStartupTasks();
        initGame();
        service.awaitTerminated(); // Await completion of background tasks.
        World.getService().awaitRunning(); // Await completion of logic service.
        initNetty();

        logger.info("Luna is now online on port " + LunaNetworkConstants.PORT + ".");
    }

    /**
     * Initializes the Netty implementation. Will block indefinitely until the
     * bootstrap is bound.
     * 
     * @throws Exception
     *             If any errors occur while creating the Netty module.
     */
    private void initNetty() throws Exception {
        ServerBootstrap bootstrap = new ServerBootstrap();
        EventLoopGroup loopGroup = new NioEventLoopGroup();

        ResourceLeakDetector.setLevel(LunaNetworkConstants.RESOURCE_LEAK_DETECTION);

        bootstrap.group(loopGroup);
        bootstrap.channel(NioServerSocketChannel.class);
        bootstrap.childHandler(LunaChannelHandlers.CHANNEL_INITIALIZER);
        bootstrap.bind(LunaNetworkConstants.PORT).syncUninterruptibly();

        if (!LunaNetworkConstants.PREFERRED_PORTS.contains(LunaNetworkConstants.PORT)) {
            String prefix = "The preferred ports for Runescape servers are ";
            logger.info(StringUtils.joinWithAnd(prefix, ".", LunaNetworkConstants.PREFERRED_PORTS));
        }
    }

    /**
     * Initializes the game logic service asynchronously, does not wait for it
     * to enter a {@code RUNNING} state.
     * 
     * @throws Exception
     *             If any errors occur while creating the GameService module.
     */
    private void initGame() throws Exception {
        World.getService().startAsync();
    }

    /**
     * Executes all startup tasks in the background using a
     * {@link io.luna.task.AsyncTaskService}.
     * 
     * @throws Exception
     *             If any errors occur while executing startup tasks.
     */
    private void initStartupTasks() throws Exception {
        service.add(() -> logger.debug("Startup tasks working correctly.")); // Temporary.
        service.startAsync();
    }
}

@@ -17,42 +17,8 @@
 %0D%0A%0D%0A
-import io.luna.game.model.World;%0D%0A
 impo
@@ -1718,37 +1718,36 @@
 tasks.%0D%0A        
-World
+Luna
 .getService().aw
@@ -1807,25 +1807,20 @@
         
+b
 in
-itNetty
+d
 ();%0D%0A%0D%0A 
@@ -2169,17 +2169,12 @@
 oid 
+b
 in
-itNetty
+d
 () t
@@ -3253,13 +3253,12 @@
     
-World
+Luna
 .get

Rename initNetty -> bind.