from pulumi import ComponentResource, ResourceOptions, Output
import pulumi_aws as aws
import json


class WebServiceArgs:

    def __init__(self,
                 db_host=None,
                 db_port=None,
                 db_name=None,
                 db_user=None,
                 db_password=None,
                 vpc_id=None,
                 subnet_ids=None,  # array of subnet IDs
                 security_group_ids=None):  # array of security group Ids

        self.db_host = db_host
        self.db_port = db_port
        self.db_name = db_name
        self.db_user = db_user
        self.db_password = db_password
        self.vpc_id = vpc_id
        self.subnet_ids = subnet_ids
        self.security_group_ids = security_group_ids


class WebService(ComponentResource):

    def __init__(self,
                 name: str,
                 args: WebServiceArgs,
                 opts: ResourceOptions = None):

        super().__init__('custom:resource:Frontend', name, {}, opts)

        # Create an ECS cluster to run a container-based service.
        self.cluster = aws.ecs.Cluster(f'{name}-ecs',
            opts=ResourceOptions(parent=self)
            )

        # Create a load balancer to listen for HTTP traffic on port 80.
        self.alb = aws.lb.LoadBalancer(f'{name}-alb',
            security_groups=args.security_group_ids,
            subnets=args.subnet_ids,
            opts=ResourceOptions(parent=self)
            )

        atg = aws.lb.TargetGroup(f'{name}-app-tg',
            port=80,
            protocol='HTTP',
            target_type='ip',
            vpc_id=args.vpc_id,
            health_check=aws.lb.TargetGroupHealthCheckArgs(
                healthy_threshold=2,
                interval=5,
                timeout=4,
                protocol='HTTP',
                matcher='200-399'
            ),
            opts=ResourceOptions(parent=self)
            )

        wl = aws.lb.Listener(f'{name}-listener',
            load_balancer_arn=self.alb.arn,
            port=80,
            default_actions=[aws.lb.ListenerDefaultActionArgs(
                type='forward',
                target_group_arn=atg.arn,
            )],
            opts=ResourceOptions(parent=self)
            )

        # Create an IAM role that can be used by our service's task.
        role = aws.iam.Role(f'{name}-task-role',
            assume_role_policy=json.dumps({
                'Version': '2008-10-17',
                'Statement': [{
                    'Sid': '',
                    'Effect': 'Allow',
                    'Principal': {
                        'Service': 'ecs-tasks.amazonaws.com'
                    },
                    'Action': 'sts:AssumeRole',
                }]
            }),
            opts=ResourceOptions(parent=self)
            )

        rpa = aws.iam.RolePolicyAttachment(f'{name}-task-policy',
            role=role.name,
            policy_arn='arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy',
            opts=ResourceOptions(parent=self))

        # Spin up a load balanced service running our container image.
        task_name = f'{name}-app-task'
        container_name = f'{name}-app-container'
        self.task_definition = Output.all(args.db_host, args.db_port, args.db_name, args.db_user, args.db_password).apply(
            lambda args:
            aws.ecs.TaskDefinition(task_name,
            family='fargate-task-definition',
            cpu='256',
            memory='512',
            network_mode='awsvpc',
            requires_compatibilities=[
                'FARGATE'],
            execution_role_arn=role.arn,
            container_definitions=json.dumps([{
                'name': container_name,
                'image': 'wordpress',
                'portMappings': [{
                    'containerPort': 80,
                    'hostPort': 80,
                    'protocol': 'tcp'
                }],
                'environment': [
                    {
                        'name': 'WORDPRESS_DB_HOST',
                        'value': f'{args[0]}:{args[1]}'
                    },
                    {
                        'name': 'WORDPRESS_DB_NAME',
                        'value': f'{args[2]}'
                    },
                    {
                        'name': 'WORDPRESS_DB_USER',
                        'value': f'{args[3]}'
                    },
                    {
                        'name': 'WORDPRESS_DB_PASSWORD',
                        'value': f'{args[4]}'
                    },
                ]
            }]),
            opts=ResourceOptions(parent=self)
            )
        )

        self.service = aws.ecs.Service(f'{name}-app-svc',
            cluster=self.cluster.arn,
            desired_count=1,
            launch_type='FARGATE',
            task_definition=self.task_definition.arn,
            network_configuration=aws.ecs.ServiceNetworkConfigurationArgs(
                assign_public_ip=True,
                subnets=args.subnet_ids,
                security_groups=args.security_group_ids
            ),
            load_balancers=[aws.ecs.ServiceLoadBalancerArgs(
                target_group_arn=atg.arn,
                container_name=container_name,
                container_port=80,
            )],
            opts=ResourceOptions(
                depends_on=[wl], parent=self),
            )

        self.register_outputs({})
