/*
* 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 com.urbancode.air.AirPluginTool

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

def baseDir = props['baseDir']
def zipName = props['zipName']
def includes = props['includes']
def excludes = props['excludes']
def update = props['update']
def followSymlinks = props['followSymlinks']
def caseSensitive = props['caseSensitive']
def customEncoding = props['customEncoding']

println "Working Directory: ${new File('.').canonicalFile}"
println "Base Directory: $baseDir"
println "Zip file name: $zipName"
println "Include: $includes"
println "Exclude: $excludes"
println "Update : $update"
println "Follow Symlinks: $followSymlinks"
println "Case Sensitive: $caseSensitive"
println "Custom Encoding: $customEncoding"
println "================================="

boolean encodingSupported = false
if (customEncoding) {
    try {
        encodingSupported = Charset.isSupported(customEncoding)
    }
    catch (IllegalArgumentException iae) {
        println ("ERROR Encoding type ${customEncoding} not valid.")
        println ('USER_ACTION Please update the step configuration with a valid encoding type.')
        System.exit(1)
    }
    if (!encodingSupported) {
        println ("ERROR Encoding type ${customEncoding} not supported.")
        println ('USER_ACTION Please update the step configuration with a supported encoding type.')
        System.exit(1)
    }
}

/**
 * Get the File object for the given path.
 * If searchCaseInsensitive is true, then fallback attempts will be made to
 * match unique case-insensitive path elements. This is for treating the base
 * path as case-insensitive on a case-sensitive file system.
 */
File getBaseDir(String baseDir, boolean searchCaseInsensitive) {
    if (new File(baseDir).exists()) {
        return new File(baseDir)
    }
    if (!searchCaseInsensitive) {
        // no special handling needed
        return new File(baseDir);
    }

    List<File> pathComponents = []
    File curDir = new File(baseDir)
    while (curDir != null) {
        pathComponents.push(curDir)
        curDir = curDir.getParentFile()
    }

    File caseSensitivePath;
    if (!pathComponents.last().absolute) {
        caseSensitivePath = new File('.');
    }
    else {
        caseSensitivePath = pathComponents.pop();
    }

    // follow each segement in a case-insensitive manner
    while (!pathComponents.isEmpty()) {
        String nextSegmentName = pathComponents.pop().name
        if (nextSegmentName == '.') {
            // no-op
        }
        else if (nextSegmentName == '..') {
            // does not show in listFiles and is already case agnostic
            caseSensitivePath = new File(caseSensitivePath, nextSegmentName);
        }
        else {
            // match a regular segment
            File[] matchingDirs = caseSensitivePath.listFiles(new java.io.FileFilter() {
                boolean accept(File path) {
                    return path.name.equalsIgnoreCase(nextSegmentName)
                }
            })
            if (!matchingDirs) {
                throw new Exception("$baseDir does not exist!")
            }
            else if (matchingDirs.length > 1) {
                throw new Exception("Cannot resolve ambiguous path to $baseDir - enable case sensitivity. Mutiple path matches for: $matchingDirs")
            }
            caseSensitivePath = matchingDirs.first();
        }
    }
    println "Found alternatively cased path: $caseSensitivePath (original $baseDir)"
    return caseSensitivePath
}

try {
    def baseDirFile = getBaseDir(baseDir, !Boolean.valueOf(caseSensitive))
    if (baseDirFile.exists()) {
        def ant = new AntBuilder()
        if (encodingSupported) {
            ant.zip(destfile: zipName, update: update, encoding: customEncoding) {
                fileset(dir:baseDirFile.getPath(), casesensitive: caseSensitive, followsymlinks: followSymlinks, defaultexcludes: 'false') {
                    includes.split('[\r\n]').each {
                        if (it && it.trim().length() > 0) {
                            include(name: it.trim())
                        }
                    }
                    excludes?.split('[\r\n]')?.each {
                        if (it && it.trim().length() > 0) {
                            exclude(name: it.trim())
                        }
                    }
                }
            }
        }
        else {
            ant.zip(destfile: zipName, update: update) {
                fileset(dir:baseDirFile.getPath(), casesensitive: caseSensitive, followsymlinks: followSymlinks, defaultexcludes: 'false') {
                    includes.split('[\r\n]').each {
                        if (it && it.trim().length() > 0) {
                            include(name: it.trim())
                        }
                    }
                    excludes?.split('[\r\n]')?.each {
                        if (it && it.trim().length() > 0) {
                            exclude(name: it.trim())
                        }
                    }
                }

            }
        }
    }
    else {
        throw new Exception("$baseDir does not exist!")
    }
}
catch (Exception e) {
    println "Error creating zip archive: ${e.message}"
    System.exit(1)
}
