/**
* Licensed Materials - Property of IBM* and/or HCL**
* IBM UrbanCode Deploy
* (c) Copyright IBM Corporation 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 com.urbancode.air.plugin.webspherebpm.Snapshot
import com.urbancode.air.plugin.webspherebpm.WebSphereBPMRestAPIHelper
import com.urbancode.air.AirPluginTool
import com.urbancode.commons.util.IO
import com.urbancode.ud.client.ComponentClient
import com.urbancode.ud.client.VersionClient

import java.nio.charset.Charset
import java.util.ArrayList
import java.util.List
import javax.net.ssl.SSLHandshakeException

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

def props = apTool.getStepProperties()

String serverUrl = props['serverUrl'].trim()
String procApp   = props['procApp'].trim()
String track     = props['track'].trim()
String username  = props['username'].trim()
String password  = props['password']
String snapshotName = props['snapshotName'].trim()
boolean trustAllCerts  = Boolean.valueOf(props['trustAllCerts'])

String componentName = props['componentName']
boolean isUseVFS = Boolean.valueOf(props['isUseVFS'])
boolean preserveExecutePermissions = Boolean.valueOf(props['saveFileExecuteBits'])

Properties agentProps = new Properties()
agentProps.load(new FileInputStream(new File(System.getenv("AGENT_HOME"),
        "conf/agent/installed.properties")))
String charsetName = agentProps.getProperty("system.default.encoding")
Charset charset = null
if (charsetName != null) {
    charset = Charset.forName(charsetName)
}

String UDUsername = "PasswordIsAuthToken"
String UDPassword = String.format("{\"token\": \"%s\"}", System.getenv("AUTH_TOKEN"))

String webUrl = System.getenv("AH_WEB_URL")
URI url = new URI(webUrl)

VersionClient versionClient = new VersionClient(url, UDUsername, UDPassword)
ComponentClient componentClient = new ComponentClient(url, UDUsername, UDPassword)

WebSphereBPMRestAPIHelper helper = new WebSphereBPMRestAPIHelper(serverUrl, username, password, trustAllCerts)
try {
    // Gather complete Process Applications list and parse to the desired Process Application (json)
    def processAppJson = helper.getProcessApp(procApp)

    // Process Application not found
    if (!processAppJson) {
        throw new RuntimeException("[Error] Unable to find Process Application `${procApp}`")
    }

    // Gather list of snapshots (aka versions)
    List<Snapshot> installedSnapshots = new ArrayList<Snapshot>()
    for (def snapshotJson : processAppJson?.installedSnapshots) {
        installedSnapshots.add(new Snapshot(snapshotJson))
    }

    // End if no snapshots are found
    if (installedSnapshots.size()) {

        // Gather all known UCD component versions
        List<String> versions = componentClient.getComponentVersions(componentName, false)
        List<String> archivedVersions = componentClient.getArchivedComponentVersions(componentName)
        versions.addAll(archivedVersions)

        // Identify snapshots to import
        List<Snapshot> importVersions = new ArrayList<Snapshot>()
        // If snapshot was specified during manual import
        if (snapshotName) {
            installedSnapshots.each{ it ->
                if (it.getName() == snapshotName || it.getAcronym() == snapshotName) {
                    if (!track || track == it.getBranchName()) {
                        importVersions.add(it)
                    }
                }
            }

            // Error if specified version is not found
            if (!importVersions.size()) {
                throw new Exception("[Error] Specified Snapshot name `${snapshotName}` could not be found!")
            }
        // Automated import or empty manual import
        } else {
            installedSnapshots.each{ it ->
                if (!track || track == it.getBranchName()) {
                    importVersions.add(it)
                }
            }
        }

        List<Snapshot> removeSnapshots = new ArrayList<Snapshot>()
        for (String version : versions) {
            for (Snapshot importVersion : importVersions) {
                if (version == importVersion.getVersionName()) {
                    removeSnapshots.add(importVersion)
                }
            }
        }
        importVersions.removeAll(removeSnapshots)

        // End if no new snapshots are found
        if (importVersions.size()) {
            println "[Info] Found new `$procApp` Snapshot version(s): ${importVersions*.getVersionName().toString()}"

            // Default includes, excludes, and extensions. Only one file to export from Websphere BPM
            String[] includes = ["export.twx"] as String[]
            String[] excludes = [] as String[]
            String[] extensions = [""] as String[]

            // Iterate through all versions, create new component versions, and download export.zip
            for (Snapshot importVersion : importVersions) {
                println ""
                println "[Action] Creating version: `${importVersion.getVersionName()}`"

                // Create version and add files
                if (isUseVFS) {
                    String projectId  = processAppJson.ID
                    File tempDir = null
                    try {
                        tempDir = helper.downloadSnapshotTWX(projectId, importVersion.getID())
                        String versionId = versionClient.createAndAddVersionFiles(componentName, importVersion.getVersionName(),
                                "", tempDir, "", includes, excludes, preserveExecutePermissions, true, charset, extensions).toString()
                        apTool.setOutputProperty("VersionID", versionId)
                    } finally {
                        // Delete temporary download folder
                        try {
                            if (tempDir != null && tempDir.exists()) {
                                IO.delete(tempDir)
                            }
                        }
                        catch (IOException e) {
                            System.err.println(String.format("[Error] Unable to delete download directory", e.getMessage()))
                        }
                    }
                // Create version only
                } else {
                    String versionId = versionClient.createVersion(componentName, importVersion.getVersionName(), " ").toString()
                    apTool.setOutputProperty("VersionID", versionId)
                    println "[Info] Not uploading artifact(s) to VFS."
                }

                // Set three output properties. Useful for the WebSphere BPM automation plugin
                try {
                    versionClient.setVersionProperty(importVersion.getVersionName(), componentName, "procAppAcronym", processAppJson.shortName, false)
                    versionClient.setVersionProperty(importVersion.getVersionName(), componentName, "snapshotAcronym", importVersion.getAcronym(), false)
                    versionClient.setVersionProperty(importVersion.getVersionName(), componentName, "trackAcronym", importVersion.getBranchName(), false)
                } catch (IOException ex) {
                    println ""
                    println "[Warn] Unable to assign 'procAppAcronym', 'snapshotAcronym', and 'trackAcronym' " +
                        "component version properties. Manually create these properties in the " +
                        "Version Properties Definitions section of the `${componentName}` component's configuration tab."
                }
            }

            println ""
            println "Import(s) completed successfully!"
        } else {
            println "[Info] No new Snapshots found."
        }
    } else {
        println "[Info] No Snapshots found for Process Application `${procApp}`"
    }
} catch (SSLHandshakeException ex) {
    throw new Exception("[Error] Certificate is invalid. Select " +
        "the `Trust All Certificates` checkbox for a temporary solution.", ex)
} finally {
    helper.closeClient()
    apTool.setOutputProperties()
}
