#!/usr/bin/env python3

import os
import glob
import envtpl
from configparser_extended import ExtendedConfigParser

MODULE_RUNTIME_HOME = os.environ["MODULE_RUNTIME_HOME"]
MFSERV_PLUGINS_HOME = os.path.join(MODULE_RUNTIME_HOME,
                                   "var", "plugins")
CONFIG = os.environ.get('MFCONFIG', 'GENERIC')
HOSTNAME = os.environ.get('MFCOM_HOSTNAME')
HOSTNAME_FULL = os.environ.get('MFCOM_HOSTNAME_FULL')

'''
Below are defined process types depending on the code language
'''

# Available types for watching python (i.e gunicorn)
PYTHON_TYP_LIST = [
    "gunicorn3_sync",
    "gunicorn2_sync",
    "gunicorn3_asyncio"
]

# Available types for watching js (i.e node)
JS_TYP_LIST = [
    "node"
]

# Static type plugin
STATIC_TYP_LIST = [
    "static"
]

# All types
ALL_TYP_LIST = \
    PYTHON_TYP_LIST + \
    JS_TYP_LIST + \
    STATIC_TYP_LIST


def get_conf(plugin_configuration_file):
    plugin_conf = {}
    parser = ExtendedConfigParser(config=CONFIG, strict=False,
                                  inheritance='im', interpolation=None)

    plugin_directory = os.path.dirname(plugin_configuration_file)
    plugin_name = os.path.basename(plugin_directory)

    parser.read(plugin_configuration_file)
    apps = [x.replace("app_", "", 1).split(':')[0] for x in parser.sections()
            if x.startswith("app_")]

    extra_general_nginx_conf_string = ""
    if parser.has_option("general", "extra_nginx_conf_filename"):
        extra_general_nginx_conf_filename = \
            parser.get("general", "extra_nginx_conf_filename")
        if extra_general_nginx_conf_filename != "null":
            extra_general_nginx_conf_filepath = \
                os.path.join(plugin_directory,
                             extra_general_nginx_conf_filename)
            with open(extra_general_nginx_conf_filepath, "r") as f:
                extra_general_nginx_conf_string = f.read()

    plugin_conf["name"] = plugin_name
    plugin_conf["extra_general_nginx_conf_string"] = \
        envtpl.render_string(extra_general_nginx_conf_string,
                             extra_variables={"PLUGIN": plugin_conf})

    plugin_conf['lua_package_paths'] = []
    plugin_conf["apps"] = []

    for app in apps:
        section = "app_%s" % app
        typ = parser.get(section, "type")
        if typ not in ALL_TYP_LIST:
            continue
        if len(glob.glob(os.path.join(plugin_directory, app, '*.lua'))) > 0:
            lua_package_path = os.path.join(plugin_directory, app, '?.lua')
            plugin_conf['lua_package_paths'].append(lua_package_path)
        extra_nginx_conf_string = ""
        if parser.has_option(section, "extra_nginx_conf_filename"):
            extra_nginx_conf_filename = parser.get(section,
                                                   "extra_nginx_conf_filename")
            if extra_nginx_conf_filename != "null":
                extra_nginx_conf_filepath = \
                    os.path.join(plugin_directory,
                                 extra_nginx_conf_filename)
                with open(extra_nginx_conf_filepath, "r") as f:
                    extra_nginx_conf_string = f.read()
        extra_nginx_conf_static_string = ""
        if parser.has_option(section, "extra_nginx_conf_static_filename"):
            extra_nginx_conf_static_filename = \
                parser.get(section, "extra_nginx_conf_static_filename")
            if extra_nginx_conf_static_filename != "null":
                extra_nginx_conf_static_filepath = \
                    os.path.join(plugin_directory,
                                 extra_nginx_conf_static_filename)
                with open(extra_nginx_conf_static_filepath, "r") as f:
                    extra_nginx_conf_static_string = f.read()
        static_routing = True
        if parser.has_option(section, "static_routing"):
            static_routing = parser.getboolean(section, "static_routing")
        virtualdomain_based_routing = True
        if parser.has_option(section, "virtualdomain_based_routing"):
            virtualdomain_based_routing = \
                parser.getboolean(section,
                                  "virtualdomain_based_routing")
        prefix_based_routing = True
        if parser.has_option(section, "prefix_based_routing"):
            prefix_based_routing = \
                parser.getboolean(section,
                                  "prefix_based_routing")
        workdir = os.path.join(os.environ['MODULE_RUNTIME_HOME'], 'var',
                               'plugins', plugin_name, app)
        virtualdomains = set()
        for host in (HOSTNAME, HOSTNAME_FULL, "localhost"):
            virtualdomains.add("%s.%s.%s" % (app, plugin_name, host))
            if app == "main" or len(apps) == 1:
                virtualdomains.add("%s.%s" % (plugin_name, host))
        prefixes = ["/%s/%s" % (plugin_name, app)]
        if app == "main" or len(apps) == 1:
            prefixes.append("/%s" % plugin_name)
        name = "app_%s_%s" % (plugin_name, app)
        app_conf = {"name": name,
                    "app_name": app,
                    "plugin_name": plugin_name,
                    "virtualdomain_based_routing": virtualdomain_based_routing,
                    "prefix_based_routing": prefix_based_routing,
                    "prefixes": prefixes,
                    "virtualdomains": sorted(list(virtualdomains)),
                    "workdir": workdir,
                    "static_routing": static_routing,
                    "socket": "%s/var/default_%s.socket" %
                    (MODULE_RUNTIME_HOME, name),
                    "type": typ}
        if typ in PYTHON_TYP_LIST:
            app_conf["socket"] = "%s/var/gunicorn_%s.socket" % \
                (MODULE_RUNTIME_HOME, name)
        elif typ in JS_TYP_LIST:
            app_conf["socket"] = "%s/var/node_%s.socket" % \
                (MODULE_RUNTIME_HOME, name)
        elif typ in STATIC_TYP_LIST:
            app_conf["socket"] = None
        app_conf['extra_nginx_conf_string'] = \
            envtpl.render_string(extra_nginx_conf_string,
                                 extra_variables={"APP": app_conf})
        app_conf['extra_nginx_conf_static_string'] = \
            envtpl.render_string(extra_nginx_conf_static_string,
                                 extra_variables={"APP": app_conf})
        plugin_conf["apps"].append(app_conf)
    return plugin_conf


plugins = []
lua_package_paths = []
for config_file in glob.glob(MFSERV_PLUGINS_HOME + "/*/config.ini"):
    plugin_conf = get_conf(config_file)
    lua_package_paths = lua_package_paths + plugin_conf['lua_package_paths']
    plugins.append(plugin_conf)
lua_package_paths = \
    lua_package_paths + ["%s/config/?.lua" % os.environ['MFSERV_HOME'],
                         "%s/lib/?.lua" % os.environ['MFSERV_HOME'],
                         "%s/config/?.lua" % os.environ['MFCOM_HOME'],
                         "%s/lib/?.lua" % os.environ['MFCOM_HOME']]

nginx_conf_file = os.path.join(os.environ['MODULE_HOME'], 'config',
                               'nginx.conf')
with open(nginx_conf_file, "r") as f:
    extra_variables = {
        "PLUGINS": plugins,
        "LUA_PACKAGE_PATH": ";".join(lua_package_paths) + ";;"
    }
    content = envtpl.render_string(f.read(), extra_variables=extra_variables)

print(content)
