import troposphere.ecs as ecs

from .common import *
from .shared import (Parameter, get_endvalue, get_expvalue, get_subvalue,
                     auto_get_props, get_condition, add_obj)
from .securitygroup import (SecurityGroupEcsService,
                            SecurityGroupRuleEcsService)


def ECS_ContainerDefinition():
    Containers = []
    for n, v in cfg.ContainerDefinitions.items():
        name = f'ContainerDefinitions{n}'  # Ex. ContainerDefinitions1

        EnvValue_Out_String = []
        EnvValue_Out_Map = {}
        for m, w in v['Environment'].items():
            if m.startswith('Env'):
                continue
            envname = f'{name}Environment{m}'
            envkeyname = w['Name']
            # parameters
            p_EnvValue = Parameter(f'{envname}Value')
            p_EnvValue.Description = (
                f'{envkeyname} - empty for default based on env/role')

            # If key NoParam is present skip adding Parameters
            # (usefull as they have a limited max number)
            if 'NoParam' not in w:
                add_obj(p_EnvValue)

            EnvValue_Out_String.append(
                '%s=${%s}' % (envkeyname, envkeyname))
            EnvValue_Out_Map.update({
                envkeyname: get_endvalue(f'{envname}Value')
            })

        # resources
        Container = ecs.ContainerDefinition(name)
        auto_get_props(Container, indexname=n)

        if len(cfg.ContainerDefinitions) == 1:
            Container.Cpu = If(
                'CpuTask',
                get_endvalue('Cpu'),
                get_endvalue(f'{name}Cpu')
            )
            Container.Memory = If(
                'LaunchTypeFarGate',
                get_endvalue('Memory'),
                get_endvalue(f'{name}Memory')
            )

        Containers.append(Container)

        # outputs
        o_EnvValueOut = Output(f'{name}Environment')
        o_EnvValueOut.Value = Sub(
            ','.join(EnvValue_Out_String), **EnvValue_Out_Map)

        add_obj(o_EnvValueOut)

    return Containers


def ECS_TaskDefinition(key):
    # Resources
    R_TaskDefinition = ecs.TaskDefinition('TaskDefinitionBase')
    auto_get_props(R_TaskDefinition)
    R_TaskDefinition.ContainerDefinitions = ECS_ContainerDefinition()

    add_obj([
        R_TaskDefinition])


def ECS_Service(key):
    # Resources
    R_SG = SecurityGroupEcsService('SecurityGroupEcsService')
    if cfg.LoadBalancerApplicationExternal:
        SGRule = SecurityGroupRuleEcsService(scheme='External')
        R_SG.SecurityGroupIngress.append(SGRule)

    if cfg.LoadBalancerApplicationInternal:
        SGRule = SecurityGroupRuleEcsService(scheme='Internal')
        R_SG.SecurityGroupIngress.append(SGRule)

    add_obj(R_SG)

    for n, v in getattr(cfg, key).items():
        if not v['IBOX_ENABLED']:
            continue
        mapname = f'{key}{n}'

        # delete not used LoadBalancers configuration, so that auto_get_props
        # do not find it
        for m in ['External', 'Internal']:
            if not getattr(cfg, f'LoadBalancerApplication{m}'):
                del v['LoadBalancers'][m]
        if not v['LoadBalancers']:
            # delete if empty to maintain compatibility with previous conf
            del v['LoadBalancers']

        r_Service = ecs.Service(mapname)
        auto_get_props(r_Service)

        if cfg.LoadBalancerApplication:
            r_Service.Role = If(
                'NetworkModeAwsVpc',
                Ref('AWS::NoValue'),
                get_expvalue('RoleECSService'))

        # When creating a service that specifies multiple target groups,
        # the Amazon ECS service-linked role must be created.
        # The role is created by omitting the Role property
        # in AWS CloudFormation
        if (cfg.LoadBalancerApplicationExternal and
                cfg.LoadBalancerApplicationInternal):
            r_Service.Role = Ref('AWS::NoValue')

        add_obj(r_Service)
