#!/usr/bin/env python3
import argparse
import _thread
import sys
import gunicorn.app.base
from tabulate import tabulate

sys.path.append(".")

from lifeguard import setup
from lifeguard.bootstrap import generate_base_project
from lifeguard.context import LIFEGUARD_CONTEXT
from lifeguard.scheduler import start_scheduler
from lifeguard.settings import (
    LIFEGUARD_SERVER_PORT,
    LIFEGUARD_SERVER_NUMBER_OF_WORKS,
    SETTINGS_MANAGER,
    SettingsManager,
)


def display_settings():
    data = {"Name": [], "Description": [], "Value": []}

    settings_manager = SettingsManager(SETTINGS_MANAGER.settings)

    for entry in settings_manager.settings:
        data["Name"].append(entry)
        data["Description"].append(settings_manager.settings[entry]["description"])
        data["Value"].append(settings_manager.read_value(entry))

    print(tabulate(data, headers="keys"))


# Scheduler
def scheduler(start_in_thread):
    if start_in_thread:
        _thread.start_new_thread(start_scheduler, ())
    else:
        start_scheduler()


# Server
class StandaloneApplication(gunicorn.app.base.BaseApplication):
    def __init__(self, app, options=None):
        self.options = options or {}
        self.application = app
        super().__init__()

    def load_config(self):
        config = {
            key: value
            for key, value in self.options.items()
            if key in self.cfg.settings and value is not None
        }
        for key, value in config.items():
            self.cfg.set(key.lower(), value)

    def load(self):
        return self.application


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-d", "--settings", help="display all plugins settings", action="store_true"
    )
    parser.add_argument(
        "-g",
        "--generate",
        help="generate base of lifeguard instance project",
        action="store_true",
    )
    parser.add_argument(
        "-q",
        "--no-scheduler",
        help="execute lifeguard without scheduler",
        action="store_true",
    )
    parser.add_argument(
        "-s",
        "--no-server",
        help="execute lifeguard without server",
        action="store_true",
    )
    args = parser.parse_args()

    if args.generate:
        generate_base_project()
        sys.exit(0)

    LIFEGUARD_CONTEXT.only_settings = args.settings

    setup(LIFEGUARD_CONTEXT)

    if args.settings:
        display_settings()
        sys.exit(0)

    if not args.no_scheduler:
        start_in_thread = not args.no_server
        scheduler(start_in_thread)

    if not args.no_server:
        from lifeguard.server import APP

        StandaloneApplication(
            APP,
            {
                "bind": "{}:{}".format("0.0.0.0", LIFEGUARD_SERVER_PORT),
                "workers": LIFEGUARD_SERVER_NUMBER_OF_WORKS,
            },
        ).run()
