# 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 Address Attributes
"""
from dataclasses import dataclass
from typing import List, Mapping

from google.protobuf.message import Message
from here.content.base import ContentPartition
from here.content.content import hmc_schema_version
from here.content.hmc2.base_attributes import Attribute, BaseAttributesBinding
from here.content.utils.proto import decode_message
from here.platform.adapter import DecodedMessage, Identifier


@dataclass
class PostalCode:
    """
    Postal Code Details.
    """

    identifier: Identifier
    postal_code: str
    type: int
    display: DecodedMessage


class AddressAttributes(BaseAttributesBinding):
    """
    Bindings for the HMC Address Attributes.
    """

    @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:address-attributes_v2:{hmc_schema_version}"
        ]

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

    @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
        """

        # Collect and parse postal codes data into PostalCode objects
        postal_codes = (
            [
                PostalCode(
                    identifier=Identifier(pc.identifier),
                    postal_code=pc.postal_code,
                    type=pc.type if hasattr(pc, "type") else None,
                    display=decode_message(pc.display) if hasattr(pc, "display") else None,
                )
                for pc in msg.postal_code  # type: ignore
            ]
            if hasattr(msg, "postal_code")
            else None
        )

        # Replace postal_code_index with PostalCode object
        def map_postal_code(postal_mapping):
            if "postal_code_index" in postal_mapping:
                pc_index = postal_mapping["postal_code_index"]
                del postal_mapping["postal_code_index"]
                postal_mapping["postal_code"] = postal_codes[pc_index]

        content_partition = super().parse_and_index(partition_id, msg)
        if postal_codes:
            for addr_range in content_partition.objects("address_range"):
                for pm in addr_range.attribute["postal_mapping"]:  # type: ignore
                    map_postal_code(pm)

        return content_partition
