/*
* Licensed Materials - Property of IBM Corp.
* IBM UrbanCode Build
* (c) Copyright IBM Corporation 2017. All Rights Reserved.
*
* U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
* GSA ADP Schedule Contract with IBM Corp.
*/
import com.urbancode.air.*
import com.urbancode.air.plugin.scm.*

import com.urbancode.commons.httpcomponentsutil.CloseableHttpClientBuilder
import org.apache.http.client.methods.HttpPost
import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.impl.client.CloseableHttpClient
import org.apache.http.entity.StringEntity
import org.apache.http.HttpHeaders
import groovy.json.JsonBuilder

final def workDir = new File('.').canonicalFile
final def dateParser = new DateParser();
final def apTool = new AirPluginTool(this.args[0], this.args[1])
final def stepProps = apTool.getStepProperties();

//--------------------------------------------------------------------------------------------------
// Repo
//--------------------------------------------------------------------------------------------------
final String username   = stepProps['source/repo/username']
final String password   = stepProps['source/repo/password'] ?: stepProps['source/repo/passScript']

//--------------------------------------------------------------------------------------------------
// Source
//--------------------------------------------------------------------------------------------------
final String srcName                 = stepProps['source']
final String remoteUrl               = stepProps['source/remoteUrl']

//--------------------------------------------------------------------------------------------------
// Step
//--------------------------------------------------------------------------------------------------
final String stateValue              = stepProps['state']
final String descriptionValue        = stepProps['description']
final String contextValue            = stepProps['context']
final String baseRestUrl             = stepProps['baseRestUrl']
final String apiToken                = stepProps['apiToken']
final String sourceRevision          = stepProps['revision']

//--------------------------------------------------------------------------------------------------
// Buildlife
//--------------------------------------------------------------------------------------------------
final String blRevision              = stepProps["buildlife/workspace.revision.$srcName"]
final String statusesUrl             = stepProps["buildlife/gitHubStatusesUrl.$srcName"]

//--------------------------------------------------------------------------------------------------
// Environment
//--------------------------------------------------------------------------------------------------
final String externalWebUrl          = System.getenv('EXTERNAL_WEB_URL')
final String webUrl                  = System.getenv('WEB_URL')
final String blId                    = System.getenv('BUILD_LIFE_ID')

//--------------------------------------------------------------------------------------------------
// Configure revision
//--------------------------------------------------------------------------------------------------
final String revision
if (sourceRevision) {
    revision = sourceRevision
}
else {
    if (blRevision) {
        println("Revision has not been specified. Using the value of property workspace.revision.$srcName: $blRevision")
        revision = blRevision
    }
    else {
        println("Revision has not been specified in the step configuration, and the property " +
            "workspace.revision.$srcName is not set.")
        System.exit(1)
    }
}

// Configure target URL
String targetUrlValue
if (externalWebUrl) {
    if (externalWebUrl.endsWith('/')) {
        externalWebUrl = externalWebUrl.substring(0, externalWebUrl.length() - 1)
    }
    println("Using external web URL '" + externalWebUrl + "' to construct target URL")
    targetUrlValue = externalWebUrl
}
else if (webUrl) {
    if (webUrl.endsWith('/')) {
        webUrl = webUrl.substring(0, webUrl.length() - 1)
    }
    println("Using external agent URL '" + webUrl + "' to construct target URL")
    targetUrlValue = webUrl
}
else {
    println("Error: Neither external web URL nor external agent URL are defined")
    exit 1
}
targetUrlValue += '/tasks/project/BuildLifeTasks/viewBuildLife?buildLifeId=' + blId

//--------------------------------------------------------------------------------------------------
// Configure REST URL for updating GitHub statuses
//--------------------------------------------------------------------------------------------------
if (!remoteUrl) {
    println("Remote URL is null!")
    System.exit(1)
}
final String restUrl
if (baseRestUrl) {
    if (baseRestUrl.endsWith('/')) {
        baseRestUrl = baseRestUrl.substring(0, baseRestUrl.length() - 1)
    }
    if (remoteUrl.startsWith("/")) {
        remoteUrl = remoteUrl.substring(1, remoteUrl.length())
    }
    if (remoteUrl.endsWith("/")) {
        remoteUrl = remoteUrl.substring(0, remoteUrl.length()-1)
    }
    restUrl = baseRestUrl + "/repos/" + remoteUrl + "/statuses/" + revision
}
else {
    println("Base REST URL has not been specified. Using the Statuses URL from GitHub's webhook data: $statusesUrl")
    if (statusesUrl.endsWith('{sha}')) {
        restUrl = statusesUrl.replaceAll(/\{sha\}/, revision)
    }
    else {
        println("Expected statuses URL to end with placeholder '{sha}', but this was not the case: " + statusesUrl)
        System.exit(1)
    }
}

//--------------------------------------------------------------------------------------------------
// Perform step
//--------------------------------------------------------------------------------------------------
println "Revision: $revision"
println "State: $stateValue"
println "Target URL: $targetUrlValue"
println "Description: $descriptionValue"
println "Context: $contextValue"
println "REST URL: $restUrl"
println ""
println ""

CloseableHttpClientBuilder clientBuilder = new CloseableHttpClientBuilder()
boolean usingToken = true
if (apiToken == null || apiToken.size() == 0) {
    println "An API token has not been specified. Using repository credentials to authenticate"
    usingToken = false
    clientBuilder.setUsername(username)
    clientBuilder.setPassword(password)
    clientBuilder.setPreemptiveAuthentication(true)
}

CloseableHttpClient client
try {
    client = clientBuilder.buildClient()
    JsonBuilder jsonBuilder = new JsonBuilder()
    jsonBuilder {
        state stateValue
        target_url targetUrlValue
        description descriptionValue
        context contextValue
    }
    StringEntity entity = new StringEntity(jsonBuilder.toString(), "UTF-8")
    entity.setContentType("application/json")
    HttpPost request = new HttpPost(restUrl)
    request.setEntity(entity)
    if (usingToken) {
        request.addHeader(HttpHeaders.AUTHORIZATION, "token $apiToken")
    }
    CloseableHttpResponse response
    try {
        response = client.execute(request)
        def statusLine = response.getStatusLine()
        Integer statusCode = statusLine.getStatusCode()
        if (statusCode == 201) {
            println "Successfully created status!"
            println response.entity?.content?.text
        }
        else {
            println "Error: ${statusCode} - Message: ${response.entity?.content?.text}"
            System.exit(1)
        }
    }
    finally {
        if (response) {
            response.close()
        }
    }
}
finally {
    if (client) {
        client.close()
    }
}