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

DEFAULT_CONFIG_FILE = "/opt/xos/config.yaml"
INITIALIZED = False
CONFIG = {}

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

    @staticmethod
    def init(config_file=DEFAULT_CONFIG_FILE):
        global INITIALIZED
        global CONFIG
        # the config module can be initialized only one
        if INITIALIZED:
            raise Exception('[XOS-Config] Module already initialized')
        INITIALIZED = True

        # if XOS-CONFIG is defined override the config_file
        if os.environ.get('XOS-CONFIG'):
            config_file = os.environ['XOS-CONFIG']

        # 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_file = Config.get_cli_param(sys.argv)

        CONFIG = Config.read_config(config_file)

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

    @staticmethod
    def validate_config_format(config_file):
        schema = os.path.abspath(os.path.dirname(os.path.realpath(__file__)) + '/config-schema.yaml')
        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):
        """
        Read the configuration file and return a dictionary
        :param config_file: string
        :return: dict
        """
        if not os.path.exists(config_file):
            raise Exception('[XOS-Config] Config file not found at: %s' % config_file)

        try:
            Config.validate_config_format(config_file)
        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

        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, default.DEFAULT_VALUES)
        if not val:
            raise Exception('[XOS-Config] Config does not have a value (or a default) parameter %s' % query)
        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'])

# NOTE is this needed if this package is not meant to be execute from the CLI?
if __name__ == '__main__':
    config = Config()
    config.init()