# 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.

"""
Bindings for the HMC Administrative Place Profiles.
"""
from dataclasses import dataclass
from typing import Any, List, Mapping, Optional

from google.protobuf.message import Message
from here.content.base import ContentIndexer, ContentPartition, SingleLayerBinding
from here.content.content import hmc_schema_version
from here.content.utils.proto import has_field, parse_ref
from here.platform.adapter import Partition, Ref


@dataclass
class AdminPlaceProfileAttributes:
    """Administrative Place Profiles Attributes."""

    partition_id: Partition
    administrative_place_ref: Ref
    move_over: Optional[int] = None
    make_way: Optional[bool] = None
    overtake_pass: Optional[bool] = None
    merging: Optional[int] = None
    right_of_way: Optional[int] = None
    keep_right: Optional[bool] = None
    solid_lane_travers_general: Optional[bool] = None
    solid_lane_exception: Optional[int] = None
    color_temp_marking: Optional[int] = None
    dashed_width_lar: Optional[float] = None
    dashed_width_non_lar: Optional[float] = None
    spaces_marking_lar: Optional[float] = None
    spaces_marking_non_lar: Optional[float] = None
    solid_edge_width_lar: Optional[float] = None
    solid_edge_width_non_lar: Optional[float] = None
    average_lane_width_mtrw: Optional[float] = None
    average_lane_width_non_mtrw: Optional[float] = None

    indexer = ContentIndexer(partition="partition_id", refs={"place": "administrative_place_ref"})


class AdminPlaceProfiles(SingleLayerBinding):
    """
    Bindings for the HMC Administrative Place Profiles.
    """

    @classmethod
    def schema_hrn(cls) -> List[str]:
        """
        :return: the HRN of schema this binding can parse and index
        """
        return [
            f"""hrn:here:schema:::com.here.schema.rib:administrative-place-profiles_v2:
            {hmc_schema_version}"""
        ]

    @classmethod
    def object_types(cls) -> Mapping[str, type]:
        """
        :return: the types of attributes supported by this binding
        """
        return {"admin_place_profile_attributes": AdminPlaceProfileAttributes}

    @classmethod
    def parse_and_index(cls, partition_id: str, msg: Message) -> ContentPartition:
        """
        Parse and index decoded message.

        :param partition_id: identifier of the partition
        :param msg: decoded content from the layer, in the form of a Protobuf message
        :return: the content of a partition parsed and indexed in its own data structure
        """
        assert hasattr(msg, "profile_attribute")

        def get_optional(obj: Message, field: str) -> Any:
            return obj.__getattribute__(field).value if has_field(obj, field) else None

        profile_attributes = [
            AdminPlaceProfileAttributes(
                partition_id=Partition(partition_id),
                administrative_place_ref=parse_ref(p.administrative_place_ref),
                move_over=get_optional(p, "move_over"),
                make_way=get_optional(p, "make_way"),
                overtake_pass=get_optional(p, "overtake_pass"),
                merging=get_optional(p, "merging"),
                right_of_way=get_optional(p, "right_of_way"),
                keep_right=get_optional(p, "keep_right"),
                solid_lane_travers_general=get_optional(p, "solid_lane_travers_general"),
                solid_lane_exception=get_optional(p, "solid_lane_exception"),
                color_temp_marking=get_optional(p, "color_temp_marking"),
                dashed_width_lar=get_optional(p, "dashed_width_lar"),
                dashed_width_non_lar=get_optional(p, "dashed_width_non_lar"),
                spaces_marking_lar=get_optional(p, "spaces_marking_lar"),
                spaces_marking_non_lar=get_optional(p, "spaces_marking_non_lar"),
                solid_edge_width_lar=get_optional(p, "solid_edge_width_lar"),
                solid_edge_width_non_lar=get_optional(p, "solid_edge_width_non_lar"),
                average_lane_width_mtrw=get_optional(p, "average_lane_width_mtrw"),
                average_lane_width_non_mtrw=get_optional(p, "average_lane_width_non_mtrw"),
            )
            for p in msg.profile_attribute  # type: ignore
        ]

        return ContentPartition(cls, admin_place_profile_attributes=profile_attributes)
