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

import java.nio.charset.Charset

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

Map tempDirs = new HashMap<String, File>()

final def airTool = new AirPluginTool(args[0], args[1])
final Properties props = airTool.getStepProperties()

// import teamserver .jar files
final String PLUGIN_HOME = System.getenv("PLUGIN_HOME")
String jarPath = props['jarPath']

if (jarPath) {
    while (jarPath.endsWith(File.separator)) {
        jarPath = jarPath.substring(0, jarPath.length() - 1)
    }
    println("[Info] Loading jrules jars into classpath from path: " + jarPath)
    loadAllJars(jarPath)
}
else {
    File jrulesengine = new File(PLUGIN_HOME + File.separator + 'lib' + File.separator + 'jrules-engine.jar')
    File jruleslanguage = new File(PLUGIN_HOME + File.separator + 'lib' + File.separator + 'jrules-language.jar')
    File jrulesartifacts = new File(PLUGIN_HOME + File.separator + 'lib' + File.separator + 'jrules-ruleartifacts.jar')
    File jrulesteamserver = new File(PLUGIN_HOME + File.separator + 'lib' + File.separator + 'jrules-teamserver.jar')
    if (!jrulesengine.exists() || !jruleslanguage.exists() || !jrulesartifacts.exists() || !jrulesteamserver.exists()) {
        println("[Error] If jar path is not specified, jrules-*.jars must be copied into the plugin '/lib' directory.")
        println("[Solution] Please specify a jar path to the jrules-*.jar locations, or copy them into the plugin lib directory.")
        System.exit(1)
    }
    else {
        println("[Info] Found jrules jars. Loading into classpath from plugin lib directory.")
    }
}
loadAllJars(PLUGIN_HOME + File.separator + 'lib')

private void loadAllJars(String directory) {
    File dir = new File(directory)
    if (!dir.isDirectory()) {
        println ("[Error] Directory ${dir.getAbsolutePath()} does not exist.")
        System.exit(1)
    }
    dir.list().each { child ->
        File childFile = new File(directory + File.separator + child)
        if (childFile.isDirectory()) {
            loadAllJars(childFile.getAbsolutePath())
        }
        def extension = ''
        def index = child.lastIndexOf('.')
        if (index && index > 0) {
            extension = child.substring(index + 1)
        }
        if (extension.equals('jar')) {
            if (childFile.isFile()) {
                this.getClass().classLoader.rootLoader.addURL(childFile.toURL())
            }
        }
    }
}

XTrustProvider.install()

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)
}

final File workDir = new File('.').canonicalFile

// clean working directory
for(File file: workDir.listFiles()) {
    if (!file.isDirectory()) {
        file.delete()
    }
}

String odmUrl = props['odmUrl'].trim()
String username = props['username'].trim()
String password = props['password']
String ruleAppName = props['ruleAppName'].trim()
boolean isUseVFS = Boolean.valueOf(props['isUseVFS'])
String componentName = props['componentName'].trim()
String datasource = props['datasource'].trim()
String snapshot = props['snapshot'].trim()
String namePattern = props['namePattern'].trim()
String nextNumberString = props['nextNumber'].trim()
Integer nextNumber

if (nextNumberString) {
    try {
        nextNumber = Integer.valueOf(nextNumberString)
    }
    catch (NumberFormatException e) {
        throw new RuntimeException("The configured next version number '"+
        nextNumberString+"' is not a valid integer.")
    }
}

String extensionsString = props['extensions']
String[] extensions = new String[0]
if (extensionsString) {
    extensions = extensionsString.split(',')
    for (int i = 0; i < extensions.size(); i++) {
        extensions[i] = extensions[i].trim()
    }
}

// Set up UCD server clients
String UDUsername = 'PasswordIsAuthToken'
String UDPassword = String.format('{\"token\": \"%s\"}', System.getenv('AUTH_TOKEN'))
URI ucdServerUrl = new URI(System.getenv('AH_WEB_URL'))
VersionClient versionClient = new VersionClient(ucdServerUrl, UDUsername, UDPassword)
ComponentClient componentClient = new ComponentClient(ucdServerUrl, UDUsername, UDPassword)

while (odmUrl.endsWith('/')) {
    odmUrl = odmUrl.substring(0, odmUrl.length() - 1)
}
URI odmRepoURI = new URI(odmUrl + '/teamserver')

//Download file to working directory to extract name information
AntBuilder ant = new AntBuilder()
ant.taskdef name: "ruleappExtractor", classname: "com.urbancode.air.plugin.odm.RuleAppExtractorTask"

println ("[Action] Extracting RuleApp from ${odmUrl}")
if (!snapshot) {
    if (nextNumberString && namePattern) {
        namePattern = namePattern + '-'
    }
    println ("[Action] Creating ODM snapshot (baseline): ${snapshot}")
    ant.ruleappExtractor(
            server: odmRepoURI.toString(),
            datasource: datasource,
            user: username,
            password: password,
            ruleapp: ruleAppName,
            baseline: namePattern + String.valueOf(nextNumber),
            fromBaseline: ''
            )
}
else {
    println ("[Action] Extracting from ODM snapshot (baseline): ${snapshot}")
    ant.ruleappExtractor(
            server: odmRepoURI.toString(),
            datasource: datasource,
            user: username,
            password: password,
            ruleapp: ruleAppName,
            baseline: '',
            fromBaseline: snapshot
            )
}

String versionName = ''
String extension = ''
String majorMinorVersion = ''

//Extract ruleAppExtractor file data to set version properties
if (workDir.listFiles().length > 1) {
    println ("[Error] Unexpected files in working directory: " + workDir.getAbsolutePath())
    System.exit(1)
}
workDir.list().each { child ->
    File ruleAppJarFile = new File(File.separator + child)
    versionName = ruleAppJarFile.name
    def index = child.lastIndexOf('.')
    if (index && index > 0) {
        extension = child.substring(index + 1)
    }
    if (!extension.equals('jar')) {
        println ("[Error] Unexpected file type extension: " + extension)
        System.exit(1)
    }
    else {
        versionName = versionName.replaceFirst(java.util.regex.Pattern.quote(ruleAppName+"-"), "")
        majorMinorVersion = versionName.substring(0, versionName.indexOf("-"))
        versionName = versionName.replaceAll(java.util.regex.Pattern.quote("."+extension), "")

        //rename jar file to more common name
        boolean rename = new File(ruleAppJarFile.name).renameTo(new File(ruleAppName + ".jar"))
        if (!rename) {
            println("[Warning] Failed to rename RuleApp jar file")
        }
    }
}

if (!snapshot && nextNumberString) {
    nextNumber++
}

def getTempDir = { version ->
    File result = tempDirs.get(version)
    if (result == null) {
        result = new File(System.getProperty('java.io.tmpdir'), UUID.randomUUID().toString())
        IO.mkdirs(result)
        tempDirs.put(version, result)
    }
    return result
}

def downloadFile = { version ->
    try {
        IO.copy(new File('.'), getTempDir(version))
        return getTempDir(version)
    }
    catch (Exception e) {
        System.err.println(String.format("Error downloading file: ", e.getMessage()))
    }
}

def downloadPackage = { version ->
    println ('\nAttempting to download Decision Center RuleApp jar...')
    UUID result = null
    File tempDir = null
    String[] includes = ['**/*'] as String[]
    String[] excludes = [] as String[]
    try {
        boolean preserveExecutePermissions = Boolean.valueOf(props['saveFileExecuteBits'])
        versions = componentClient.getComponentVersions(componentName.toString(), false)
        componentClient.updateSourceConfigProperty(componentName, "nextNumber", nextNumber.toString(), "", false)

        println ('Creating a new component version')
        String versionId = versionClient.createVersion(componentName, version.toString(), ' ').toString()
        airTool.setOutputProperty('VersionID', versionId)
        if (isUseVFS) {
            tempDir = downloadFile(version)
            versionClient.addVersionFiles(componentName, versionId, tempDir, '', includes, excludes, preserveExecutePermissions, true, charset, extensions)
            versionClient.setVersionProperty(versionName, componentName, 'ruleAppVersion', majorMinorVersion, false)
        } else {
            println (String.format('Not uploading version %s to CodeStation because using VFS was not selected.',
                    versionId))
        }
    }
    catch (Exception e) {
        println ("Error creating a new version: %s" + e.printStackTrace())
        System.exit(1)
    }
    finally {
        airTool.storeOutputProperties()
        try {
            if (tempDir != null && tempDir.exists()) {
                IO.delete(tempDir)
            }
        }
        catch (IOException e) {
            println ("Unable to delete download directory: " + e.getMessage())
        }
    }
    return result
}

downloadPackage(versionName)


