#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import logging
import signal
import os

from flamingo.server.logging import RPCHandler

rpc_logging_handler = RPCHandler(level=logging.DEBUG)

logging.basicConfig(level=logging.DEBUG)
logging.root.handlers = [rpc_logging_handler]

# setup server
import asyncio  # NOQA

from aiohttp.web import Application, run_app  # NOQA

from flamingo.core.utils.cli import gen_default_parser, parse_args, error  # NOQA
from flamingo.server.server import Server  # NOQA

# parse command line
parser = gen_default_parser(prog='flamingo server')

parser.add_argument('--port', type=int, default=8080)
parser.add_argument('--host', type=str, default='localhost')
parser.add_argument('--log-backlog', type=int, default=2500)
parser.add_argument('--shell', action='store_true')
parser.add_argument('--shell-history', action='store_true')

namespace, settings = parse_args(parser, setup_logging=False)

log_level = {
    'DEBUG': logging.DEBUG,
    'INFO': logging.INFO,
    'WARN': logging.WARN,
    'ERROR': logging.ERROR,
    'FATAL': logging.FATAL,
}[namespace.log_level]

rpc_logging_handler.set_internal_level(log_level)
rpc_logging_handler.buffer_max_size = namespace.log_backlog
rpc_logging_handler.loggers = namespace.loggers

# setup aiohttp app
loop = asyncio.get_event_loop()
app = Application(loop=loop)

# setup flamingo server
try:
    server = Server(app=app, loop=loop, settings=namespace.settings or [],
                    rpc_logging_handler=rpc_logging_handler)

except KeyboardInterrupt:
    exit()

# setup shell
if namespace.shell:
    async def start_shell(server):
        def _start_shell(server):
            server.start_shell(history=namespace.shell_history)
            os.kill(os.getpid(), signal.SIGTERM)

        await server.await_unlock()
        await server.rpc.worker_pool.run(_start_shell, server)

        print('shell stopped')

    loop.create_task(start_shell(server))

# run
print('starting server on http://localhost:{}/'.format(namespace.port))

try:
    # this is a hack that is necessary because of the current design of the
    # rpc worker_pool
    loop.close = lambda *args, **kwargs: None

    run_app(app=app, host=namespace.host, port=namespace.port,
            print=lambda *args, **kwargs: None)

except OSError:
    server.shutdown()
    exit(error('ERROR: can not bind to port {}'.format(namespace.port)))

print('\rshutting down server')
server.shutdown()
