# 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 contains a :class:`ServiceRegistryApi` class to perform service registry API operations.

The HERE Location Service Registry API reference documentation used in this module can be found here:
|service_registry_api_reference|

.. |service_registry_api_reference| raw:: html

   <a href="https://developer.here.com/documentation/service-registry/dev_guide/index.html" target="_blank">HERE Location Service Registry API Reference</a>  # noqa E501
"""

from typing import List, Optional

from here.platform.api.base_api import BaseApi
from here.platform.auth import Auth
from here.platform.config import ApplicationConfig, PlatformConfig
from here.platform.exceptions import AuthenticationException, PlatformException


class ServiceRegistryApi(BaseApi):
    """
    This class provides access to HERE Platform Service Registry APIs.

    The registry service provides basic service management operations.
    It manages all platform service resources needed for different kinds
    of services and operations on them.
    """

    def __init__(
        self,
        base_url: str,
        platform_config: PlatformConfig,
        application_config: ApplicationConfig,
        auth: Optional[Auth],
        proxies: Optional[dict],
    ):
        """
        Instantiate ServiceRegistryApi object.

        :param base_url: base url
        :param platform_config: a mandatory :class:`PlatformConfig` object to provide
        configuration information for the API.
        :param application_config: a mandatory :class:`ApplicationConfig` object to provide
        configuration information for the API.
        :param auth: an Authentication instance.
        :param proxies: an optional proxy configuration. Defaults to the environment proxy
        configuration.
        """
        super(ServiceRegistryApi, self).__init__(
            platform_config=platform_config,
            application_config=application_config,
            auth=auth,
            proxies=proxies,
        )
        self.base_url = base_url

    def get_services(self) -> List[dict]:
        """
        List all services.

        :return: a list of dictionaries with details of all services
        :raises PlatformException: If platform responds with an HTTP error.
        """
        path = "/services"
        url = self.format_url(self.base_url, path)
        resp = self.get(url)
        if resp.status_code == 200:
            resp_json: List[dict] = resp.json()
            # strip trailing slash from all base urls
            for i in range(len(resp_json)):
                if "baseUrl" in resp_json[i]:
                    resp_json[i]["baseUrl"] = resp_json[i]["baseUrl"].rstrip("/")
            return resp_json
        else:
            raise PlatformException(resp)

    def get_service(self, service_hrn: str) -> dict:
        """
        Fetches a service having specified HRN if it exists.

        :param service_hrn: a HERE Resource Name
        :return: a dictionary with details of service with specified HRN
        :raises AuthenticationException: If the service cannot be accessed.
        :raises PlatformException: If platform responds with an HTTP error.
        """
        path = f"/services/{service_hrn}"
        url = self.format_url(self.base_url, path)
        resp = self.get(url)
        if resp.status_code == 200:
            resp_json: dict = resp.json()
            # strip trailing slash from base url
            if "baseUrl" in resp_json:
                resp_json["baseUrl"] = resp_json["baseUrl"].rstrip("/")
            return resp_json
        elif resp.status_code == 404:
            # 404 error can occur either if the service doesn't exist or isn't authorized. Given
            # the ambiguity, chose to treat as an authentication error.
            raise AuthenticationException(resp)
        else:
            raise PlatformException(resp)
