# 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
import six.moves.configparser as ConfigParser
import sys

from six.moves import StringIO

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 _load_config_file(self, config_file):
        """
        Load the config_file into a StringIO buffer parsable by the current py
        version.

        TODO b:179407161, when running only in Python 3, force config files
        to be correct, and remove this special parsing.

        When in Python 3, this will change instances of %, not followed
        immediately by (, to %%. Thus:
            "%foo" --> "%%foo"
            "%(foo" --> "%(foo"
            "%%foo" --> "%%foo"
        In Python 2, we will do the opposite, and change instances of %%, to %.
            "%%foo" --> "%foo"
            "%%(foo" --> "%(foo"
            "%foo" --> "%foo"
        """
        with open(config_file) as cf:
            config_file_str = cf.read()
        if six.PY3:
            config_file_str = re.sub(r"([^%]|^)%([^%(]|$)", r"\1%%\2",
                                     config_file_str)
        else:
            config_file_str = config_file_str.replace('%%', '%')
        return StringIO(config_file_str)

    def _read_config(self, config, buf):
        """Read the provided io buffer, into the specified config."""
        if six.PY3:
            config.read_file(buf)
        else:
            config.readfp(buf)

    def parse_config_file(self):
        """Parse config files."""
        self.config = seven.config_parser()
        if self.config_file and os.path.exists(self.config_file):
            buf = self._load_config_file(self.config_file)
            self._read_config(self.config, buf)
        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()
            mob_buf = self._load_config_file(self.moblab_file)
            self._read_config(moblab_config, mob_buf)
            # 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_buf = self._load_config_file(self.shadow_file)
            self._read_config(shadow_config, shadow_buf)
            # 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
