/**
 * Licensed Materials - Property of IBM* and/or HCL**
 * 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 java.nio.charset.Charset
import java.util.HashMap
import java.io.IOException

import com.urbancode.air.AirPluginTool
import com.urbancode.commons.util.IO
import com.urbancode.ud.client.ComponentClient
import com.urbancode.ud.client.VersionClient

import com.urbancode.plugins.nuget.NuGetHelper
import com.urbancode.plugins.nuget.NuGetVersion

AirPluginTool apTool = new AirPluginTool(this.args[0], this.args[1])
Properties inProps = apTool.getStepProperties()

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

String nuGetHost = inProps['nuGetHost'].trim()
String nuGetPackage = inProps['nuGetPackage'].trim()
String username  = inProps['user'].trim()
String password  = inProps['password']
String proxyHost = inProps['proxyHost']?.trim()
int proxyPort    = inProps['proxyPort']?.trim() ? Integer.parseInt(inProps['proxyPort'].trim()) : -1
String proxyUser = inProps['proxyUser']?.trim()
String proxyPass = inProps['proxyPass']?.trim()
boolean trustAllCerts = Boolean.parseBoolean(inProps['trustAllCerts'])

boolean isUseVFS = Boolean.parseBoolean(inProps['isUseVFS'])
boolean preserveExecutePermissions = Boolean.valueOf(inProps['saveFileExecuteBits'])
boolean extensions = Boolean.parseBoolean(inProps['extensions'])

String nuGetVersionName  = inProps['versionName']?.trim()
String nuGetVersion = inProps['version']?.trim()

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

String webString = System.getenv('AH_WEB_URL')
URI webUrl = new URI(webString)

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

NuGetHelper nh = new NuGetHelper(nuGetHost, nuGetPackage, username, password, proxyHost, proxyPort,
    proxyUser, proxyPass, trustAllCerts)

try {
    List<NuGetVersion> nvList = nh.getVersionList()

    if (nvList.size() > 0) {

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

        // Retrieve specified version
        if (nuGetVersion) {
            List<NuGetVersion> newNvList = new ArrayList<NuGetVersion>()
            nvList.each { nv ->
                if (nv.version == nuGetVersion) {
                    nv.name = nuGetVersionName
                    newNvList.add(nv)
                }
            }

            // Should never be thrown
            if (newNvList.size() > 1) {
                throw new Exception("[Error] Found ${newNvList.size()} '${nuGetVersion}' versions when " +
                    "a single version was expected.");
            } else if (newNvList.size() == 0) {
                throw new Exception("[Error] Unable to find '${nuGetVersion}' version. " +
                    "Identified NuGet version(s): ${nvList*.version}");
            }

            nvList = newNvList

        }

        // Remove all previously imported versions
        List<NuGetVersion> removeNv = new ArrayList<NuGetVersion>()
        for (NuGetVersion nv : nvList) {
            for (String v : versions) {
                if (nv.getName() == v) {
                    removeNv.add(nv)
                }
            }
        }
        nvList.removeAll(removeNv)


        if (nvList.size() > 0) {

            // Default includes, excludes, and extensions. Only one file to export from NuGet repos
            String[] includes = ["*.nupkg"] as String[]
            String[] excludes = [] as String[]
            String[] extensionsList = [""] as String[]
            if (extensions) {
                extensionsList = [".nupkg"] as String[]
            }

            println "[Info] Found ${nvList.size()} new version(s)!"
            for (NuGetVersion nv : nvList) {
                println ""
                println "[Action] Creating version: `${nv.getName()}`"

                // Create version and add files
                if (isUseVFS) {
                    File tempDir = null
                    try {
                        tempDir = nh.download(nv)
                        String versionId = versionClient.createAndAddVersionFiles(componentName, nv.getName(),
                                "", tempDir, "", includes, excludes, preserveExecutePermissions, true, charset, extensionsList).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, nv.getName(), " ").toString()
                    apTool.setOutputProperty("VersionID", versionId)
                    println "[Info] Not uploading artifact(s) to VFS."
                }

                // Set output properties.
                try {
                    versionClient.setVersionProperty(nv.getName(), componentName, "id", nv.id, false)
                    versionClient.setVersionProperty(nv.getName(), componentName, "pkgTitle", nv.pkgTitle, false)
                    versionClient.setVersionProperty(nv.getName(), componentName, "title", nv.title, false)
                    versionClient.setVersionProperty(nv.getName(), componentName, "updated", nv.updated, false)
                    versionClient.setVersionProperty(nv.getName(), componentName, "content", nv.content, false)
                    versionClient.setVersionProperty(nv.getName(), componentName, "description", nv.description, false)
                    versionClient.setVersionProperty(nv.getName(), componentName, "version", nv.version, false)
                    versionClient.setVersionProperty(nv.getName(), componentName, "filename", isUseVFS ? nv.getFilename() : "", false)
                } catch (IOException ex) {
                    println ""
                    println "[Warn] Unable to assign 'id', 'pkgTitle', 'title', 'updated', 'content', " +
                        "'description', 'version', and 'filename' component version properties. Manually create these properties in the " +
                        "Version Properties Definitions section of the `${componentName}` component's configuration tab " +
                        "or allow the `UC Version Import` role to Manage Properties under Component permissions."
                }
            }
            println ""
            println "[Info] Import(s) successful!"
        } else {
            println "[Info] No new NuGet Versions found."
        }

    } else {
        println "[Error] Unable to find list of NuGet Versions."
        System.exit(1)
    }
} finally {
    nh.closeClient()
}
