#!/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.file.Files;
import java.nio.file.attribute.PosixFileAttributeView;
import java.nio.file.attribute.PosixFileAttributes;
import java.nio.file.attribute.PosixFilePermissions;

import com.urbancode.air.AirPluginTool;
import com.urbancode.commons.util.ssl.XTrustProvider;
import com.urbancode.ud.client.ComponentClient;
import com.urbancode.commons.httpcomponentsutil.HttpClientBuilder;

import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.HttpRequest;

def ant = new AntBuilder()
def apTool = new AirPluginTool(this.args[0], this.args[1]);
def props = apTool.getStepProperties();

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

def flip = { file ->
    File tempFile = File.createTempFile("temp", "file");
    file.eachLine { line ->
       tempFile.append(line);
       tempFile.append(System.getProperty("line.separator"));
    }
    ant.copy(file:tempFile.getAbsolutePath(), tofile:file.getAbsolutePath(), overwrite:true);
    tempFile.delete();
}

def getPosixAttrs = { file ->
    if (file == null) {
        return null;
    }
    try {
        return Files.readAttributes(file.toPath(), PosixFileAttributes.class);
    }
    catch (Exception e) {
        return null;
    }
}

def setPosixAttrs = { file, attrs ->
    if (file == null || attrs == null) {
        return;
    }
    try {
        def view = Files.getFileAttributeView(file.toPath(), PosixFileAttributeView.class);
        view.setPermissions(attrs.permissions());
        view.setGroup(attrs.group());
    }
    catch (Exception e) {
    }
}

final def requestId = props['requestId'];
final def name = props['name'];

def propFile = File.createTempFile("prop.",".properties", workDir);
def propFileName = propFile.getName();
propFile.delete();
def includes = name;
def excludes = "";
def propertyPrefix ="";

def envPropValues = props['envPropValues'];
def startDelimiter = '@';
def endDelimiter = '@';

final def baseDirectory = new File('.')

if (baseDirectory.isFile()) {
    throw new IllegalArgumentException("Base directory ${baseDirectory} is a file!")
}
else if (!baseDirectory.isDirectory()) {
    throw new IllegalArgumentException("Base directory ${baseDirectory} does not exist!");
}

File finalDest = new File(baseDirectory, name);
if (finalDest.exists() && !finalDest.isFile()) {
    throw new IllegalArgumentException("File name ${name} already exists in ${baseDirectory} but is not a file!");
}
//
// Download the files
//

XTrustProvider.install()

println "Downloading file ${name} to ${baseDirectory}"

def weburl = System.getenv("AH_WEB_URL");
def username = apTool.getAuthTokenUsername();
def password = apTool.getAuthToken();
def componentClient = new ComponentClient(new URI(weburl), username, password);
HttpResponse response = componentClient.downloadConfigTemplateByRequest(requestId, name);

if (finalDest.isFile()) {
    println "File already exists ... Replacing ...";
    finalDest.delete();
}

finalDest << response.getEntity().getContent();

println "Download complete"


try {
    def posixAttrs = getPosixAttrs(finalDest);
    def Properties properties = new Properties()
    def outStream  = new FileOutputStream(propFile)
    if(envPropValues) {
       if (propertyPrefix) {
            println "Looking for properties starting with $propertyPrefix"
        }
        //this is jeffs magic regex to split on ,'s preceded by even # of \ including 0
        envPropValues.split("(?<=(^|[^\\\\])(\\\\{2}){0,8}),").each { prop ->
            //split out the name
            def parts = prop.split("(?<=(^|[^\\\\])(\\\\{2}){0,8})=",2);
            def propName = parts[0];
            def propValue = parts.size() == 2 ? parts[1] : "";
            //replace \, with just , and then \\ with \
            propName = propName.replace("\\=", "=").replace("\\,", ",").replace("\\\\", "\\")
            propValue = propValue.replace("\\=", "=").replace("\\,", ",").replace("\\\\", "\\")

            if ((!propertyPrefix || propName.startsWith(propertyPrefix))) {
                properties.setProperty(startDelimiter + propName + endDelimiter, propValue)
                println 'added: ' + startDelimiter + propName + endDelimiter + ':' + propValue
            }
        }
    }
    properties.store(outStream, 'Auto generated property file')
    outStream.close()

    if (properties.size() > 0) {
        println "Replacing tokens..."
        if (excludes) {
            ant.replace(
                    dir:".",
                    summary: 'true',
                    replacefilterfile: propFileName,
                    includes: includes,
                    excludes: excludes,
                    defaultexcludes: 'no')

        }   
        else {
            ant.replace(
                    dir:".",
                    summary: 'true',
                    replacefilterfile: propFileName,
                    includes: includes,
                    defaultexcludes: 'no')
        }   
        println "Token replacement complete"
    }   
    else {
        println 'No properties found to replace tokens for. No token replacement needed.'
    }  
    flip(finalDest);
    setPosixAttrs(finalDest, posixAttrs);
}
catch (Exception e) {
    println "Error replacing tokens!"
    e.printStackTrace()
    System.exit(1)
}
finally {
    if (propFile != null) {
        propFile.delete()
    }
}
