#!/usr/bin/env groovy
/*
 * Licensed Materials - Property of IBM Corp.
 * IBM UrbanCode Release
 * (c) Copyright IBM Corporation 2014. All Rights Reserved.
 *
 * U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
 * GSA ADP Schedule Contract with IBM Corp.
 */

import groovy.json.JsonSlurper
import groovy.json.JsonException

import java.util.Date

import org.apache.http.util.EntityUtils
import org.apache.http.client.HttpClient
import org.apache.http.client.methods.HttpGet
import org.apache.http.client.utils.URIBuilder
import org.apache.http.HttpEntity
import org.apache.http.HttpResponse
import org.apache.http.HttpStatus
import org.apache.commons.lang3.StringUtils

import com.urbancode.commons.httpcomponentsutil.HttpClientBuilder
import com.urbancode.air.XTrustProvider
import com.urbancode.air.AirPluginTool

XTrustProvider.install()

def apTool = new AirPluginTool(this.args[0], this.args[1])
def props = apTool.getStepProperties()

def host = props['releaseUrl']
def username = props['releaseUser']
def password = props['releasePassword']
def snapId = props['snapshotId']
def lifecycle = props['lifecycleName']
def phase = props['phaseName']
def timeout = props['timeout']

snapUId = null
try {
    snapUId = UUID.fromString(snapId)
}
catch (IllegalArgumentException iae) {
    println ('ERROR Snapshot ID "' + snapId + '" is not a valid UUID. Please update the step configuration with a valid UUID.')
    System.exit(1)
}
String url = prepareUrl(host, lifecycle, phase, snapId)
HttpClient client = prepareClient(username, password)
int exitValue = checkGates(url, client, timeout, apTool)
apTool.setOutputProperties()
System.exit(exitValue)

private String prepareUrl (host, lifecycle, phase, snapId) {
    // Format host
    while (host.endsWith('/')) {
        host = host.substring(0, host.length() - 1)
    }

    // Create URL
    URIBuilder uri = new URIBuilder(host)
    uri.setPath('/lifecycles/' + lifecycle + '/' + phase + '/snapshotPassesGatesByExternalId/' + snapId)
    String url = uri.toString()

    return url
}

private HttpClient prepareClient (username, password) {
    // Build HTTP client
    HttpClientBuilder builder = new HttpClientBuilder()
    builder.setTrustAllCerts(true)

    // Add credentials if present
    if (username != null && password != null) {
        builder.setUsername(username)
        builder.setPassword(password)
        builder.setPreemptiveAuthentication(true)
    }

    return builder.buildClient()
}

private int checkGates (url, client, timeout, apTool) {
    // Prepare for contact
    HttpGet get = new HttpGet(url)
    HttpResponse response = null
    String body = null
    boolean responseOk = false
    boolean timeoutReached = false
    def startTime = new Date().time

    // Try to contact server
    while (!responseOk && !timeoutReached) {
        println ('ACTION Checking lifecycle gate in UrbanCode Release...')
        response = client.execute(get)
        body = response.entity?.content?.text
        if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
            responseOk = true
        }
        else {
            println ('ERROR Check failed: response code ' + response.getStatusLine().getStatusCode() + ' - ' + body)
            def duration = (new Date().time - startTime) / 1000
            if (!StringUtils.isNumeric(timeout)) {
                timeoutReached = true
                println ('ERROR The value of the Timeout property is not numeric. Please update the step configuration with a numeric value for Timeout.')
                apTool.setOutputProperty('Error', 'Invalid Timeout')
                return 1
            }
            else if (duration > timeout.toInteger()) {
                timeoutReached = true
                println ('ERROR Reached Timeout before successful connection.')
            }
            else {
                sleep 500
                println ('ACTION Checking again...')
            }
        }
    }

    if (!responseOk) {
        apTool.setOutputProperty('Error', 'Timeout Exceeded')
        return 1
    }
    else {
        // Process response
        if (body != null) {
            def slurper = new JsonSlurper()
            def result = null
            try {
                result = slurper.parseText(body)
            }
            catch (JsonException jse) {
                println ('ERROR converting response to JSON.')
                println ('Response: ' + body)
                apTool.setOutputProperty('Error', 'Invalid JSON')
                return 1
            }

            if (result.passesGates) {
                println ('OK Gates Passed')
                return 0
            }
            else {
               println ('ERROR Gate Failed')
               apTool.setOutputProperty('Error', 'Gate Failed')
               return 1
            }
        }
        else {
            println ('ERROR Response Body Empty')
            apTool.setOutputProperty('Error', 'Response Body Empty')
            return 1
        }
    }
}