# Copyright 2017-present Open Networking Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


import os
import sys
import yaml
import default
from pykwalify.core import Core as PyKwalify
import pykwalify

pykwalify.init_logging(1)

DEFAULT_CONFIG_FILE = "/opt/xos/xos_config.yaml"
DEFAULT_CONFIG_SCHEMA = "xos-config-schema.yaml"
INITIALIZED = False
CONFIG_FILE = None
CONFIG = {}

OVERRIDE_CONFIG = {}


class Config:
    """
    XOS Configuration APIs
    """

    @staticmethod
    def init(
        config_file=DEFAULT_CONFIG_FILE,
        config_schema=DEFAULT_CONFIG_SCHEMA,
        override_config_file=None,
    ):

        # make schema relative to this directory
        # TODO give the possibility to specify an absolute path
        config_schema = Config.get_abs_path(config_schema)

        global INITIALIZED
        global CONFIG
        global CONFIG_FILE

        global OVERRIDE_CONFIG
        global OVERRIDE_CONFIG_FILE
        global OVERRIDE_CONFIG_SCHEMA

        # Use same schema for both provided and global config by default
        OVERRIDE_CONFIG_SCHEMA = config_schema
        OVERRIDE_CONFIG_FILE = override_config_file

        # the config module can be initialized only one
        if INITIALIZED:
            raise Exception("[XOS-Config] Module already initialized")
        INITIALIZED = True

        # if XOS_CONFIG_FILE is defined override the config_file
        # FIXME shouldn't this stay in whatever module call this one? and then just pass the file to the init method
        if os.environ.get("XOS_CONFIG_FILE"):
            config_file = os.environ["XOS_CONFIG_FILE"]

        # if XOS_CONFIG_SCHEMA is defined override the config_schema
        # FIXME shouldn't this stay in whatever module call this one? and then just pass the file to the init method
        if os.environ.get("XOS_CONFIG_SCHEMA"):
            config_schema = Config.get_abs_path(os.environ["XOS_CONFIG_SCHEMA"])

        # allow OVERRIDE_CONFIG_* to be overridden  by env vars
        if os.environ.get("XOS_OVERRIDE_CONFIG_FILE"):
            OVERRIDE_CONFIG_FILE = os.environ["XOS_OVERRIDE_CONFIG_FILE"]
        if os.environ.get("XOS_OVERRIDE_CONFIG_SCHEMA"):
            OVERRIDE_CONFIG_SCHEMA = Config.get_abs_path(
                os.environ["XOS_OVERRIDE_CONFIG_SCHEMA"]
            )

        # if a -C parameter is set in the cli override the config_file
        # FIXME shouldn't this stay in whatever module call this one? and then just pass the file to the init method
        if Config.get_cli_param(sys.argv):
            config_schema = Config.get_cli_param(sys.argv)

        CONFIG_FILE = config_file
        CONFIG = Config.read_config(config_file, config_schema)

        # if an override is set
        if OVERRIDE_CONFIG_FILE is not None:
            OVERRIDE_CONFIG = Config.read_config(
                OVERRIDE_CONFIG_FILE, OVERRIDE_CONFIG_SCHEMA, True
            )

    @staticmethod
    def get_config_file():
        return CONFIG_FILE

    @staticmethod
    def clear():
        global INITIALIZED
        INITIALIZED = False

    @staticmethod
    def get_abs_path(path):
        if os.path.isabs(path):
            return path
        return os.path.dirname(os.path.realpath(__file__)) + "/" + path

    @staticmethod
    def validate_config_format(config_file, config_schema):
        schema = os.path.abspath(config_schema)
        c = PyKwalify(source_file=config_file, schema_files=[schema])
        c.validate(raise_exception=True)

    @staticmethod
    def get_cli_param(args):
        last = None
        for arg in args:
            if last == "-C":
                return arg
            last = arg

    @staticmethod
    def read_config(config_file, config_schema, ignore_if_not_found=False):
        """
        Read the configuration file and return a dictionary
        :param config_file: string
        :return: dict
        """

        if not os.path.exists(config_file) and ignore_if_not_found:
            return {}

        if not os.path.exists(config_file):
            raise Exception("[XOS-Config] Config file not found at: %s" % config_file)

        if not os.path.exists(config_schema):
            raise Exception(
                "[XOS-Config] Config schema not found at: %s" % config_schema
            )

        try:
            Config.validate_config_format(config_file, config_schema)
        except Exception as e:
            try:
                error_msg = e.msg
            except AttributeError:
                error_msg = str(e)
            raise Exception("[XOS-Config] The config format is wrong: %s" % error_msg)

        with open(config_file, "r") as stream:
            return yaml.safe_load(stream)

    @staticmethod
    def get(query):
        """
        Read a parameter from the config
        :param query: a dot separated selector for configuration options (eg: database.username)
        :return: the requested parameter in any format the parameter is specified
        """
        global INITIALIZED
        global CONFIG
        global OVERRIDE_CONFIG
        global OVERRIDE_CONFIG_FILE

        if not INITIALIZED:
            raise Exception("[XOS-Config] Module has not been initialized")

        val = Config.get_param(query, CONFIG)
        if OVERRIDE_CONFIG_FILE or not val:
            # if we specified an override configuration, we should override the value
            # we also look for the value in case it's missing
            over_val = Config.get_param(query, OVERRIDE_CONFIG)
            if over_val is not None:
                val = over_val
        if not val:
            val = Config.get_param(query, default.DEFAULT_VALUES)
        if not val:
            # TODO if no val return none
            # raise Exception('[XOS-Config] Config does not have a value (or a default) parameter %s' % query)
            return None
        return val

    @staticmethod
    def get_param(query, config):
        """
        Search for a parameter in config's first level, other call get_nested_param
        :param query: a dot separated selector for configuration options (eg: database.username)
        :param config: the config source to read from (can be the config file or the defaults)
        :return: the requested parameter in any format the parameter is specified
        """
        keys = query.split(".")
        if len(keys) == 1:
            key = keys[0]
            if key not in config:
                return None
            return config[key]
        else:
            return Config.get_nested_param(keys, config)

    @staticmethod
    def get_nested_param(keys, config):
        """

        :param keys: a list of descending selector
        :param config: the config source to read from (can be the config file or the defaults)
        :return: the requested parameter in any format the parameter is specified
        """
        param = config
        for k in keys:
            if k not in param:
                return None
            param = param[k]
        return param


if __name__ == "__main__":
    Config.init()
