"""
Autogenerated using `pop-create-idem <https://gitlab.com/saltstack/pop/pop-create-idem>`__

hub.exec.boto3.client.ecr.describe_repositories
hub.exec.boto3.client.ecr.delete_repository_policy
hub.exec.boto3.client.ecr.get_repository_policy
hub.exec.boto3.client.ecr.set_repository_policy
"""
import copy
from typing import Any
from typing import Dict

__contracts__ = ["resource"]


async def present(
    hub,
    ctx,
    name: str,
    repository_name: str,
    policy_text: Dict or str,
    resource_id: str = None,
    registry_id: str = None,
    force: bool = False,
) -> Dict[str, Any]:
    r"""
    Applies a repository policy to the specified repository to control access permissions.
    For more information, see Amazon ECR Repository policies in the Amazon Elastic Container Registry User Guide.

    Args:
        name(string): An Idem name of the resource.
        repository_name(string): The name of the repository to receive the policy.
        policy_text(Dict or string): The JSON repository policy text to apply to the repository.
        resource_id(string, optional): The registry id and repository name with a separator '-'. Format: [registry_id]-[repository_name].
        registry_id(string, optional): The Amazon Web Services account ID associated with the registry that contains the repository. If you
            do not specify a registry, the default registry is assumed.
        force(bool, optional): If the policy you are attempting to set on a repository policy would prevent you from setting another policy
            in the future, you must force the SetRepositoryPolicy operation. This is intended to prevent accidental repository lock outs.

    Request Syntax:
        [idem_test_aws_ecr_repository_policy]:
          aws.ecr.repository_policy.present:
            - name: 'string'
            - repository_name: 'string'
            - policy_text: 'string'
            - registry_id: 'string'
            - force: True|False

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            idem_test_aws_ecr_repository_policy:
              aws.ecr.repository.present:
                - name: value
                - repository_name: value
                - policy_text: value
                - registry_id: value
                - force: True
    """

    result = dict(comment=(), old_state=None, new_state=None, name=name, result=True)

    before_ret = None
    resource_updated = False
    policy_text = hub.tool.aws.state_comparison_utils.standardise_json(policy_text)

    if resource_id:
        if registry_id is None:
            registry_id = resource_id.split("-")[0]

    before_ret = await hub.exec.boto3.client.ecr.get_repository_policy(
        ctx, registryId=registry_id, repositoryName=repository_name
    )
    if not before_ret["result"]:
        if "RepositoryNotFoundException" not in str(
            before_ret["comment"][0]
        ) and "RepositoryPolicyNotFoundException" not in str(before_ret["comment"][0]):
            result["result"] = False
            result["comment"] = before_ret["comment"]
            return result

    if before_ret:
        result["comment"] = (f"aws.ecr.repository_policy '{name}' already exists",)
        result[
            "old_state"
        ] = hub.tool.aws.ecr.conversion_utils.convert_raw_repository_policy_to_present(
            raw_resource=before_ret.get("ret"),
            idem_resource_name=name,
        )
        result["new_state"] = copy.deepcopy(result["old_state"])

        if policy_text and not hub.tool.aws.state_comparison_utils.is_json_identical(
            result["old_state"]["policy_text"], policy_text
        ):
            if ctx.get("test", False):
                result["comment"] = result["comment"] + (
                    f"Would update policy_text for aws.ecr.repository_policy '{name}'",
                )
                result["new_state"]["policy_text"] = policy_text
                return result

            update_ret = await hub.exec.boto3.client.ecr.set_repository_policy(
                ctx,
                registryId=registry_id,
                repositoryName=repository_name,
                policyText=policy_text,
                force=force,
            )
            if not update_ret["result"]:
                result["result"] = False
                result["comment"] = result["comment"] + update_ret["comment"]
                return result

            result["comment"] = result["comment"] + (
                f"Updated aws.ecr.repository_policy '{name}'",
            )
            resource_updated = True
    else:
        if ctx.get("test", False):
            result[
                "new_state"
            ] = raw_resource = hub.tool.aws.test_state_utils.generate_test_state(
                enforced_state={},
                desired_state={
                    "name": name,
                    "resource_id": f"{registry_id}-{repository_name}",
                    "registry_id": registry_id,
                    "repository_name": repository_name,
                    "policy_text": policy_text,
                },
            )
            result["comment"] = hub.tool.aws.comment_utils.would_create_comment(
                resource_type="aws.ecr.repository_policy", name=name
            )
            return result

        set_policy_ret = await hub.exec.boto3.client.ecr.set_repository_policy(
            ctx,
            registryId=registry_id,
            repositoryName=repository_name,
            policyText=policy_text,
            force=force,
        )
        if not set_policy_ret["result"]:
            result["result"] = False
            result["comment"] = set_policy_ret["comment"]
            return result

        result["comment"] = hub.tool.aws.comment_utils.create_comment(
            resource_type="aws.ecr.repository_policy", name=name
        )

    if (not result["old_state"]) or resource_updated:
        after_ret = await hub.exec.boto3.client.ecr.get_repository_policy(
            ctx, registryId=registry_id, repositoryName=repository_name
        )
        if not after_ret["result"]:
            result["result"] = False
            result["comment"] = result["comment"] + after_ret["comment"]
            return result

        result[
            "new_state"
        ] = hub.tool.aws.ecr.conversion_utils.convert_raw_repository_policy_to_present(
            raw_resource=after_ret.get("ret"),
            idem_resource_name=name,
        )

    return result


async def absent(
    hub,
    ctx,
    name: str,
    repository_name: str,
    resource_id: str = None,
    registry_id: str = None,
) -> Dict[str, Any]:
    r"""
    Deletes the repository policy associated with the specified repository.

    Args:
        name(string): An Idem name of the resource.
        repository_name(string): The name of the repository that contains the policy to delete.
        resource_id(string, optional): The registry id and repository name with a separator '-'. Format: [registry_id]-[repository_name].
            Idem automatically considers this resource being absent if this field is not specified.
        registry_id(string, optional): The Amazon Web Services account ID associated with the registry that contains the repository policy to
            delete. If you do not specify a registry, the default registry is assumed. Defaults to None.

    Request syntax:
        [idem_test_aws_ecr_repository_policy]:
          aws.ecr.repository_policy.absent:
            - name: 'string'
            - repository_name: value
            - resource_id: 'string'
            - registry_id: 'string'

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            idem_test_aws_ecr_repository_policy:
              aws.ecr.repository_policy.absent:
                - name: value
                - repository_name: value
                - resource_id: value
                - registry_id: value
    """

    result = dict(comment=(), old_state=None, new_state=None, name=name, result=True)

    if not resource_id:
        result["comment"] = hub.tool.aws.comment_utils.already_absent_comment(
            resource_type="aws.ecr.repository_policy", name=name
        )
        return result
    else:
        if registry_id is None:
            registry_id = resource_id.split("-")[0]

    before_ret = await hub.exec.boto3.client.ecr.get_repository_policy(
        ctx, registryId=registry_id, repositoryName=repository_name
    )
    if not before_ret["result"]:
        if "RepositoryNotFoundException" in str(
            before_ret["comment"][0]
        ) or "RepositoryPolicyNotFoundException" in str(before_ret["comment"][0]):
            result["comment"] = hub.tool.aws.comment_utils.already_absent_comment(
                resource_type="aws.ecr.repository_policy", name=name
            )
        else:
            result["result"] = False
            result["comment"] = before_ret["comment"]
        return result

    result[
        "old_state"
    ] = hub.tool.aws.ecr.conversion_utils.convert_raw_repository_policy_to_present(
        raw_resource=before_ret.get("ret"),
        idem_resource_name=name,
    )

    if ctx.get("test", False):
        result["comment"] = hub.tool.aws.comment_utils.would_delete_comment(
            resource_type="aws.ecr.repository_policy", name=name
        )
        return result

    delete_ret = await hub.exec.boto3.client.ecr.delete_repository_policy(
        ctx, registryId=registry_id, repositoryName=repository_name
    )
    if not result["result"]:
        result["result"] = False
        result["comment"] = delete_ret["comment"]
        return result

    result["comment"] = hub.tool.aws.comment_utils.delete_comment(
        resource_type="aws.ecr.repository_policy", name=name
    )

    return result


async def describe(hub, ctx) -> Dict[str, Dict[str, Any]]:
    r"""
    Describes policies for image repositories in a registry in a way that can be recreated/managed with the corresponding "present" function.

    Returns:
        Dict[str, Dict[str, Any]]

    Examples:

        .. code-block:: bash

            $ idem describe aws.ecr.repository_policy
    """

    result = {}

    # To describe all the repository policies, we first need to list all the repositories,
    # and then we get the policy associated to each repository
    describe_ret = await hub.exec.boto3.client.ecr.describe_repositories(ctx)
    if not describe_ret["result"]:
        hub.log.warning(f"Could not describe repositories: {describe_ret['comment']}")
        return result

    for repository in describe_ret["ret"].get("repositories"):
        registry_id = repository.get("registryId")
        repository_name = repository.get("repositoryName")

        get_policy_ret = await hub.exec.boto3.client.ecr.get_repository_policy(
            ctx,
            registryId=registry_id,
            repositoryName=repository_name,
        )
        if not get_policy_ret["result"]:
            hub.log.warning(
                f"Could not get policy for repository '{registry_id}/{repository_name}': "
                f"{get_policy_ret['comment']}. Describe will skip this repository and continue."
            )
            continue

        resource_translated = (
            hub.tool.aws.ecr.conversion_utils.convert_raw_repository_policy_to_present(
                raw_resource=get_policy_ret.get("ret"),
            )
        )

        result[resource_translated.get("name")] = {
            "aws.ecr.repository_policy.present": [
                {parameter_key: parameter_value}
                for parameter_key, parameter_value in resource_translated.items()
            ]
        }

    return result


async def search(
    hub, ctx, name, repository_name: str, registry_id: str = None
) -> Dict[str, Any]:
    r"""
    Use an un-managed ECR repository policy as a data-source.

    Args:
        name(string): An Idem name of the resource.
        repository_name(string): The name of the repository that contains the policy to search.
        registry_id(string, optional): The Amazon Web Services account ID associated with the registry that contains the repository
            with the policy to search. If you do not specify a registry, the default registry is assumed. Defaults to None.

    Request syntax:
        [idem_test_aws_ecr_repository_policy]:
          aws.ecr.repository_policy.search:
            - name: 'string'
            - repository_name: 'string'
            - registry_id: 'string'

    Returns:
        Dict[str, Any]

    Examples:

        .. code-block:: sls

            idem_test_aws_ecr_repository_policy:
              aws.ecr.repository_policy.search:
                - name: value
                - repository_name: value
                - registry_id: value
    """

    result = dict(comment=(), old_state=None, new_state=None, name=name, result=True)

    get_policy_ret = await hub.exec.boto3.client.ecr.get_repository_policy(
        ctx, registryId=registry_id, repositoryName=repository_name
    )
    if not get_policy_ret["result"]:
        result["result"] = False
        if "RepositoryNotFoundException" in str(
            get_policy_ret["comment"][0]
        ) or "RepositoryPolicyNotFoundException" in str(get_policy_ret["comment"][0]):
            result["comment"] = (
                f"Unable to find aws.ecr.repository_policy resource for repository '{registry_id}/{repository_name}'",
            )
        else:
            result["comment"] = get_policy_ret["comment"]
        return result

    result[
        "old_state"
    ] = hub.tool.aws.ecr.conversion_utils.convert_raw_repository_policy_to_present(
        raw_resource=get_policy_ret.get("ret"),
        idem_resource_name=name,
    )
    result["new_state"] = copy.deepcopy(result["old_state"])

    return result
