import groovy.json.JsonOutput

AWS_REGION = "us-west-2"

DEPLOY_BRANCHES = ["develop"]
DEPLOY_BRANCHES_WITH_CONFIRMATION = ["master"]
SLACK_CHANNEL = "#mdaas-deploys"

DEPLOY_CONFIRMATION_ENABLED = DEPLOY_BRANCHES_WITH_CONFIRMATION.contains(env.BRANCH_NAME)
DEPLOY_ENABLED = DEPLOY_BRANCHES.contains(env.BRANCH_NAME) || DEPLOY_CONFIRMATION_ENABLED
DEPLOY_NAME = env.BRANCH_NAME == "master" ? "Production" : "Staging"
DEPLOY_TARGET = env.BRANCH_NAME == "master" ? "prod" : "staging"
AWS_CREDENTIALS = DEPLOY_TARGET == "prod" ? "twitch-mdaas-ingest-prod" : "twitch-mdaas-ingest-dev"

JOB_URL = "${env.JENKINS_URL}job/${env.JOB_NAME.replace("/", "/job/")}/"

def gitCommitSha() {
    return sh(script: "git log -1 --format=%h", returnStdout: true).trim()
}

def gitCommitMessage() {
    return sh(script: "git log -1 --format=%B", returnStdout: true).trim()
}

def commitLink() {
    sha = gitCommitSha()
    msg = gitCommitMessage()
    return "<https://git.xarth.tv/devhub/mdaas-discovery-tags-validator/commits/${sha}|${sha}> ${msg}"
}

def message(payload) {
    try {
        slackSend(
            attachments: JsonOutput.toJson(payload),
            channel: SLACK_CHANNEL,
            tokenCredentialId: "samus-slack-api-token"
        )
    } catch (Exception e) {
        println e
    }
}

def startedMessage(stageName, icon) {
    message([[
        title: "Tags Validator: [${env.BRANCH_NAME}] ${DEPLOY_NAME} ${stageName} started ${icon}",
        text: commitLink(),
    ]])
}

def successMessage(stageName) {
    message([[
        title: "Tags Validator: [${env.BRANCH_NAME}] ${DEPLOY_NAME} ${stageName} succeeded 🎉",
        color: "good",
        text: commitLink(),
    ]])
}

def failureMessage(stageName) {
    message([[
        title: "Tags Validator: [${env.BRANCH_NAME}] ${DEPLOY_NAME} ${stageName} failed 💀",
        color: "danger",
        text: commitLink(),
        actions: [[
            type: "button",
            text: "Logs",
            url: "${env.BUILD_URL}console"
        ]]
    ]])
}

def confirmDeployMessage() {
    message([[
        title: "Tags Validator: [${env.BRANCH_NAME}] ${DEPLOY_NAME} build succeeded 🎉",
        color: "good",
        text: commitLink(),
        actions: [[
            type: "button",
            text: "Deploy",
            url: "${JOB_URL}"
        ]]
    ]])
}

pipeline {
    agent any

    options {
        disableConcurrentBuilds()
        timeout(time: 1, unit: "HOURS")
        timestamps()
    }

    environment {
        FORCE_DEPLOYS = "true"
    }

    stages {
        stage("Build") {
            steps {
                script {
                    if (DEPLOY_ENABLED) {
                        startedMessage("build", "🔨")
                    }
                }

                sh "make build-docker"
            }

            post {
                success {
                    script {
                        if (DEPLOY_ENABLED) {
                            successMessage("build")
                        }
                    }
                }

                failure {
                    script {
                        if (DEPLOY_ENABLED) {
                            failureMessage("build")
                        }
                    }
                }
            }
        }

        stage("Test & Lint") {
            parallel {
                stage("Lint") {
                    steps {
                        script {
                            if (DEPLOY_ENABLED) {
                                startedMessage("lint", "🔨")
                            }
                        }

                        sh "make lint-docker"
                    }

                    post {
                        success {
                            script {
                                if (DEPLOY_ENABLED) {
                                    successMessage("lint")
                                }
                            }
                        }

                        failure {
                            script {
                                if (DEPLOY_ENABLED) {
                                    failureMessage("lint")
                                }
                            }
                        }
                    }
                }

                stage("Test") {
                    steps {
                        script {
                            if (DEPLOY_ENABLED) {
                                startedMessage("tests", "🔨")
                            }
                        }

                        sh "make test-docker"
                    }

                    post {
                        success {
                            script {
                                if (DEPLOY_ENABLED) {
                                    successMessage("tests")
                                }
                            }
                        }

                        failure {
                            script {
                                if (DEPLOY_ENABLED) {
                                    failureMessage("tests")
                                }
                            }
                        }
                    }
                }
            }
        }

        stage("Confirm deploy") {
            when {
                expression { return DEPLOY_CONFIRMATION_ENABLED }
            }

            options {
                timeout(time: 5, unit: "MINUTES")
            }

            steps {
                script { confirmDeployMessage() }
                input message: "Deploy to ${DEPLOY_TARGET}?"
                echo "Deploying to ${DEPLOY_TARGET}."
            }
        }

        stage("Deploy") {
            when {
                expression { return DEPLOY_ENABLED }
            }

            steps {
                script { startedMessage("deploy", "🚀") }

                withAWS(credentials: AWS_CREDENTIALS, region: AWS_REGION) {
                    sh "make deploy-docker"
                }
            }

            post {
                success { script { successMessage("deploy") } }
                failure { script { failureMessage("deploy") } }
            }
        }
    }

    // Give access to Jenkins so jenkins can remove files created by the docker image. There may be a better way to do this.
    post{
        cleanup {
            script {
                docker.image("golang:latest").inside("-u root") {
                    sh "chown -R 61000:61000 /opt /go"
                }
            }
        }
    }
}
