"""
.. module stratumgs.web

The web server for stratumgs.
"""

import datetime
import os

import tornado.web
import tornado.websocket
import tornado.httpserver
import tornado.ioloop

import stratumgs.game
import stratumgs.client.server


def init(host, port, debug):
    """
        Initialize the web server.

        :param port: The web server port.
        :type port: int
   """

    template_path = os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        "assets", "templates")
    static_files_path = os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        "assets", "web")
    app = tornado.web.Application([
        tornado.web.url(r"/", HomeHandler, name="main"),
        tornado.web.url(r"/games", GamesHandler, name="games"),
        tornado.web.url(r"/games/([^/]+)/configure", ConfigureHandler, name="configure"),
        tornado.web.url(r"/games/([^/]+)/start", StartHandler, name="start"),
        tornado.web.url(r"/games/([^/]+)/view/([\d]+)", ViewHandler, name="view"),
        tornado.web.url(r"/games/([^/]+)/view/([\d]+)/socket", ViewSocketHandler,
                        name="view_socket"),
        tornado.web.url(r"/matches", MatchesHandler, name="matches"),
        tornado.web.url(r"/players", PlayersHandler, name="players"),
        tornado.web.url(r"/assets/(.*)", tornado.web.StaticFileHandler,
                        {"path": static_files_path}, name="static")
    ], template_path=template_path, debug=debug)
    server = tornado.httpserver.HTTPServer(app)
    server.listen(port, address=host)


class LoggingHandler(tornado.web.RequestHandler):
    """
        Base class for all request handlers. Logs the time, method, uri, and
        HTTP version to the console for each request.
    """

    def prepare(self):
        print("[{datetime}] {req.method} {req.uri} {req.version}".format(
            datetime=datetime.datetime.now().strftime("%m-%d-%Y %H:%M"),
            req=self.request))


class HomeHandler(LoggingHandler):
    """
        Renders the home page.
    """

    def get(self):
        self.render("home.html")


class GamesHandler(LoggingHandler):
    """
        Lists the available games to play.
    """

    def get(self):
        games = stratumgs.game.get_available_game_engines()
        self.render("games.html", games=games)


class ConfigureHandler(LoggingHandler):
    """
        Displays a configuration screen to configure a new game.
    """

    def get(self, game):
        players = stratumgs.client.server.get_available_client_names_for_game(game)
        config = stratumgs.game.get_game_configuration(game)
        self.render("configure.html", players=players, game_name=game, config=config)


class StartHandler(LoggingHandler):
    """
        Starts a new game.
    """

    def post(self, game):
        player_ids = self.get_arguments("players")
        game_id = stratumgs.game.init_game_engine(game, player_ids=player_ids)
        self.redirect("/games/tictactoe/view/{}".format(game_id))


class ViewHandler(LoggingHandler):
    """
        Displays a game.
    """

    def get(self, game, gid):
        game_template = self.render_string("games/{}.html".format(game))
        self.render("view.html", game_name=game, game_template=game_template)


class ViewSocketHandler(tornado.websocket.WebSocketHandler):
    """
        Handles websocket connections for viewing games.
    """

    def open(self, game, game_id):
        self.is_open = True
        stratumgs.game.get_game_runner(int(game_id)).add_view(self)

    def on_close(self):
        self.is_open = False

    def on_message(self, message):
        pass


class MatchesHandler(LoggingHandler):
    """
        Displays current matches.
    """

    def get(self):
        all_matches = stratumgs.game.get_current_games()
        active_matches = []
        inactive_matches = []
        for match in all_matches:
            if match[1].is_running:
                active_matches.append(match)
            else:
                inactive_matches.append(match)
        self.render("matches.html",
                    active_matches=active_matches,
                    inactive_matches=inactive_matches)


class PlayersHandler(LoggingHandler):
    """
        List currently connected players.
    """

    def get(self):
        players = stratumgs.client.server.get_connected_clients()
        self.render("players.html", players=players)

"""
.. module stratumgs.web

The web server for stratumgs.
"""

import datetime
import os

import tornado.web
import tornado.websocket
import tornado.httpserver
import tornado.ioloop

import stratumgs.game
import stratumgs.client.server


def init(host, port, debug):
    """
        Initialize the web server.

        :param port: The web server port.
        :type port: int
   """

    template_path = os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        "assets", "templates")
    static_files_path = os.path.join(
        os.path.dirname(os.path.realpath(__file__)),
        "assets", "web")
    app = tornado.web.Application([
        tornado.web.url(r"/", HomeHandler, name="main"),
        tornado.web.url(r"/games", GamesHandler, name="games"),
        tornado.web.url(r"/games/([^/]+)/configure", ConfigureHandler, name="configure"),
        tornado.web.url(r"/games/([^/]+)/start", StartHandler, name="start"),
        tornado.web.url(r"/games/([^/]+)/view/([\d]+)", ViewHandler, name="view"),
        tornado.web.url(r"/games/([^/]+)/view/([\d]+)/socket", ViewSocketHandler,
                        name="view_socket"),
        tornado.web.url(r"/matches", MatchesHandler, name="matches"),
        tornado.web.url(r"/players", PlayersHandler, name="players"),
        tornado.web.url(r"/assets/(.*)", tornado.web.StaticFileHandler,
                        {"path": static_files_path}, name="static")
    ], template_path=template_path, debug=debug)
    server = tornado.httpserver.HTTPServer(app)
    server.listen(port, address=host)


class LoggingHandler(tornado.web.RequestHandler):
    """
        Base class for all request handlers. Logs the time, method, uri, and
        HTTP version to the console for each request.
    """

    def prepare(self):
        print("[{datetime}] {req.method} {req.uri} {req.version}".format(
            datetime=datetime.datetime.now().strftime("%m-%d-%Y %H:%M"),
            req=self.request))


class HomeHandler(LoggingHandler):
    """
        Renders the home page.
    """

    def get(self):
        self.render("home.html")


class GamesHandler(LoggingHandler):
    """
        Lists the available games to play.
    """

    def get(self):
        games = stratumgs.game.get_available_game_engines()
        self.render("games.html", games=games)


class ConfigureHandler(LoggingHandler):
    """
        Displays a configuration screen to configure a new game.
    """

    def get(self, game):
        players = stratumgs.client.server.get_available_client_names_for_game(game)
        config = stratumgs.game.get_game_configuration(game)
        self.render("configure.html", players=players, game_name=game, config=config)


class StartHandler(LoggingHandler):
    """
        Starts a new game.
    """

    def post(self, game):
        player_ids = self.get_arguments("players")
        game_id = stratumgs.game.init_game_engine(game, player_ids=player_ids)
        self.redirect("/games/tictactoe/view/{}".format(game_id))


class ViewHandler(LoggingHandler):
    """
        Displays a game.
    """

    def get(self, game, gid):
        game_template = self.render_string("games/{}.html".format(game))
        self.render("view.html", game_name=game, game_template=game_template)


class ViewSocketHandler(tornado.websocket.WebSocketHandler):
    """
        Handles websocket connections for viewing games.
    """

    def open(self, game, game_id):
        self.is_open = True
        stratumgs.game.get_game_runner(int(game_id)).add_view(self)

    def on_close(self):
        self.is_open = False

    def on_message(self, message):
        pass


class MatchesHandler(LoggingHandler):
    """
        Displays current matches.
    """

    def get(self):
        all_matches = stratumgs.game.get_current_games()
        active_matches = []
        inactive_matches = []
        for match in all_matches:
            if match[1].is_running:
                active_matches.append(match)
            else:
                inactive_matches.append(match)
        self.render("matches.html",
                    active_matches=active_matches,
                    inactive_matches=inactive_matches)


class PlayersHandler(LoggingHandler):
    """
        List currently connected players.
    """

    def get(self):
        players = stratumgs.client.server.get_connected_clients()
        self.render("players.html", players=players)

.. module stratumgs.web  The web server for stratumgs. Initialize the web server.          :param port: The web server port.         :type port: int Base class for all request handlers. Logs the time, method, uri, and         HTTP version to the console for each request. Renders the home page. Lists the available games to play. Displays a configuration screen to configure a new game. Starts a new game. Displays a game. Handles websocket connections for viewing games. Displays current matches. List currently connected players.