import groovy.transform.Field

@Field
DEPLOYMENT_TYPES = [
    'CREATE_TASK_DEFINITION': 'create-task-definition',
    'UPDATE_CLOUDWATCH_EVENT': 'update-cloudwatch-event',
    'UPDATE_SERVICE': 'deploy',
]

def call(Map args) {
    assert (args.awsRegions && args.environment && args.gitCommit && args.serviceName): 'awsRegions, environment, gitCommit, and serviceName arguments must be passed.'
    assert args.awsRegions.getClass() in Collection: 'awsRegions must be a list or set of regions'
    assert (args.deployType == null || DEPLOYMENT_TYPES.keySet().contains(args.deployType)): "Invalid deployType. Must be one of ${DEPLOYMENT_TYPES.keySet()}"

    // These variables need default values
    def clusterName = args.clusterName ?: "${args.environment}-${args.serviceName}"
    def containerName = args.containerName ?: args.serviceName
    def fargateServiceName = args.fargateServiceName ?: "${args.environment}-${args.serviceName}"
    def taskFamily = args.taskFamily ?: "${args.environment}-${args.serviceName}"
    boolean doUpdateCustomSidecars = args.doUpdateCustomSidecars == null ? false: args.doUpdateCustomSidecars
    def customSidecars = args.customSidecars == null ? "" : args.customSidecars.join(',')
    def deployType = args.deployType ?: 'UPDATE_SERVICE'
    def task_details_output_file_name = 'task_details.json'
    def dockerImage = args.dockerImage ?: '086679231553.dkr.ecr.us-east-1.amazonaws.com/fargate-tools:latest'

    List<String> environmentVariables = []

    /*
     * If arguments include optional parameters, set environment variable to that value.
     * If not, no need to set it as the deployment script has working defaults.
    */
    def optionalParameterMap = ['deployMode', 'ecrRegistryAccountId', 'ecrRegistryRegion', 'forceScaleOut', 'imageNameOverride', 'imageUri', 'updateTimeout', 'verifyMode']
    for (parameter in optionalParameterMap) {
        if (args."${parameter}") {
            def envVar = parameter.replaceAll('([A-Z])', '_$1').toUpperCase()
            println "Optional parameter provided - setting environment variable ${envVar}"
            environmentVariables << "${envVar}=${args."${parameter}"}"
        }
    }

    withEcr {
        dir("fargateDeploy/${fargateServiceName}") {
            checkout([$class: 'GitSCM', branches: [[name: '*/master']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: '577cbc72-7d9e-4eba-924c-ecbbe6de9805', url: "git@github.com:theorchard/python-deployment-utils.git"]]])
            for (def region in args.awsRegions) {
                println "Deploying to ${region}"

                def envVars = [
                    "AWS_REGION=${region}",
                    "CLUSTER_NAME=${clusterName}",
                    "CONTAINER_NAME=${containerName}",
                    "CUSTOM_SIDECARS=${customSidecars}",
                    "DO_UPDATE_CUSTOM_SIDECARS=${doUpdateCustomSidecars}",
                    "Environment=${args.environment}",
                    "FARGATE_SERVICE_NAME=${fargateServiceName}",
                    "GIT_COMMIT=${args.gitCommit}",
                    "SERVICE_NAME=${args.serviceName}",
                    "TASK_FAMILY=${taskFamily}",
                    "OUTPUT_FILE_PATH=/var/app/${task_details_output_file_name}",
                    *environmentVariables
                ]

                if (args.awsDeploymentRoleName && args.awsDeploymentTargetAccountId) {
                    withAWS(role: args.awsDeploymentRoleName, roleAccount: args.awsDeploymentTargetAccountId, roleSessionName: args.awsDeploymentRoleName, useNode: true) {
                        println "IAM role name provided - using ${args.awsDeploymentRoleName} as deployment role"
                        deploy(deployType, envVars, dockerImage)
                    }
                } else {
                    deploy(deployType, envVars, dockerImage)
                }
            }
        }
    }
    def task_details_output_file_path = "fargateDeploy/${fargateServiceName}/fargate/${task_details_output_file_name}"
    if (fileExists(task_details_output_file_path)) {
        return readJSON(file: task_details_output_file_path)
    }
}

def deploy(def deployType, List envVars, String dockerImage) {
    def cliCommand = DEPLOYMENT_TYPES[deployType]

    dir('fargate') {
        sh label: "Fargate Deploy", script: """
        docker run --rm \\
            -v "\${PWD}:/var/app" \\
            -w /var/app/docker \\
            -u \$(id -u):\$(id -g) \\
            -e PYTHONPATH=/var/app/docker \\
            -e AWS_ACCESS_KEY_ID \\
            -e AWS_SECRET_ACCESS_KEY \\
            -e AWS_SESSION_TOKEN \\
            -e JOB_URL \\
            ${envVars.collect { "-e '${it}'" }.join(' ')} \\
            ${dockerImage} \\
            ${cliCommand}
        """
    }
}
