# -*- coding: utf-8 -*-

#  Copyright 2017 Michael De La Rue | Ansible
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

import re


def validate_aws_arn(
    arn, partition=None, service=None, region=None, account_id=None, resource=None, resource_type=None, resource_id=None
):
    details = parse_aws_arn(arn)

    if not details:
        return False

    if partition and details.get("partition") != partition:
        return False
    if service and details.get("service") != service:
        return False
    if region and details.get("region") != region:
        return False
    if account_id and details.get("account_id") != account_id:
        return False
    if resource and details.get("resource") != resource:
        return False
    if resource_type and details.get("resource_type") != resource_type:
        return False
    if resource_id and details.get("resource_id") != resource_id:
        return False

    return True


def parse_aws_arn(arn):
    """
    Based on https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html

    The following are the general formats for ARNs.
        arn:partition:service:region:account-id:resource-id
        arn:partition:service:region:account-id:resource-type/resource-id
        arn:partition:service:region:account-id:resource-type:resource-id
    The specific formats depend on the resource.
    The ARNs for some resources omit the Region, the account ID, or both the Region and the account ID.

    Note: resource_type handling is very naive, for complex cases it may be necessary to use
    "resource" directly instead of resource_type, this will include the resource type and full ID,
    including all paths.
    """
    m = re.search(r"arn:(aws(-([a-z\-]+))?):([\w-]+):([a-z0-9\-]*):(\d*|aws|aws-managed):(.*)", arn)
    if m is None:
        return None
    result = dict()
    result.update(dict(partition=m.group(1)))
    result.update(dict(service=m.group(4)))
    result.update(dict(region=m.group(5)))
    result.update(dict(account_id=m.group(6)))
    result.update(dict(resource=m.group(7)))

    m2 = re.search(r"^([^:/]*)[:/](.+)$", m.group(7))
    if m2 is None:
        result.update(dict(resource_type=None, resource_id=m.group(7)))
    else:
        result.update(dict(resource_type=m2.group(1), resource_id=m2.group(2)))

    return result


# An implementation of this used was originally in ec2.py, however Outposts
# aren't specific to the EC2 service
def is_outpost_arn(arn):
    """
    Validates that the ARN is for an AWS Outpost


    API Specification Document:
    https://docs.aws.amazon.com/outposts/latest/APIReference/API_Outpost.html
    """
    details = parse_aws_arn(arn)

    if not details:
        return False

    service = details.get("service") or ""
    if service.lower() != "outposts":
        return False
    resource = details.get("resource") or ""
    if not re.match("^outpost/op-[a-f0-9]{17}$", resource):
        return False

    return True
