# Copyright (C) 2020-2021 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.

"""
Provide access to HERE Map Content catalogs.
"""
from typing import Optional

from here.content.content import Content, ContentBinding
from here.content.hmc.adasattributes import AdasAttributes
from here.content.hmc.addressattributes import AddressAttributes
from here.content.hmc.administrativelocations import AdministrativeLocationsAttributes
from here.content.hmc.administrativeplaces import AdministrativePlaces
from here.content.hmc.advancednavigationattributes import AdvancedNavigationAttributes
from here.content.hmc.environmentalzones import EnvironmentalZonesAttributes
from here.content.hmc.multilayeradminboundary import SegmentToAdminBoundary
from here.content.hmc.multilayerenvironmentalzones import SegmentToEnvironmentalZone
from here.content.hmc.multilayerspeedlimit import SegmentToSpeedLimit
from here.content.hmc.multilayerstreetname import SegmentToStreetName
from here.content.hmc.navigationattributes import NavigationAttributes
from here.content.hmc.roadattributes import RoadAttributes
from here.content.hmc.streetnames import StreetNames
from here.content.hmc.topologygeometry import TopologyGeometry
from here.content.hmc.trafficpatterns import TrafficPatterns
from here.platform import Environment, Platform
from here.platform.adapter import Adapter


class HMC(ContentBinding):
    """
    Entry point to provide access to HERE Map Content catalogs.
    """

    def __init__(
        self,
        platform: Platform,
        catalog_hrn: Optional[str] = None,
        version: Optional[int] = None,
        adapter: Optional[Adapter] = None,
    ):
        """
        Initialize HMC, selecting which version to use.

        :param platform: access to the HERE platform
        :param catalog_hrn: a catalog name with HMC schema.
            Default is None in which case,
            the following values are assigned depending on environment:
            Environment.DEFAULT: "hrn:here:data::olp-here:rib-2"
            Environment.INTERNAL: "hrn:here:data::olp-here:rib-2"
            Environment.CHINA: "hrn:here-cn:data::olp-cn-here:here-map-content-china-2"
            Environment.LOCAL: raise ValueError
        :param version: which version of HMC to read, latest if not specified
        :param adapter: the ``Adapter`` to transform data between different representations,
          ``None`` to use the adapter defined in ``platform``.
        :raises ValueError: If the finally/automatically assigned catalog_hrn is None
        """

        # In the case that catalog_hrn is None,
        # if Environment is LOCAL, raise ValueError.
        # Otherwise, catalog_hrn is automatically assigned with default catalog name as below.
        if catalog_hrn is None:
            if (
                platform.environment == Environment.DEFAULT
                or platform.environment == Environment.INTERNAL
            ):
                catalog_hrn = "hrn:here:data::olp-here:rib-2"
            elif platform.environment == Environment.CHINA:
                catalog_hrn = "hrn:here-cn:data::olp-cn-here:here-map-content-china-2"
            else:
                raise ValueError("catalog_hrn should be specified for your environment!")

        content = Content(platform, catalog_hrn, version)

        super().__init__(content, adapter)

        # Feature layers we expose
        self.admin_places = AdministrativePlaces(content, "administrative-places", adapter)
        self.street_names = StreetNames(content, "street-names", adapter)
        self.topology_geometry = TopologyGeometry(content, "topology-geometry", adapter)

        # Attributes layers we expose
        self.adas_attributes = AdasAttributes(content, "adas-attributes", adapter)
        self.address_attributes = AddressAttributes(content, "address-attributes", adapter)
        self.admin_locations = AdministrativeLocationsAttributes(
            content, "administrative-locations", adapter
        )
        self.advanced_navigation_attributes = AdvancedNavigationAttributes(
            content, "advanced-navigation-attributes", adapter
        )
        self.navigation_attributes = NavigationAttributes(
            content, "navigation-attributes", adapter
        )
        self.road_attributes = RoadAttributes(content, "road-attributes", adapter)
        self.environmental_zones = EnvironmentalZonesAttributes(
            content, "environmental-zones", adapter
        )
        self.traffic_patterns = TrafficPatterns(content, "traffic-patterns", adapter)

        # Multi-layer attributes
        self.multilayer_speedlimit = SegmentToSpeedLimit(
            content, "navigation-attributes", "advanced-navigation-attributes", adapter
        )
        self.multilayer_streetname = SegmentToStreetName(
            content, "address-attributes", "street-names", adapter
        )
        self.multilayer_adminboundary = SegmentToAdminBoundary(
            content,
            "address-attributes",
            "administrative-places",
            "administrative-locations",
            adapter,
        )
        self.multilayer_envzone = SegmentToEnvironmentalZone(
            content, "navigation-attributes", "environmental-zones", adapter
        )
