import groovy.json.JsonSlurperClassic

// Uploads a file to a Gitlab project
// Requires env.GITLAB_BASE_URL
String uploadFileToGitLab(String fileName, String projectId) {
    String link = ""
    String response = ""
    withCredentials([string(credentialsId: 'gitlab-api-token', variable: 'TOKEN')]) {
        response = sh(script: "curl -s --request POST --header 'PRIVATE-TOKEN:\$TOKEN' --form file=@${fileName} ${env.GITLAB_BASE_URL}/api/v4/projects/${projectId}/uploads", returnStdout: true).trim()
    }
    link = new JsonSlurperClassic().parseText(response).markdown
    echo "Logs uploaded to: ${link}"
    return link
}

// Downloads the console log from this Jenkins build
void downloadJenkinsConsoleLog(String fileName) {
    withCredentials([usernameColonPassword(credentialsId: 'jenkins-ro', variable: 'CREDENTIALS')]) {
        sh "curl -u \"\${CREDENTIALS}\" ${BUILD_URL}consoleText -o ${fileName}"
    }
}

// Downloads the logs of the build, uploads them to the gitlab project
// And return the URL
String getLogsUrl(String projectId) {
    String message = ""
    String fileName = "build.log"
    String logUrl = ""
    downloadJenkinsConsoleLog(fileName)
    return uploadFileToGitLab(fileName, projectId)
}

// Post a failure message in MR
void commentFailedBuild() {
    logUrl = getLogsUrl(env.PROJECT_ID)
    addGitLabMRComment(comment: ":red_circle: ${currentBuild.projectName} :green_apple: <b>SDK iOS</b> FAILURE  :worried:<br/>Build results: [Jenkins [${currentBuild.displayName}]](${currentBuild.absoluteUrl})<br/>Commit: ${env.GIT_COMMIT}<br/>Logs: ${logUrl}" )
    updateGitlabCommitStatus(name: 'Build iOS', state: 'failed')
}

pipeline {
    agent none
    options {
        buildDiscarder(logRotator(numToKeepStr: '135', daysToKeepStr: '21'))
        gitLabConnection('GitLabConnectionJenkins')
        ansiColor('xterm')
    }

    parameters {
        booleanParam(name: 'IOS_REBUILD_3RDPARTY', defaultValue: false, description: 'Should we rebuild 3rdparty deps for iOS?')
    }

    environment {
        BUILD_OPTIONS = ' '
    }

    stages {
        stage('Update Gitlab commitStatus') {
            agent any
            steps {
                updateGitlabCommitStatus(name: 'Build iOS', state: 'running')
                script{
                    COMMIT_ID = env.GIT_COMMIT
                    println GIT_COMMIT
                }
            }
        }
        stage('Build'){
            agent { label 'osx && arm64' }
            stages {
                stage('clean previous runs'){
                    steps{
                        deleteDir()
                    }
                }
                stage('Get build parameters'){
                    parallel{
                        stage('Get build options'){
                            when {
                                allOf {
                                    expression { env.gitlabTriggerPhrase != null }
                                    expression { env.gitlabTriggerPhrase.contains('BUILD_OPTIONS') }
                                }
                            }
                            steps {
                                script{
                                    BUILD_OPTIONS = sh(script: 'echo "$gitlabTriggerPhrase" | grep BUILD_OPTIONS | awk -F "BUILD_OPTIONS="  \'{print \$2}\' | cut -d"\"" -f2', returnStdout: true).trim()
                                    println BUILD_OPTIONS
                                }
                            }
                        }

                        stage('Get MEGAchat branch'){
                            steps {
                                script{
                                    env.MEGACHAT_BRANCH = sh(script: 'echo "$gitlabMergeRequestDescription" | grep MEGACHAT_BRANCH_TO_TEST | awk -F "MEGACHAT_BRANCH_TO_TEST="  \'{print \$2}\' | cut -d" " -f1', returnStdout: true).trim()
                                    if (MEGACHAT_BRANCH == ""){
                                        echo "MEGACHAT_BRANCH was not found on description so develop will be used by default"
                                        env.MEGACHAT_BRANCH = "develop"
                                    }
                                    println MEGACHAT_BRANCH
                                }
                            }
                        }

                        stage('Get iOS branch'){
                            steps {
                                script{
                                    env.IOS_BRANCH = sh(script: 'echo "$gitlabMergeRequestDescription" | grep IOS_BRANCH_TO_TEST | awk -F "IOS_BRANCH_TO_TEST="  \'{print \$2}\' | cut -d" " -f1', returnStdout: true).trim()
                                    if (IOS_BRANCH == ""){
                                        echo "IOS_BRANCH was not found on description so develop will be used by default"
                                        env.IOS_BRANCH = "develop"
                                    }
                                    println IOS_BRANCH
                                }
                            }
                        }
                    }
                }

                stage('Checkout SDK MEGAchat and iOS'){
                    steps {
                        //Clone iOS
                        sh "echo Cloning iOS branch \"${IOS_BRANCH}\""
                        checkout([
                            $class: 'GitSCM',
                            branches: [[name: "${IOS_BRANCH}"]],
                            userRemoteConfigs: [[ url: "${env.GIT_URL_IOS}", credentialsId: "12492eb8-0278-4402-98f0-4412abfb65c1" ]],
                            extensions: [
                                [$class: "UserIdentity",name: "jenkins", email: "jenkins@jenkins"]
                                ]
                        ])
                        withCredentials([gitUsernamePassword(credentialsId: 'jenkins_sdk_token_with_user', gitToolName: 'Default')]) {
                            sh "git submodule update --init --recursive"
                        }
                        script{
                            ios_sources_workspace = WORKSPACE
                            sdk_sources_workspace = "${ios_sources_workspace}/Modules/DataSource/MEGASDK/Sources/MEGASDK"
                            megachat_sources_workspace = "${ios_sources_workspace}/Modules/DataSource/MEGAChatSDK/Sources/MEGAChatSDK"
                        }
                        dir('Modules/DataSource/MEGAChatSDK/Sources/MEGAChatSDK'){

                            //Clone MEGAchat
                            sh "echo Cloning megachat branch \"${env.MEGACHAT_BRANCH}\""
                            checkout([
                                $class: 'GitSCM',
                                branches: [[name: "${env.MEGACHAT_BRANCH}"]],
                                userRemoteConfigs: [[ url: "${env.GIT_URL_MEGACHAT}", credentialsId: "12492eb8-0278-4402-98f0-4412abfb65c1" ]],
                                extensions: [
                                    [$class: "UserIdentity",name: "jenkins", email: "jenkins@jenkins"]
                                    ]
                            ])
                        }
                        dir('Modules/DataSource/MEGASDK/Sources/MEGASDK'){
                            //Clone SDK (with PreBuildMerge)
                            checkout([
                                $class: 'GitSCM',
                                branches: [[name: "origin/${env.gitlabSourceBranch}"]],
                                userRemoteConfigs: [[ url: "${GIT_URL_SDK}", credentialsId: "12492eb8-0278-4402-98f0-4412abfb65c1" ]],
                                extensions: [
                                    [$class: "UserIdentity",name: "jenkins", email: "jenkins@jenkins"],
                                    [$class: 'PreBuildMerge', options: [fastForwardMode: 'FF', mergeRemote: "origin", mergeStrategy: 'DEFAULT', mergeTarget: "${env.gitlabTargetBranch}"]]
                                    ]
                            ])
                        }
                    }
                }
                stage('Build SDK and iOS'){
                    environment {
                        PATH = "/usr/local/bin:${env.PATH}"
                        LIBTOOLIZE = "/usr/local/bin/glibtoolize"
                    }
                    options{
                        timeout(time: 200, unit: 'MINUTES')
                    }
                    steps{
                        sh "bundle config set --local path 'vendor/bundle'"
                        sh "bundle install"
                        dir("${megachat_sources_workspace}/src"){
                            sh "cmake -P genDbSchema.cmake"
                        }
                        script {
                            if (params.IOS_REBUILD_3RDPARTY == "true") {
                                dir("${sdk_sources_workspace}/bindings/ios/3rdparty"){
                                    sh "sh build-all.sh --enable-chat"
                                }
                            }
                            else {
                                sh "bundle exec fastlane configure_sdk_and_chat_library use_cache:true"
                            }
                        }
                        withCredentials([gitUsernamePassword(credentialsId: 'jenkins_sdk_token_with_user', gitToolName: 'Default')]) {
                                sh "bundle exec fastlane update_plugins"
                                sh "bundle exec fastlane build_simulator"
                        }
                    }
                    post {
                        always {
                            sh "tar czvf buildlog.tar.gz buildlog/ || true"
                            archiveArtifacts artifacts: 'buildlog.tar.gz', allowEmptyArchive: true, onlyIfSuccessful: false
                        }
                    }
                }
            }
            post{
                always {
                    deleteDir()
                }
                failure {
                    node('linux') { // We need an agent able to download logs from Jenkins.
                        script {
                            commentFailedBuild()
                        }
                    }
                }
            }
        }
    }
    post {
        success {
            updateGitlabCommitStatus(name: 'Build iOS', state: 'success')
            addGitLabMRComment(comment: ":white_check_mark: ${currentBuild.projectName} :green_apple: <b>SDK iOS</b> SUCCEEDED :muscle:<br/>Build results: [Jenkins [${currentBuild.displayName}]](${currentBuild.absoluteUrl})<br/>Commit: ${COMMIT_ID}" )
        }
        unstable {
            updateGitlabCommitStatus(name: 'Build iOS', state: 'failed')
            addGitLabMRComment(comment: ":interrobang: ${currentBuild.projectName} :green_apple: <b>SDK iOS</b> UNSTABLE  :confused:<br/>Build results: [Jenkins [${currentBuild.displayName}]](${currentBuild.absoluteUrl})<br/>Commit: ${COMMIT_ID}" )      
        }
        aborted {
            updateGitlabCommitStatus(name: 'Build iOS', state: 'canceled')
            addGitLabMRComment(comment: ":interrobang: ${currentBuild.projectName} :green_apple: <b>SDK iOS</b> ABORTED  :confused:<br/>Build results: [Jenkins [${currentBuild.displayName}]](${currentBuild.absoluteUrl})<br/>Commit: ${COMMIT_ID}" )
        }
    }
}
