# 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 Metadata.
"""
from dataclasses import dataclass
from typing import List, Mapping, Optional

from google.protobuf.message import Message
from here.content.base import ContentIndexer, ContentPartition, SingleLayerBinding
from here.content.utils.proto import decode_message
from here.platform.adapter import DecodedMessage, Identifier


@dataclass
class CategorySystem:
    """A category system."""

    identifier: Identifier
    name: DecodedMessage
    description: Optional[DecodedMessage]

    indexer = ContentIndexer(identifier="identifier")


@dataclass
class Category:
    """A category that belongs to a category system."""

    identifier: Identifier
    name: DecodedMessage
    description: Optional[DecodedMessage]
    category_system: Identifier

    indexer = ContentIndexer(identifier="identifier")


class Metadata(SingleLayerBinding):
    """
    Bindings for the HMC Metadata.
    """

    @classmethod
    def schema_hrn(cls) -> List[str]:
        """
        :return: the HRN of schema this binding can parse and index
        """
        return ["hrn:here:schema:::com.here.schema.rib:meta_v2:2.71.0"]

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

        return {
            "category_system": CategorySystem,
            "category": Category,
        }

    @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, "category_system")
        assert hasattr(msg, "category")

        category_system = [
            CategorySystem(
                identifier=Identifier(s.identifier),
                name=decode_message(s.name[0]),
                description=decode_message(s.description[0]) if s.description else None,
            )
            for s in msg.category_system  # type: ignore
        ]
        category = [
            Category(
                identifier=Identifier(c.identifier),
                name=decode_message(c.name[0]),
                description=decode_message(c.description[0]) if c.description else None,
                category_system=category_system[c.category_system_index].identifier,
            )
            for c in msg.category  # type: ignore
        ]

        return ContentPartition(cls, category_system=category_system, category=category)
