#!python
# -----------------------------------------------------------------------------
# HSS - Hermes Skill Server
# Copyright (c) 2020 - Patrick Fial
# -----------------------------------------------------------------------------
# hss-server
# -----------------------------------------------------------------------------
# -----------------------------------------------------------------------------
# Imports
# -----------------------------------------------------------------------------

import logging
import sys
import os
import signal
import configparser
import pkg_resources

from appdirs import user_config_dir

from hss_server import logger
from hss_server import skillserver

# ------------------------------------------------------------------------------
# globals
# ------------------------------------------------------------------------------

try:
    __version__ = pkg_resources.require("hss_server")[0].version
except Exception as e:
    __version__ = "0.0.0"

server = None
skill_directory = None
config_dir = None

# ------------------------------------------------------------------------------
# parseArgs
# ------------------------------------------------------------------------------


def parseArgs():
    def _getArg(a):
        try:
            res = a.split('=', 2)

            if len(res) == 1:
                return res[0].replace('--', ''), None

            return res[0].replace('--', ''), res[1]
        except Exception as e:
            print("Failed to parse command line arguments ({})".format(e))
            return None

    return {kv[0]: kv[1] for kv in list(map(_getArg, sys.argv)) if kv != None}

# ------------------------------------------------------------------------------
# help
# ------------------------------------------------------------------------------


def help():
    version()

    print("\nUsage:")
    print("   $ ./hss_server [OPTIONS]")
    print("\nOptions:")
    print("\n   --host=[HOST]           MQTT host to connect to (default: localhost)")
    print("   --port=[PORT]           MQTT port (default: 1883)")
    print("   --topic=[TOPIC]         MQTT topic to listen on (default: hermes/intent/#)")
    print("   --tts-topic=[TOPIC]     MQTT topic to publish TTS to (default: hermes/tts/say)")
    print("   --tts-url=[URL]         URL to post TTS to. If set, TTS is not sent via MQTT (default: None)")
    print("   --start-port=[PORT]     Starting port for RCP communication (default: 51000)")
    print("\n   --config-dir=[DIR]      Location where the server's config.ini is located (default: user config dir)")
    print("   --log-file=[FILE]       Log file to write log entries to (default: console)")
    print("   --debug                 Enable debug log output")
    print("\n   --help                  Show this help and exit")
    print("   --version               Show version and exit")
    print("\n")

# ------------------------------------------------------------------------------
# version
# ------------------------------------------------------------------------------


def version(log=None):
    if log:
        log.info("Hermes Skill Server v{}".format(__version__))
    else:
        print("Hermes Skill Server v{}".format(__version__))

# ------------------------------------------------------------------------------
# run
# ------------------------------------------------------------------------------


def run():
    global server

    if 'log-file' not in args:
        logger.Logger.static_init(
            None, logging.DEBUG if "debug" in args else logging.INFO)
    else:
        log_file = args["log-file"] if "log-file" in args else "hss.log"

        logger.Logger.static_init(
            log_file, logging.DEBUG if "debug" in args else logging.INFO)

    log = logging.getLogger("hss")

    version(log)

    log.info("Using config dir '{}'".format(config_dir))
    log.info("Loading skills from '{}'".format(skill_directory))

    # attach default arguments

    if not "host" in args:
        args["host"] = "10.0.50.5"

    if not "port" in args:
        args["port"] = 1883

    if not "topic" in args:
        args["topic"] = "hermes/intent/#"

    if not "tts-topic" in args:
        args["tts-topic"] = "hermes/tts/say"

    if not "start-port" in args:
        args["start-port"] = 51000

    # start skill server (blocks)

    server = skillserver.SkillServer(args, skill_directory)
    server.start()

    # goodbye

    log.info("Bye.")


# ------------------------------------------------------------------------------
# signal_handler
# ------------------------------------------------------------------------------


def signal_handler(sig, frame):
    server.stop()

# ------------------------------------------------------------------------------
# init_config
# ------------------------------------------------------------------------------


def init_config():
    global skill_directory
    global config_dir

    config = configparser.ConfigParser()
    config_dir = args["config-dir"] if "config-dir" in args else user_config_dir("hss_server", "s710")
    config_ini = os.path.join(config_dir, "config.ini")
    skill_directory = os.path.join(config_dir, "skills")

    # bail out of anything is weird

    if not config_dir:
        raise Exception("Unable to get configuration dir. Use --config-dir option.")

    # create config dir if it does not yet exist (~/.config/hss_server)

    if not os.path.exists(config_dir):
        os.makedirs(config_dir, exist_ok=True)
        os.makedirs(skill_directory, exist_ok=True)

    # if ~/.config/hss_server/config.ini exists, load it

    if os.path.exists(config_ini) and os.path.isfile(config_ini):
        config.read(config_ini)

    # if config does not exist yet or if it does not contain the skill-directory,
    # use the default & save it back to the config file

    if not "server" in config or not "skill_directory" in config["server"]:
        if not "server" in config:
            config.add_section("server")

        config["server"]["skill_directory"] = skill_directory

        with open(config_ini, 'w') as file:
            config.write(file)

    # when ending up here, ~/.config/hss_server/config.ini exists and
    # contains the skill-directory

    skill_directory = config["server"]["skill_directory"]

# ------------------------------------------------------------------------------
# main
# ------------------------------------------------------------------------------


if __name__ == "__main__":
    signal.signal(signal.SIGINT, signal_handler)
    signal.signal(signal.SIGTERM, signal_handler)

    args = parseArgs()

    init_config()

    if args is None or "help" in args:
        help()
    elif args and "version" in args:
        version()
    else:
        run()
