#
#    Copyright (c) 2023 Project CHIP Authors
#    All rights reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License");
#    you may not use this file except in compliance with the License.
#    You may obtain a copy of the License at
#
#        http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS,
#    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#    See the License for the specific language governing permissions and
#    limitations under the License.
#

from dataclasses import dataclass, field

from chip.testing.conformance import ConformanceDecision
from chip.testing.global_attribute_ids import GlobalAttributeIds
from chip.testing.matter_testing import MatterBaseTest, async_test_body, default_matter_test_main
from chip.tlv import uint
from TC_DeviceConformance import DeviceConformanceTests


@dataclass
class ClusterMinimalElements:
    feature_masks: list[uint] = field(default_factory=list)
    attribute_ids: list[uint] = field(default_factory=list)
    # Only received commands are necessary - generated events are ALWAYS determined from accepted
    command_ids: list[uint] = field(default_factory=list)
    # TODO: need event support


class MinimalRepresentationChecker(DeviceConformanceTests):
    def GenerateMinimals(self, ignore_in_progress: bool, is_ci: bool) -> dict[uint, dict[uint, ClusterMinimalElements]]:
        if not self.xml_clusters:
            self.setup_class_helper()

        success, _ = self.check_conformance(ignore_in_progress, is_ci)
        if not success:
            self.fail_current_test("Problems with conformance")

        # Now what we know the conformance is OK, we want to expose all the data model elements on the device
        # that are OPTIONAL given the other elements that are present. We can do this by assessing the conformance
        # again only on the elements we have. Because we've already run the full conformance checkers, we can rely
        # on the optional response really meaning optional.
        # TODO: do we also want to record the optional stuff that's NOT implemented?
        # endpoint -> list of clusters by id
        representation: dict[uint, dict[uint, ClusterMinimalElements]] = {}
        for endpoint_id, endpoint in self.endpoints_tlv.items():
            representation[endpoint_id] = {}
            for cluster_id, cluster in endpoint.items():
                minimal = ClusterMinimalElements()
                if cluster_id not in self.xml_clusters.keys():
                    continue

                feature_map = cluster[GlobalAttributeIds.FEATURE_MAP_ID]
                attribute_list = cluster[GlobalAttributeIds.ATTRIBUTE_LIST_ID]
                all_command_list = cluster[GlobalAttributeIds.ACCEPTED_COMMAND_LIST_ID] + \
                    cluster[GlobalAttributeIds.GENERATED_COMMAND_LIST_ID]
                accepted_command_list = cluster[GlobalAttributeIds.ACCEPTED_COMMAND_LIST_ID]

                # All optional features
                feature_masks = [1 << i for i in range(32) if feature_map & (1 << i)]
                for f in feature_masks:
                    xml_feature = self.xml_clusters[cluster_id].features[f]
                    conformance_decision = xml_feature.conformance(feature_map, attribute_list, all_command_list)
                    if conformance_decision == ConformanceDecision.OPTIONAL:
                        minimal.feature_masks.append(f)

                # All optional attributes
                for attribute_id, attribute in cluster.items():
                    if attribute_id not in self.xml_clusters[cluster_id].attributes.keys():
                        if attribute_id > 0xFFFF:
                            # MEI
                            minimal.attribute_ids.append(attribute_id)
                        continue
                    xml_attribute = self.xml_clusters[cluster_id].attributes[attribute_id]
                    conformance_decision = xml_attribute.conformance(feature_map, attribute_list, all_command_list)
                    if conformance_decision == ConformanceDecision.OPTIONAL:
                        minimal.attribute_ids.append(attribute_id)

                # All optional commands
                for command_id in accepted_command_list:
                    if command_id not in self.xml_clusters[cluster_id].accepted_commands:
                        if command_id > 0xFFFF:
                            # MEI
                            minimal.attribute_ids.append(command_id)
                        continue
                    xml_command = self.xml_clusters[cluster_id].accepted_commands[command_id]
                    conformance_decision = xml_command.conformance(feature_map, attribute_list, all_command_list)
                    if conformance_decision == ConformanceDecision.OPTIONAL:
                        minimal.command_ids.append(command_id)

                representation[endpoint_id][cluster_id] = minimal

        return representation

    def PrettyPrintRepresentation(self, representation: dict[uint, dict[uint, ClusterMinimalElements]]) -> None:
        for endpoint_id, cluster_list in representation.items():
            print(f'Endpoint: {endpoint_id}')
            for cluster_id, minimals in cluster_list.items():
                name = self.xml_clusters[cluster_id].name
                print(f'  Cluster {cluster_id:04x} - {name}')
                print('    Features:')
                for feature in minimals.feature_masks:
                    code = self.xml_clusters[cluster_id].features[feature].code
                    print(f'      {feature:02x}: {code}')
                print('    Attributes:')
                for attribute in minimals.attribute_ids:
                    name = self.xml_clusters[cluster_id].attributes[attribute].name
                    print(f'      {attribute:02x}: {name}')
                print('    Commands:')
                for command in minimals.command_ids:
                    name = self.xml_clusters[cluster_id].accepted_commands[command].name
                    print(f'      {command:02x}: {name}')


# Helper for running this against a test device through the python test framework
class MinimalRunner(MatterBaseTest, MinimalRepresentationChecker):
    @async_test_body
    async def setup_class(self):
        super().setup_class()
        await self.setup_class_helper()

    def test_MinimalRepresentation(self):
        # Before we can generate a minimal representation, we need to make sure that the device is conformant.
        # Otherwise, the values we extract aren't fully informative.
        ignore_in_progress = self.user_params.get("ignore_in_progress", False)
        representation = self.GenerateMinimals(ignore_in_progress, self.is_pics_sdk_ci_only)
        print(type(representation[0]))
        self.PrettyPrintRepresentation(representation)


if __name__ == "__main__":
    default_matter_test_main()
