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

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

from here.content.content import Content, ContentBinding
from here.content.hmc2 import AdminIndex
from here.content.hmc2.adas_attributes import AdasAttributes
from here.content.hmc2.address_attributes import AddressAttributes
from here.content.hmc2.admin_locations import AdminLocations
from here.content.hmc2.admin_place_profiles import AdminPlaceProfiles
from here.content.hmc2.admin_places import AdminPlaces
from here.content.hmc2.advanced_navigation_attributes import AdvancedNavigationAttributes
from here.content.hmc2.bicycle_attributes import BicycleAttributes
from here.content.hmc2.composite_road_attributes import CompositeRoadAttribute
from here.content.hmc2.environmental_zone_conditions import EnvironmentalZoneConditions
from here.content.hmc2.environmental_zones import EnvironmentalZones
from here.content.hmc2.extended_speed_limit import ExtendedSpeedLimit
from here.content.hmc2.here_places import HerePlaces
from here.content.hmc2.metadata import Metadata
from here.content.hmc2.navigation_attributes import NavigationAttributes
from here.content.hmc2.road_attributes import RoadAttributes
from here.content.hmc2.segment_admin_boundary import SegmentAdminBoundary
from here.content.hmc2.segment_street_names import SegmentToStreetName
from here.content.hmc2.sign_text import SignText
from here.content.hmc2.street_names import StreetNames
from here.content.hmc2.topology_geometry import TopologyGeometry
from here.content.hmc2.traffic_patterns import TrafficPatterns
from here.content.hmc2.truck_attributes import TruckAttributes
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.

    Use an instance of this class to access a catalog in the HMC format.
    Alternatively, instantiate manually the bindings for selected layers
    to bind to other catalogs that adheres to a subset of the HMC format and layers.
    """

    default_hrns = {
        Environment.DEFAULT: "hrn:here:data::olp-here:rib-2",
    }

    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.
            When ``None``, a default catalog is selected given the environment
            of the platform passed above. If no default can be set, an exception is raised
        :param version: which version of the 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 a default catalog HRN is not defined for the environment
        """

        catalog_hrn = catalog_hrn or HMC.default_hrns.get(platform.environment)
        if not catalog_hrn:
            raise ValueError(
                "The environment does not have a default HRN for HMC, "
                "a catalog HRN should be specified explicitly"
            )

        content = Content(platform, catalog_hrn, version)

        super().__init__(content, adapter)

        # Feature bindings
        self.topology_geometry = TopologyGeometry(content, "topology-geometry", adapter)
        self.environmental_zones = EnvironmentalZones(content, "environmental-zones", adapter)

        # Attribute bindings
        self.road_attributes = RoadAttributes(content, "road-attributes", adapter)
        self.navigation_attributes = NavigationAttributes(
            content, "navigation-attributes", adapter
        )
        self.advanced_navigation_attributes = AdvancedNavigationAttributes(
            content, "advanced-navigation-attributes", adapter
        )
        self.bicycle_attributes = BicycleAttributes(content, "bicycle-attributes", adapter)
        self.recreational_vehicle_attributes = AdvancedNavigationAttributes(
            content, "recreational-vehicle-attributes", adapter
        )
        self.truck_attributes = TruckAttributes(content, "truck-attributes", adapter)

        # Metadata
        self.places_metadata = Metadata(content, "places-metadata", adapter)
        self.cartography_metadata = Metadata(content, "cartography-metadata", adapter)
        self.building_metadata = Metadata(content, "building-metadata", adapter)

        # Administrative
        self.admin_places = AdminPlaces(content, "administrative-places", adapter)
        self.admin_place_profiles = AdminPlaceProfiles(
            content, "administrative-place-profiles", adapter
        )
        self.admin_index = AdminIndex(content, "indexed-locations", adapter)

        # SignBindings
        self.sign_text = SignText(content, "sign-text", adapter)
        self.admin_locations = AdminLocations(content, "administrative-locations", adapter)
        self.street_names = StreetNames(content, "street-names", adapter)
        self.address_attributes = AddressAttributes(content, "address-attributes", adapter)

        # Traffic Bindings
        self.traffic_patterns = TrafficPatterns(content, "traffic-patterns", adapter)

        # Multilayer Environment Bindings
        self.environmental_zone_conditions = EnvironmentalZoneConditions(
            content, "navigation-attributes", adapter
        )

        # Multilayer Bindings
        self.segment_street_names = SegmentToStreetName(content, "address-attributes", adapter)
        self.extended_speed_limit = ExtendedSpeedLimit(content, "navigation-attributes", adapter)
        self.segment_admin_boundary = SegmentAdminBoundary(content, "address-attributes", adapter)

        # Here Places
        self.here_places = HerePlaces(content, "places", adapter)
        self.adas_attributes = AdasAttributes(content, "adas-attributes", adapter)
        self.composite_road_attributes = CompositeRoadAttribute(
            content, "complex-road-attributes", adapter
        )
