#!python -u

import pelix.framework
import argparse
import json
import yaml
import os
import logging
import sys
from bembel.bembel_constants import default_framework_conf, empty_extra_bundles_conf
from pelix.misc.init_handler import InitFileHandler
from pelix.ipopo.constants import use_ipopo
from logstash_formatter import LogstashFormatter
from prometheus_client import start_http_server

_logger = logging.getLogger(__name__)


def get_arguments():
    p = argparse.ArgumentParser(
        description='Bembel is a lightweight component application framework.')

    p.add_argument(
        '-c',
        '--console',
        action='store_true',
        help='Starts bembel with interactive console',
    )
    p.add_argument(
        '-i',
        '--init',
        action='store_true',
        default=False,
        help='Initializes the framework with basic configuration',
    )
    args = p.parse_args()

    return args


def init_prometheus():
    start_http_server(9111)


def init_logger():
    logger = logging.getLogger()

    logger.setLevel(logging.getLevelName(os.getenv('LOG_LEVEL', "DEBUG")))
    #logger.handlers = []

    handler = logging.StreamHandler(stream=sys.stdout)
    handler.setLevel(logging.INFO)

    #formatter = LogstashFormatter()
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s')
    handler.setFormatter(formatter)
    logger.addHandler(handler)
    _logger.info("Logger initialized")


def main():

    arg = get_arguments()

    if arg.init:
        print("here")
        if not os.path.isfile("framework.conf"):
            with open("framework.conf", "w+") as f:
                print("here2")
                f.write(default_framework_conf)
        if not os.path.isfile("extra-bundles.conf"):
            with open("extra-bundles.conf", "w+") as f:
                f.write(empty_extra_bundles_conf)
        if not os.path.isdir("etc"):
            os.mkdir("etc")

    init_prometheus()
    init = InitFileHandler()

    try:
        init.load("framework.conf")
    except Exception:
        print("Can not find framwork.conf")
        exit(1)

    try:
        init.load("extra-bundles.conf")
    except Exception:
        print("Can not find extra-bundles.conf")
        exit(1)

    components = []

    for filename in os.listdir("etc"):
        if filename.endswith(".yaml"):
            with open(os.path.join("etc", filename), "r") as filep:
                data = yaml.full_load(filep)
                if data:
                    components += data

    init.normalize()

    if arg.console:
        init.bundles.append("pelix.shell.console")
    else:
        init_logger()

    framework = pelix.framework.create_framework(init.bundles, init.properties)
    framework.start()

    if "pelix.ipopo.core" in init.bundles:
        ctx = framework.get_bundle_context()
        init.instantiate_components(ctx)
        with use_ipopo(ctx) as ipopo:
            if components:
                for component in components:
                    ipopo.instantiate(component["factory"],
                                      component["name"], component["properties"])

    else:
        _logger.critical("iPOPO has not been setup in the configuration file.")
    try:
        framework.wait_for_stop()
    except KeyboardInterrupt:
        framework.stop()


# Classic entry point...
if __name__ == "__main__":
    main()
