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

from cfnlint.rules import CloudFormationLintRule, RuleMatch


class Ebs(CloudFormationLintRule):
    """Check Ec2 Ebs Resource Properties"""

    id = "E2504"
    shortdesc = "Check Ec2 Ebs Properties"
    description = "See if Ec2 Ebs Properties are valid"
    source_url = "https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-blockdev-template.html"
    tags = ["properties", "ec2", "ebs"]

    def _checkEbs(self, cfn, ebs, path):
        matches = []

        if isinstance(ebs, dict):
            volume_types_obj = cfn.get_values(ebs, "VolumeType")
            iops_obj = cfn.get_values(ebs, "Iops")
            if volume_types_obj is not None:
                for volume_type_obj in volume_types_obj:
                    volume_type = volume_type_obj.get("Value")
                    if isinstance(volume_type, str):
                        if volume_type in ("io1", "io2"):
                            if iops_obj is None:
                                pathmessage = path[:] + ["VolumeType"]
                                message = "VolumeType {0} requires Iops to be specified for {1}"
                                matches.append(
                                    RuleMatch(
                                        pathmessage,
                                        message.format(
                                            volume_type, "/".join(map(str, pathmessage))
                                        ),
                                    )
                                )
                        elif volume_type in ("gp2", "st1", "sc1", "standard"):
                            if iops_obj is not None:
                                pathmessage = path[:] + ["Iops"]
                                message = (
                                    "Iops shouldn't be defined for type {0} for {1}"
                                )
                                matches.append(
                                    RuleMatch(
                                        pathmessage,
                                        message.format(
                                            volume_type, "/".join(map(str, pathmessage))
                                        ),
                                    )
                                )

        return matches

    def match(self, cfn):
        """Check Ec2 Ebs Resource Parameters"""

        matches = []

        results = cfn.get_resource_properties(
            ["AWS::EC2::Instance", "BlockDeviceMappings"]
        )
        results.extend(
            cfn.get_resource_properties(
                ["AWS::AutoScaling::LaunchConfiguration", "BlockDeviceMappings"]
            )
        )
        for result in results:
            path = result["Path"]
            if isinstance(result["Value"], list):
                for index, properties in enumerate(result["Value"]):
                    virtual_name = properties.get("VirtualName")
                    ebs = properties.get("Ebs")
                    if virtual_name:
                        # switch to regex
                        if not re.match(
                            r"^ephemeral([0-9]|[1][0-9]|[2][0-3])$", virtual_name
                        ):
                            pathmessage = path[:] + [index, "VirtualName"]
                            message = "Property VirtualName should be of type ephemeral(n) for {0}"
                            matches.append(
                                RuleMatch(
                                    pathmessage,
                                    message.format("/".join(map(str, pathmessage))),
                                )
                            )
                    elif ebs:
                        matches.extend(
                            self._checkEbs(cfn, ebs, path[:] + [index, "Ebs"])
                        )
        return matches
