"""
Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""

from cfnlint.rules import CloudFormationLintRule, RuleMatch


class AvailabilityZone(CloudFormationLintRule):
    """Check Availibility Zone parameter checks"""

    id = "W3010"
    shortdesc = "Availability Zone Parameters should not be hardcoded"
    description = "Check if an Availability Zone property is hardcoded."
    source_url = "https://github.com/aws-cloudformation/cfn-python-lint"
    tags = ["parameters", "availabilityzone"]

    def __init__(self):
        """Init"""
        super().__init__()
        resource_type_specs = [
            "AWS::AutoScaling::AutoScalingGroup",
            "AWS::DAX::Cluster",
            "AWS::DMS::ReplicationInstance",
            "AWS::EC2::Host",
            "AWS::EC2::Instance",
            "AWS::EC2::Subnet",
            "AWS::EC2::Volume",
            "AWS::ElasticLoadBalancing::LoadBalancer",
            "AWS::OpsWorks::Instance",
            "AWS::RDS::DBCluster",
            "AWS::RDS::DBInstance",
        ]

        property_type_specs = [
            # Singular
            "AWS::EC2::LaunchTemplate.Placement",
            "AWS::EC2::SpotFleet.LaunchTemplateOverrides",
            "AWS::EC2::SpotFleet.SpotPlacement",
            "AWS::EMR::Cluster.PlacementType",
            "AWS::ElasticLoadBalancingV2::TargetGroup.TargetDescription",
            "AWS::Glue::Connection.PhysicalConnectionRequirements",
        ]

        for resource_type_spec in resource_type_specs:
            self.resource_property_types.append(resource_type_spec)
        for property_type_spec in property_type_specs:
            self.resource_sub_property_types.append(property_type_spec)

    # pylint: disable=W0613
    def check_az_value(self, value, path):
        matches = []

        # value of `all` is a valide exception in AWS::ElasticLoadBalancingV2::TargetGroup
        if value not in ["all"]:
            if path[-1] != ["Fn::GetAZs"]:
                message = "Don't hardcode {0} for AvailabilityZones"
                matches.append(RuleMatch(path, message.format(value)))

        return matches

    def check(self, properties, resource_type, path, cfn):
        """Check itself"""
        matches = []

        # Skip rule if CDK
        if cfn.is_cdk_template():
            return matches

        matches.extend(
            cfn.check_value(
                properties,
                "AvailabilityZone",
                path,
                check_value=self.check_az_value,
                check_ref=None,
                check_find_in_map=None,
                check_split=None,
                check_join=None,
            )
        )
        matches.extend(
            cfn.check_value(
                properties,
                "AvailabilityZones",
                path,
                check_value=self.check_az_value,
                check_ref=None,
                check_find_in_map=None,
                check_split=None,
                check_join=None,
            )
        )

        return matches

    def match_resource_sub_properties(self, properties, property_type, path, cfn):
        """Match for sub properties"""
        matches = []

        matches.extend(self.check(properties, property_type, path, cfn))

        return matches

    def match_resource_properties(self, properties, resource_type, path, cfn):
        """Check CloudFormation Properties"""
        matches = []

        matches.extend(self.check(properties, resource_type, path, cfn))

        return matches
