from troposphere import iam
import troposphere as tp


def _generate_execution_policy():
    return iam.ManagedPolicy(
        "BaseExecutionPolicy",
        PolicyDocument={
            "Version": "2012-10-17",
            "Statement": [{
                "Effect": "Allow",
                "Action": "lambda:*",
                "Resource": tp.Sub("arn:aws:lambda:${AWS::Region}:*:function:*")
            }],
        },
        ManagedPolicyName=tp.Sub('conio-sdk-${ConioEnv}-base-execution-policy')
    )


def _generate_execution_role(*policies):
    return iam.Role(
        "ConioSDKExecutionRole",
        AssumeRolePolicyDocument={
            "Version": "2012-10-17",
            "Statement": [{
                "Effect": "Allow",
                "Action": "sts:AssumeRole",
                "Principal": {
                    "Service": ["lambda.amazonaws.com"]
                }
            }]
        },
        ManagedPolicyArns=[
            "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess",
            "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole",
            "arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess"
            ] + [
            tp.Ref(p) for p in policies
        ],
        RoleName=tp.Sub("conio-sdk-${ConioEnv}-base-execution-role")
    )

def _generate_ssm_access_policy():
    return iam.ManagedPolicy(
        "ConioSDKSSMAccessPolicy",
        PolicyDocument={
            "Version": "2012-10-17",
            "Statement": [{
                "Effect": "Allow",
                "Action": [
                    "ssm:DescribeParameters",
                    "ssm:GetParameterHistory",
                    "ssm:GetParametersByPath",
                    "ssm:GetParameters",
                    "ssm:GetParameter"
                    ],
                "Resource": "*",
                "Condition": {
                    "StringLike": {
                        "ssm:resourceTag/ConioEnv": [tp.Ref("ConioEnv")]
                    }
                }
            }],
        },
        ManagedPolicyName=tp.Sub('conio-sdk-${ConioEnv}-ssm-access-policy')
    )

def _generate_dynamodb_access_policy(ddb_table):
    return iam.ManagedPolicy(
        "ConioSDKDynamoDB"+ddb_table.replace("Arn", "")+"AccessPolicy",
        PolicyDocument={
            "Version": "2012-10-17",
            "Statement": [{
                "Effect": "Allow",
                "Action": [
                    "dynamodb:BatchGetItem",
                    "dynamodb:BatchWriteItem",
                    "dynamodb:PutItem",
                    "dynamodb:DeleteItem",
                    "dynamodb:Scan",
                    "dynamodb:Query",
                    "dynamodb:DescribeStream",
                    "dynamodb:UpdateItem",
                    "dynamodb:CreateBackup",
                    "dynamodb:DescribeTable",
                    "dynamodb:GetShardIterator",
                    "dynamodb:DescribeGlobalTable",
                    "dynamodb:GetItem",
                    "dynamodb:DescribeContinuousBackups",
                    "dynamodb:DescribeBackup",
                    "dynamodb:GetRecords",
                ],
                "Resource": tp.Ref(ddb_table)
            }],
        },
        ManagedPolicyName=tp.Sub('conio-sdk-${ConioEnv}-ddb-'+ddb_table.replace("Arn", "")+'-access-policy')
    )


def generate_policy_template(conio_env_param, ddb_table_params):
    policy_template = tp.Template()
    policy_template.add_parameter(conio_env_param)

    for dtp in ddb_table_params:
        policy_template.add_parameter(
            tp.Parameter(
                dtp,
                Description=dtp,
                Type="String"
            )
        )

    base_execution_policy = _generate_execution_policy()
    policy_template.add_resource(base_execution_policy)
    ssm_access_policy = _generate_ssm_access_policy()
    policy_template.add_resource(ssm_access_policy)

    ddb_access_policies = []
    for t in ddb_table_params:
        ddb_access_policy = _generate_dynamodb_access_policy(t)
        policy_template.add_resource(ddb_access_policy)
        ddb_access_policies.append(ddb_access_policy)

    base_execution_role = _generate_execution_role(base_execution_policy, ssm_access_policy, *ddb_access_policies)
    policy_template.add_resource(base_execution_role)

    execution_role_output = tp.Output(
        "ExecutionRoleArn",
        Value=tp.GetAtt(base_execution_role, "Arn")
    )
    policy_template.add_output(execution_role_output)

    return policy_template.to_yaml()