# Copyright (C) 2020-2022 HERE Global B.V. and its affiliate(s).
# All rights reserved.
#
# This software and other materials contain proprietary information
# controlled by HERE and are protected by applicable copyright legislation.
# Any use and utilization of this software and other materials and
# disclosure to any third parties is conditional upon having a separate
# agreement with HERE for the access, use, utilization or disclosure of this
# software. In the absence of such agreement, the use of the software is not
# allowed.

"""
This module provides a ``PlatformConfig`` class to be used for platform configuration management.

A config object can be created from a ``platform_config.conf`` file in the package.
"""

import os
from os.path import expanduser, expandvars
from pathlib import Path
from typing import Optional

from here.platform.environment import Environment
from here.platform.exceptions import ConfigException
from here.platform.utils.properties_helper import PropertiesDict


class PlatformConfig:
    """
    PlatformConfig provides functions for dealing with the HERE platform
    Config.

    Config can be read from the packaged platform_config.conf file based on platform environment
    """

    def __init__(
        self,
        api: str,
        portal_url: Optional[str] = None,
        status_url: Optional[str] = None,
        platform_status_url: Optional[str] = None,
        account_url: Optional[str] = None,
    ):
        """
        Instantiate the PlatformConfig object.

        :param api: Platform API.
        :param portal_url: (Optional) Platform portal URL.
        :param status_url: (Optional) Status URL.
        :param platform_status_url: (Optional) Platform status api URL.
        :param account_url: (Optional) Account URL.
        """
        self.api = api
        self.portal_url = portal_url
        self.status_url = status_url
        self.platform_status_url = platform_status_url
        self.account_url = account_url

    @classmethod
    def from_environment(cls, environment: Environment) -> "PlatformConfig":
        """
        Return the config object from a specified config file path.

        :param environment: an instance of Environment enum.
        :return: config
        """

        this_dir = Path(__file__).parent
        path = this_dir / environment.name.lower() / "platform_config.conf"
        return cls._from_config_file(os.fspath(path))

    @classmethod
    def _from_config_file(cls, path: str) -> "PlatformConfig":
        """
        Return the config object from a specified config file path.

        :param path: path to a HERE platform platform_config.conf file.
        :return: config
        :raises ConfigException: Erroneous platform_config.conf file in path
        """
        config_path = expanduser(expandvars(path))

        try:
            config_properties = PropertiesDict.parse(config_path)
            return PlatformConfig(
                # this will raise ConfigException if key is not present
                api=config_properties["here_platform_api"],
                # following params are optional
                portal_url=config_properties.get("here_platform_portal_url", None),
                status_url=config_properties.get("here_status_url", None),
                platform_status_url=config_properties.get("platform_status_api_url", None),
                account_url=config_properties.get("here_account_api_url", None),
            )
        except Exception as e:
            raise ConfigException(f"Erroneous {config_path} file: {e}")
