#!/usr/bin/env python

import argparse
from expvar.stats import stats
import logging
import os
import sys
from threading import Thread
from time import sleep
import tornado.ioloop
import tornado.httpserver
import tornado.web

import grouper
from grouper.api.routes import HANDLERS
from grouper.api.settings import settings
from grouper.email import SendEmailThread
from grouper.graph import GroupGraph
from grouper.models import get_db_engine, Session, load_plugins
from grouper.util import get_loglevel, get_database_url

from sqlalchemy.exc import OperationalError

sa_log = logging.getLogger("sqlalchemy.engine.base.Engine")


class Application(tornado.web.Application):
    def __init__(self, *args, **kwargs):
        self.my_settings = kwargs.pop("my_settings", {})
        super(Application, self).__init__(*args, **kwargs)


class DbRefreshThread(Thread):
    def __init__(self, graph, refresh_interval, *args, **kwargs):
        self.graph = graph
        self.refresh_interval = refresh_interval
        Thread.__init__(self, *args, **kwargs)

    def run(self):

        while True:
            sleep(self.refresh_interval)

            logging.debug("Updating Graph from Database.")
            try:
                session = Session()
                self.graph.update_from_db(session)
                session.close()
                stats.set_gauge("successful-db-update", 1)
            except OperationalError:
                Session.configure(bind=get_db_engine(get_database_url(settings)))
                logging.critical("Failed to connect to database.")
                stats.set_gauge("successful-db-update", 0)


def main(argv):

    parser = argparse.ArgumentParser(description="Grouper Web Server.")
    parser.add_argument("-c", "--config", default="/etc/grouper.yaml",
                        help="Path to config file.")
    parser.add_argument("-v", "--verbose", action="count", default=0,
                        help="Increase logging verbosity.")
    parser.add_argument("-q", "--quiet", action="count", default=0,
                        help="Decrease logging verbosity.")
    parser.add_argument("-V", "--version", action="version",
                        version="%%(prog)s %s" % grouper.__version__,
                        help="Display version information.")
    parser.add_argument("-p", "--port", type=int, default=None, help="Override port in config.")
    args = parser.parse_args()
    settings.start_config_thread(args.config, "api")

    log_level = get_loglevel(args)
    logging.basicConfig(
        level=log_level,
        format=settings.log_format,
    )

    if log_level < 0:
        sa_log.setLevel(logging.INFO)

    if settings.plugin_dir:
        if not os.path.exists(settings.plugin_dir):
            logging.fatal("Plugin directory does not exist")
            sys.exit(1)
        load_plugins(settings.plugin_dir, service_name="grouper-api")

    tornado_settings = {
        "debug": settings.debug,
    }

    Session.configure(bind=get_db_engine(get_database_url(settings)))

    logging.info("Initilializing graph data.")
    session = Session()
    graph = GroupGraph.from_db(session)
    session.close()

    my_settings = {
        "graph": graph,
    }

    application = Application(HANDLERS, my_settings=my_settings, **tornado_settings)

    refresher = DbRefreshThread(graph, settings.refresh_interval)
    refresher.daemon = True
    refresher.start()

    emailer = SendEmailThread(settings)
    emailer.daemon = True
    emailer.start()

    port = args.port or settings.port

    logging.info("Starting application server on port %d", port)
    server = tornado.httpserver.HTTPServer(application)
    server.bind(port)
    server.start()
    try:
        tornado.ioloop.IOLoop.instance().start()
    except KeyboardInterrupt:
        tornado.ioloop.IOLoop.instance().stop()
    finally:
        print "Bye"


if __name__ == "__main__":
    main(sys.argv)
