#!/usr/bin/env groovy
/*
* Licensed Materials - Property of IBM* and/or HCL**
* UrbanCode Deploy
* UrbanCode Build
* UrbanCode Release
* AnthillPro
* (c) Copyright IBM Corporation 2011, 2017. All Rights Reserved.
* (c) Copyright HCL Technologies Ltd. 2018. All Rights Reserved.
*
* U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
* GSA ADP Schedule Contract with IBM Corp.
*
* * Trademark of International Business Machines
* ** Trademark of HCL Technologies Limited
*/

import java.nio.charset.Charset
import java.util.UUID

import com.urbancode.air.AirPluginTool
import com.urbancode.commons.httpcomponentsutil.HttpClientBuilder
import com.urbancode.commons.util.IO
import com.ibm.uclab.csrepl.client.ops.Sync

import org.apache.http.impl.client.DefaultHttpClient
import org.apache.http.util.EntityUtils
import org.apache.http.client.methods.HttpGet
import org.apache.http.HttpResponse
import org.apache.http.HttpStatus
import org.codehaus.jettison.json.JSONArray
import org.codehaus.jettison.json.JSONObject

def apTool = new AirPluginTool(args[0], args[1])

def AGENT_HOME = new File(System.env['AGENT_HOME'])
def PROXY_HOST = System.env['PROXY_HOST']
def PROXY_PORT = System.env['PROXY_PORT']
if (PROXY_PORT != null) {
    PROXY_PORT = Integer.valueOf(PROXY_PORT)
}

def props = apTool.getStepProperties()

def fileIncludePatterns = props['fileIncludePatterns']
def fileExcludePatterns = props['fileExcludePatterns']
def resId = props['resId']
def serverURL = props['serverUrl']
def setFileExecuteBits = (props['setFileExecuteBits'] != null && Boolean.valueOf(props['setFileExecuteBits']))
def verifyFileIntegrity = (props['verifyFileIntegrity'] != null && props['verifyFileIntegrity'] == "true")
def charset = Util.getCharset(props)

def baseDirectory = new File("").canonicalFile

def includes = fileIncludePatterns?.readLines()
def excludes = fileExcludePatterns?.readLines()

//
// Validation
//

if (baseDirectory.isFile()) {
    throw new IllegalArgumentException("Base directory ${baseDirectory} is a file!")
}

Util.configureLogging()

def getVersions = {
    def url = serverURL
    while (url.endsWith("/")) {
        url = url.substring(0, url.length - 1)
    }
    def query =
        "rowsPerPage=100000&pageNumber=1" +
        "&orderField=dateCreated&sortType=desc" +
        "&filterFields=resourceId&filterValue_resourceId=${resId}" +
        "&filterType_resourceId=eq&filterClass_resourceId=String"
    def reqUrl = "${url}/rest/inventory/resourceInventory/table?${query}"

    def builder = new HttpClientBuilder()
    if (PROXY_HOST) {
        builder.setProxyHost(PROXY_HOST)
        builder.setProxyPort(PROXY_PORT)
    }
    builder.setUsername(apTool.getAuthTokenUsername())
    builder.setPassword(apTool.getAuthToken())
    builder.setPreemptiveAuthentication(true)

    String verifyServerIdentityString = System.getenv().get("UC_TLS_VERIFY_CERTS");
    Boolean trustAllCerts = Boolean.valueOf(verifyServerIdentityString);
    builder.setTrustAllCerts(!trustAllCerts);

    def client = builder.buildClient()

    def req = new HttpGet(reqUrl)
    def res = client.execute(req)
    def code = res.getStatusLine().getStatusCode()
    def content = EntityUtils.toString(res.getEntity())

    switch (code) {
    case 200:
        def ids = [] as Set
        def versions = []
        JSONArray records = new JSONObject(content).getJSONArray("records")
        for (int i = records.length() - 1; i >= 0; i--) {
            def record = records.getJSONObject(i)
            def version = record.getJSONObject("version")
            def id = UUID.fromString(version.getString("id"))
            def name = version.getString("name")
            if (!ids.contains(id)) {
                ids.add(id)
                versions.add([id: id, name: name])
            }
        }
        return versions
    default:
        def reason = res.getStatusLine().getReasonPhrase()
        println "Unexpected HTTP status getting resource inventory: ${code} ${reason}"
        System.exit(1)
    }
}
def versions = getVersions()
println "Syncing for versions: ${versions*.name}"

if (versions == null || versions.isEmpty()) {
    println 'No versions found in inventory. Skipping sync operation.';
}
else {
    def forceUseServerUrl = false
    def csClient = Util.getCodestationClient(
            serverURL,
            forceUseServerUrl,
            apTool.getAuthTokenUsername(),
            apTool.getAuthToken())

    def op = new Sync(csClient, baseDirectory, versions*.id)
    op.setIncludes(includes)
    op.setExcludes(excludes)
    op.setOutputCharset(charset)
    op.setSetExecuteBits(setFileExecuteBits)
    op.setVerifyFiles(verifyFileIntegrity)

    println "Syncing files in ${baseDirectory}"
    println "Including ${fileIncludePatterns}"
    println "Excluding ${fileExcludePatterns}"
    println ""
    println ""
    op.run()
}