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 = {}

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
        # 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'])

        # 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)

    @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):
        """
        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)

        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

        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:
            # 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()