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

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

GLOBAL_CONFIG_FILE = DEFAULT_CONFIG_FILE
GLOBAL_CONFIG_SCHEMA = DEFAULT_CONFIG_SCHEMA
GLOBAL_CONFIG = {}

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

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

        # 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 GLOBAL_CONFIG
        global GLOBAL_CONFIG_FILE
        global GLOBAL_CONFIG_SCHEMA

        # Use same schema for both provided and global config by default
        GLOBAL_CONFIG_SCHEMA = config_schema

        # 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 GLOBAL_CONFIG_* to be overridden  by env vars
        if os.environ.get('XOS_GLOBAL_CONFIG_FILE'):
            GLOBAL_CONFIG_FILE = os.environ['XOS_GLOBAL_CONFIG_FILE']
        if os.environ.get('XOS_GLOBAL_CONFIG_SCHEMA'):
            GLOBAL_CONFIG_SCHEMA = Config.get_abs_path(os.environ['XOS_GLOBAL_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)

        # Load global schema
        GLOBAL_CONFIG = Config.read_config(GLOBAL_CONFIG_FILE, GLOBAL_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, e:
            raise Exception('[XOS-Config] The config format is wrong: %s' % e.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 GLOBAL_CONFIG

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

        val = Config.get_param(query, CONFIG)
        if not val:
            val = Config.get_param(query, GLOBAL_CONFIG)
        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 not config.has_key(key):
                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 not param.has_key(k):
                return None
            param = param[k]
        return param

    @staticmethod
    def get_service_list():
        """
        Query registrator to get the list of services
        NOTE: we assume that consul is a valid URL
        :return: a list of service names
        """
        service_dict = requests.get('http://consul:8500/v1/catalog/services').json()
        service_list = []
        for s in service_dict:
            service_list.append(s)
        return service_list

    @staticmethod
    def get_service_info(service_name):
        """
        Query registrator to get the details about a service
        NOTE: we assume that consul is a valid URL
        :param service_name: the name of the service, can be retrieved from get_service_list
        :return: the informations about a service
        """
        response = requests.get('http://consul:8500/v1/catalog/service/%s' % service_name)
        if not response.ok:
            raise Exception('[XOS-Config] Registrator is down')
        service = response.json()
        if not service or len(service) == 0:
            raise Exception('[XOS-Config] The service missing-service looking for does not exist')
        return {
            'name': service[0]['ServiceName'],
            'url': service[0]['ServiceAddress'],
            'port': service[0]['ServicePort']
        }

    @staticmethod
    def get_service_endpoint(service_name):
        """
        Query registrator to get the details about a service and return the endpoint in for of a string
        :param service_name: the name of the service, can be retrieved from get_service_list
        :return: the endpoint of the service
        """
        service = Config.get_service_info(service_name)
        return 'http://%s:%s' % (service['url'], service['port'])

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