"""
Copyright 2020 The Magma Authors.

This source code is licensed under the BSD-style license found in the
LICENSE file in the root directory of this source tree.

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""

import logging
import os
from typing import Optional  # noqa: lint doesn't handle inline typehints
from typing import Any, Dict

import yaml
from configuration.exceptions import LoadConfigError

# Location of configs (both service config and mconfig)
CONFIG_DIR = './magma_configs'
CONFIG_OVERRIDE_DIR = './override_configs'


def load_override_config(service_name: str) -> Optional[Any]:
    """
    Load override service configuration from the file in the override
    directory.

    Args:
        service_name: service to pull configs for; name of config file

    Returns: json-decoded value of the service config, None if it's not found

    Raises:
        LoadConfigError:
            Unable to load config due to missing file or missing key
    """
    override_file_name = _override_file_name(service_name)
    if os.path.isfile(override_file_name):
        return _load_yaml_file(override_file_name)
    return None


def save_override_config(service_name: str, cfg: Any):
    """
    Write the configuration object to its corresponding file in the override
    directory.

    Args:
        service_name: service to write config object to; name of config file
        cfg: json-decoded value of the service config
    """
    override_file_name = _override_file_name(service_name)
    os.makedirs(CONFIG_OVERRIDE_DIR, exist_ok=True)
    with open(override_file_name, 'w', encoding='utf-8') as override_file:
        yaml.dump(cfg, override_file, default_flow_style=False)


def load_service_config(service_name: str) -> Any:
    """
    Load service configuration from file. Also check override directory,
    and, if service file present there, override the values.

    Args:
        service_name: service to pull configs for; name of config file

    Returns: json-decoded value of the service config

    Raises:
        LoadConfigError:
            Unable to load config due to missing file or missing key
    """
    print(CONFIG_DIR, service_name)
    cfg_file_name = os.path.join(CONFIG_DIR, '%s.yml' % service_name)
    cfg = _load_yaml_file(cfg_file_name)

    overrides = load_override_config(service_name)
    if overrides is not None:
        # Update the keys in the config if they are present in the override
        cfg.update(overrides)
    return cfg


cached_service_configs = {}     # type: Dict[str, Any]


def get_service_config_value(service: str, param: str, default: Any) -> Any:
    """
    Get a config value for :service:, falling back to a :default: value.

    Log error if the default config is returned.

    Args:
        service: name of service to get config for
        param: config key to fetch the value for
        default: default value to return on failure

    Returns:
        value of :param: in the config files for :service:
    """
    service_configs = cached_service_configs.get(service)
    try:
        service_configs = service_configs or load_service_config(service)
    except LoadConfigError as e:
        logging.error('Error retrieving config: %s', e)
        return default

    # Handle empty file
    if not service_configs:
        logging.error('Error retrieving config, file empty for: %s', service)
        return default

    cached_service_configs[service] = service_configs

    config_value = service_configs.get(param)
    if config_value is not None:
        return config_value
    else:
        logging.error(
            'Error retrieving config for %s, key not found: %s',
            service, param,
        )
        return default


def _override_file_name(service_name: str) -> str:
    return os.path.join(CONFIG_OVERRIDE_DIR, '%s.yml' % service_name)


def _load_yaml_file(file_name: str) -> Any:
    """
    Load the yaml file and returns the python object.

    Args:
        file_name: name of the .yml file

    Returns:
        Contents of the yml file deserialized into a Python object

    Raises:
        LoadConfigError: on error
    """

    try:
        with open(file_name, 'r', encoding='utf-8') as stream:
            data = yaml.safe_load(stream)
            return data
    except (OSError, yaml.YAMLError) as e:
        raise LoadConfigError('Error loading yml config') from e
