# Lint as: python2, python3
"""A singleton class for accessing global config values

provides access to global configuration file
"""

# The config values can be stored in 3 config files:
#     global_config.ini
#     moblab_config.ini
#     shadow_config.ini
# When the code is running in Moblab, config values in moblab config override
# values in global config, and config values in shadow config override values
# in both moblab and global config.
# When the code is running in a non-Moblab host, moblab_config.ini is ignored.
# Config values in shadow config will override values in global config.

import collections
import os
import re
import six.moves.configparser as ConfigParser
import sys

from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import lsbrelease_utils
from autotest_lib.client.common_lib import seven


class ConfigError(error.AutotestError):
    """Configuration error."""
    pass


class ConfigValueError(ConfigError):
    """Configuration value error, raised when value failed to be converted to
    expected type."""
    pass



common_lib_dir = os.path.dirname(sys.modules[__name__].__file__)
client_dir = os.path.dirname(common_lib_dir)
root_dir = os.path.dirname(client_dir)

# Check if the config files are at autotest's root dir
# This will happen if client is executing inside a full autotest tree, or if
# other entry points are being executed
global_config_path_root = os.path.join(root_dir, 'global_config.ini')
moblab_config_path_root = os.path.join(root_dir, 'moblab_config.ini')
shadow_config_path_root = os.path.join(root_dir, 'shadow_config.ini')
config_in_root = os.path.exists(global_config_path_root)

# Check if the config files are at autotest's client dir
# This will happen if a client stand alone execution is happening
global_config_path_client = os.path.join(client_dir, 'global_config.ini')
config_in_client = os.path.exists(global_config_path_client)

if config_in_root:
    DEFAULT_CONFIG_FILE = global_config_path_root
    if os.path.exists(moblab_config_path_root):
        DEFAULT_MOBLAB_FILE = moblab_config_path_root
    else:
        DEFAULT_MOBLAB_FILE = None
    if os.path.exists(shadow_config_path_root):
        DEFAULT_SHADOW_FILE = shadow_config_path_root
    else:
        DEFAULT_SHADOW_FILE = None
    RUNNING_STAND_ALONE_CLIENT = False
elif config_in_client:
    DEFAULT_CONFIG_FILE = global_config_path_client
    DEFAULT_MOBLAB_FILE = None
    DEFAULT_SHADOW_FILE = None
    RUNNING_STAND_ALONE_CLIENT = True
else:
    DEFAULT_CONFIG_FILE = None
    DEFAULT_MOBLAB_FILE = None
    DEFAULT_SHADOW_FILE = None
    RUNNING_STAND_ALONE_CLIENT = True


class global_config_class(object):
    """Object to access config values."""
    _NO_DEFAULT_SPECIFIED = object()

    _config = None
    config_file = DEFAULT_CONFIG_FILE
    moblab_file=DEFAULT_MOBLAB_FILE
    shadow_file = DEFAULT_SHADOW_FILE
    running_stand_alone_client = RUNNING_STAND_ALONE_CLIENT


    @property
    def config(self):
        """ConfigParser instance.

        If the instance dict doesn't have a config key, this descriptor
        will be called to ensure the config file is parsed (setting the
        config key in the instance dict as a side effect).  Once the
        instance dict has a config key, that value will be used in
        preference.
        """
        if self._config is None:
            self.parse_config_file()
        return self._config


    @config.setter
    def config(self, value):
        """Set config attribute.

        @param value: value to set
        """
        self._config = value


    def check_stand_alone_client_run(self):
        """Check if this is a stand alone client that does not need config."""
        return self.running_stand_alone_client


    def set_config_files(self, config_file=DEFAULT_CONFIG_FILE,
                         shadow_file=DEFAULT_SHADOW_FILE,
                         moblab_file=DEFAULT_MOBLAB_FILE):
        self.config_file = config_file
        self.moblab_file = moblab_file
        self.shadow_file = shadow_file
        self._config = None


    def _handle_no_value(self, section, key, default):
        if default is self._NO_DEFAULT_SPECIFIED:
            msg = ("Value '%s' not found in section '%s'" %
                   (key, section))
            raise ConfigError(msg)
        else:
            return default


    def get_section_as_dict(self, section):
        """Return a dict mapping section options to values.

        This is useful if a config section is being used like a
        dictionary.  If the section is missing, return an empty dict.

        This returns an OrderedDict, preserving the order of the options
        in the section.

        @param section: Section to get.
        @return: OrderedDict
        """
        if self.config.has_section(section):
            return collections.OrderedDict(self.config.items(section))
        else:
            return collections.OrderedDict()


    def get_section_values(self, section):
        """
        Return a config parser object containing a single section of the
        global configuration, that can be later written to a file object.

        @param section: Section we want to turn into a config parser object.
        @return: ConfigParser() object containing all the contents of section.
        """
        cfgparser = seven.config_parser()
        cfgparser.add_section(section)
        for option, value in self.config.items(section):
            cfgparser.set(section, option, value)
        return cfgparser


    def get_config_value(self, section, key, type=str,
                         default=_NO_DEFAULT_SPECIFIED, allow_blank=False):
        """Get a configuration value

        @param section: Section the key is in.
        @param key: The key to look up.
        @param type: The expected type of the returned value.
        @param default: A value to return in case the key couldn't be found.
        @param allow_blank: If False, an empty string as a value is treated like
                            there was no value at all. If True, empty strings
                            will be returned like they were normal values.

        @raises ConfigError: If the key could not be found and no default was
                             specified.

        @return: The obtained value or default.
        """
        try:
            val = self.config.get(section, key)
        except ConfigParser.Error:
            return self._handle_no_value(section, key, default)

        if not val.strip() and not allow_blank:
            return self._handle_no_value(section, key, default)

        return self._convert_value(key, section, val, type)


    def get_config_value_regex(self, section, key_regex, type=str):
        """Get a dict of configs in given section with key matched to key-regex.

        @param section: Section the key is in.
        @param key_regex: The regex that key should match.
        @param type: data type the value should have.

        @return: A dictionary of key:value with key matching `key_regex`. Return
                 an empty dictionary if no matching key is found.
        """
        configs = {}
        for option, value in self.config.items(section):
            if re.match(key_regex, option):
                configs[option] = self._convert_value(option, section, value,
                                                      type)
        return configs


    # This order of parameters ensures this can be called similar to the normal
    # get_config_value which is mostly called with (section, key, type).
    def get_config_value_with_fallback(self, section, key, fallback_key,
                                       type=str, fallback_section=None,
                                       default=_NO_DEFAULT_SPECIFIED, **kwargs):
        """Get a configuration value if it exists, otherwise use fallback.

        Tries to obtain a configuration value for a given key. If this value
        does not exist, the value looked up under a different key will be
        returned.

        @param section: Section the key is in.
        @param key: The key to look up.
        @param fallback_key: The key to use in case the original key wasn't
                             found.
        @param type: data type the value should have.
        @param fallback_section: The section the fallback key resides in. In
                                 case none is specified, the the same section as
                                 for the primary key is used.
        @param default: Value to return if values could neither be obtained for
                        the key nor the fallback key.
        @param **kwargs: Additional arguments that should be passed to
                         get_config_value.

        @raises ConfigError: If the fallback key doesn't exist and no default
                             was provided.

        @return: The value that was looked up for the key. If that didn't
                 exist, the value looked up for the fallback key will be
                 returned. If that also didn't exist, default will be returned.
        """
        if fallback_section is None:
            fallback_section = section

        try:
            return self.get_config_value(section, key, type, **kwargs)
        except ConfigError:
            return self.get_config_value(fallback_section, fallback_key,
                                         type, default=default, **kwargs)


    def override_config_value(self, section, key, new_value):
        """Override a value from the config file with a new value.

        @param section: Name of the section.
        @param key: Name of the key.
        @param new_value: new value.
        """
        self.config.set(section, key, new_value)


    def reset_config_values(self):
        """
        Reset all values to those found in the config files (undoes all
        overrides).
        """
        self.parse_config_file()


    def merge_configs(self, override_config):
        """Merge existing config values with the ones in given override_config.

        @param override_config: Configs to override existing config values.
        """
        # overwrite whats in config with whats in override_config
        sections = override_config.sections()
        for section in sections:
            # add the section if need be
            if not self.config.has_section(section):
                self.config.add_section(section)
            # now run through all options and set them
            options = override_config.options(section)
            for option in options:
                val = override_config.get(section, option)
                self.config.set(section, option, val)


    def parse_config_file(self):
        """Parse config files."""
        self.config = seven.config_parser()
        if self.config_file and os.path.exists(self.config_file):
            self.config.read(self.config_file)
        else:
            raise ConfigError('%s not found' % (self.config_file))

        # If it's running in Moblab, read moblab config file if exists,
        # overwrite the value in global config.
        if (lsbrelease_utils.is_moblab() and self.moblab_file and
            os.path.exists(self.moblab_file)):
            moblab_config = seven.config_parser()
            moblab_config.read(self.moblab_file)
            # now we merge moblab into global
            self.merge_configs(moblab_config)

        # now also read the shadow file if there is one
        # this will overwrite anything that is found in the
        # other config
        if self.shadow_file and os.path.exists(self.shadow_file):
            shadow_config = seven.config_parser()
            shadow_config.read(self.shadow_file)
            # now we merge shadow into global
            self.merge_configs(shadow_config)


    # the values that are pulled from ini
    # are strings.  But we should attempt to
    # convert them to other types if needed.
    def _convert_value(self, key, section, value, value_type):
        # strip off leading and trailing white space
        sval = value.strip()

        # if length of string is zero then return None
        if len(sval) == 0:
            if value_type == str:
                return ""
            elif value_type == bool:
                return False
            elif value_type == int:
                return 0
            elif value_type == float:
                return 0.0
            elif value_type == list:
                return []
            else:
                return None

        if value_type == bool:
            if sval.lower() == "false":
                return False
            else:
                return True

        if value_type == list:
            # Split the string using ',' and return a list
            return [val.strip() for val in sval.split(',')]

        try:
            conv_val = value_type(sval)
            return conv_val
        except:
            msg = ("Could not convert %s value %r in section %s to type %s" %
                    (key, sval, section, value_type))
            raise ConfigValueError(msg)


    def get_sections(self):
        """Return a list of sections available."""
        return self.config.sections()


# insure the class is a singleton.  Now the symbol global_config
# will point to the one and only one instace of the class
global_config = global_config_class()


class FakeGlobalConfig(object):
    """Fake replacement for global_config singleton object.

    Unittest will want to fake the global_config so that developers'
    shadow_config doesn't leak into unittests. Provide a fake object for that
    purpose.

    """
    # pylint: disable=missing-docstring

    def __init__(self):
        self._config_info = {}


    def set_config_value(self, section, key, value):
        self._config_info[(section, key)] = value


    def get_config_value(self, section, key, type=str,
                         default=None, allow_blank=False):
        identifier = (section, key)
        if identifier not in self._config_info:
            return default
        return self._config_info[identifier]


    def parse_config_file(self):
        pass
