// send_message_to_slack to send message to slack channel
def send_message_to_slack(String MESSAGE, String COLOR) {
    withCredentials([usernamePassword(credentialsId: 'bubbles-slack-notify-token', passwordVariable: 'SLACK_TOKEN_VARIABLE', usernameVariable: '')]) {
        slackSend (
            teamDomain: 'nexlesoft', 
            token: "${SLACK_TOKEN_VARIABLE}", 
            channel: '#bubbles-build-notify', 
            color: "${COLOR}",
            message: "${MESSAGE}"
        )
    }
}

// deploy to deploy new code to the environment
def deploy(String environmentDeploy) {

    // Split environmentDeploy
    environmentDeployArr=environmentDeploy.split()

    // Deploy each environment in environmentDeployArr
    for (i=0;i < environmentDeployArr.size(); i++)
    {
        // Get environment
        ENV_DEPLOY=environmentDeployArr[i]
        echo "Environment deploying..."
        echo ENV_DEPLOY
        // Build
        withCredentials([usernamePassword(credentialsId: 'nexlesoft-docker-hub-url', passwordVariable: 'DOCKERHUB_REGISTRY', usernameVariable: '')]) {
            withCredentials([usernamePassword(credentialsId: 'bubbles-dockerhub', passwordVariable: 'DOCKERHUB_PASSWORD', usernameVariable: 'DOCKERHUB_USERNAME')]) {
                sh "export ENV=${ENV_DEPLOY} && export DOCKERHUB_REGISTRY=${DOCKERHUB_REGISTRY} && export DOCKERHUB_PASSWORD=${DOCKERHUB_PASSWORD} && export DOCKERHUB_USERNAME=${DOCKERHUB_USERNAME} && make build"
            }
            // Manual approve if env is prd
            verify_production("${ENV_DEPLOY}", "Deploy to production environment")

            // Deploy
            withCredentials([usernamePassword(credentialsId: 'bubbles-dockerhub', passwordVariable: 'DOCKERHUB_PASSWORD', usernameVariable: 'DOCKERHUB_USERNAME')]) {
                sh "export ENV=${ENV_DEPLOY} && export DOCKERHUB_REGISTRY=${DOCKERHUB_REGISTRY} && export DOCKERHUB_PASSWORD=${DOCKERHUB_PASSWORD} && export DOCKERHUB_USERNAME=${DOCKERHUB_USERNAME} && make deploy"
            }
        }    
    }
}

// verify_production to confirm process when environment is production
def verify_production(String environmentDeploy, String stageName) {
    stage("Verify Production") {
        echo stageName
        if ( environmentDeploy == "prd" ) 
        {
            send_message_to_slack("${MESSAGE_MANUAL_APPROVAL}", "${ORANGE_COLOR}")
            stageNameTitle = "Please confirm you sure to proceed " + stageName
            timeout(time: 3600, unit: "SECONDS") {
                def userInput 
                try {
                    input(
                    id: "userInput", message: stageName, parameters: [
                    [$class: "BooleanParameterDefinition", defaultValue: false , description: "", name: stageNameTitle]
                    ])
                } catch(err) { // input false
                    userInput = false
                   }

                // If confirm and stage is "DNS Rollback" ==> Rollback DNS
                if ( stageName == "DNS Rollback" )
                {
                    if ( userInput == true ) 
                    {   
                        sh "make dns-rollback"
                        currentBuild.result = "ABORTED"
                        error "Rollback DNS."
                    }
                }
                // Not confirm, exit
                else if ( userInput == false )
                {
                    currentBuild.result = "ABORTED"
                    error "Deploy wasnt confirmed."
                }
            }
        }
    }
}

// choose_environment_depend_on_branch_name to choose environment to deploy AWS depend on branch name
def choose_environment_depend_on_branch_name(String branchName) {
    stage("Choose Environment") {
        script {

            // Return prd if branch is hotfix
            if ( branchName ==~ /^(production$|hotfix)(.*)/) 
                { 
                    echo "prd will be deployed"
                    return "prd"
                } 
            
            // // Return prd and stg if branch is release
            // if ( branchName ==~ /^(release)(.*)/) 
            //     { 
            //         echo "prd and stg will be deployed"
            //         // stg will be deployed first. If you want to deploy prd first, swap the position in return command
            //         return "stg prd"
            //     }     

            // Return stg if branch is demo   
            else if ( branchName ==~ /^(demo)/) 
                {
                    echo "demo will be deployed"
                    return "demo"
                }

            // Return dev if branch is master or feature
            else if ( branchName ==~ /^(master$|feature)(.*)/) 
            {
                echo "Dev will be deployed"
                return "dev"
            }     
            
            // Return dev_tax if branch is dev_tax
            else if ( branchName ==~ /^(dev_tax)(.*)/) 
            {
                echo "dev_tax will be deployed"
                return "dev_tax"
            }      

            // Return dev_payroll if branch is dev_cr3_payroll
            else if ( branchName ==~ /^(dev_cr3_payroll)(.*)/) 
            {
                echo "dev_payroll will be deployed"
                return "dev_payroll"
            }                        
            else
            {
                echo "Can not detect environment."
                currentBuild.result = "ABORTED"
                error "Can not detect environment."
            }
        }
    }
}

// Pipeline
pipeline {
    options {
        disableConcurrentBuilds()
    }
    environment {
        BLUE_COLOR="#0f6ebe"
        GREEN_COLOR="#36a64f"
        RED_COLOR="#ff0000"
        ORANGE_COLOR="#f9a602"
    }
    // agent any
    agent { node { label 'jenkins-agent-1' } }
    stages {
        stage("Deploy with Docker") {
            steps {
                script {

                    // Get head commit id
                    env.HEAD_COMMIT_ID = sh(script: "git rev-parse --short HEAD", returnStdout: true).trim()
                    echo "HEAD_COMMIT_ID: ${HEAD_COMMIT_ID}"
                    
                    // Get branch name
                    BRANCH_NAME=env.BRANCH_NAME
                    echo "BRANCH_NAME: ${BRANCH_NAME}"

                    // Detect environment
                    env.ENV_DEPLOY_DEPEND_ON_BRANCH_NAME=choose_environment_depend_on_branch_name("${BRANCH_NAME}")
                    echo "ENV_DEPLOY_DEPEND_ON_BRANCH_NAME: ${ENV_DEPLOY_DEPEND_ON_BRANCH_NAME}"
                    
                    // Environment
                    JOB_NAME="${JOB_NAME}".split("/")[2]
                    MESSAGE_START="*[START]* *${JOB_NAME}* with *${BRANCH_NAME}* branch build is started with `${ENV_DEPLOY_DEPEND_ON_BRANCH_NAME}` environment (<${env.BUILD_URL}|#${env.BUILD_NUMBER}>)."
                    MESSAGE_MANUAL_APPROVAL="*[MANUAL_APPROVAL]* *${JOB_NAME}* with *${BRANCH_NAME}* branch build is waiting for approval with `${ENV_DEPLOY_DEPEND_ON_BRANCH_NAME}` environment (<${env.BUILD_URL}|#${env.BUILD_NUMBER}>)."
                    MESSAGE_SUCCESS="*[SUCCESS]* *${JOB_NAME}* with *${BRANCH_NAME}* branch build is success with `${ENV_DEPLOY_DEPEND_ON_BRANCH_NAME}` environment (<${env.BUILD_URL}|#${env.BUILD_NUMBER}>)."
                    MESSAGE_FAIL="*[FAILURE]* <!channel> *${JOB_NAME}* with *${BRANCH_NAME}* branch build is failure with `${ENV_DEPLOY_DEPEND_ON_BRANCH_NAME}` environment (<${env.BUILD_URL}|#${env.BUILD_NUMBER}>)."

                    // Send start notify to Slack
                    send_message_to_slack("${MESSAGE_START}", "${BLUE_COLOR}")

                    // Deploy
                    deploy("${ENV_DEPLOY_DEPEND_ON_BRANCH_NAME}")
                }
            }
        }
    }
    post {
        always {
            echo "Delete Jenkins Workspace."
            deleteDir()
            script {
                echo "Build is ${currentBuild.result}"
                echo "Post to slack!"
                if ( "${currentBuild.result}" == "SUCCESS" ) {
                    send_message_to_slack("${MESSAGE_SUCCESS}", "${GREEN_COLOR}")
                }
                else {
                    send_message_to_slack("${MESSAGE_FAIL}", "${RED_COLOR}")
                }
            }
        }
    }
}
