/*
* Licensed Materials - Property of IBM* and/or HCL**
* UrbanCode Deploy
* (c) Copyright IBM Corporation 2002-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
*/
package com.urbancode.air.plugin.iisconfiguration.helper
import java.nio.charset.Charset
import com.urbancode.air.plugin.iisconfiguration.Globals

class FileUtilReplaceTokens {
    public FileUtilReplaceTokens(){

    }

    public run(def props, def offSetDir) {
        def workDir = new File('.').canonicalFile

        def propFileName = "replace_tokens.properties"
        def dirOffset = offSetDir?:'.'
        workDir = new File(workDir, dirOffset).canonicalPath
        def includes = "**/${Globals.CONFIG_FILE}"
        def excludes = ""
        def startDelimiter = props['tokenDelimiter']?:''
        def endDelimiter = props['tokenDelimiter']?:''
        def propertyPrefix = props['propertyPrefix']
        def envPropValues = props['envPropValues']
        def explicitTokens = props['explicitTokens']
        def customEncoding = props['customEncoding']
        def propFile = new File(workDir, propFileName)
        def propFileExists = false
        def encoding
        if (customEncoding) {
            try {
                encodingSupported = Charset.isSupported(customEncoding)
            }
            catch (IllegalArgumentException iae) {
                println ("[error]  Encoding type ${customEncoding} not valid.")
                println ('[possible solution]  Please update the step configuration with a valid encoding type.')
                System.exit(1)
            }
            if (!encodingSupported) {
                println ("[error]  Encoding type ${customEncoding} not supported.")
                println ('[possible solution]  Please update the step configuration with a supported encoding type.')
                System.exit(1)
            }
            else {
                encoding = customEncoding
            }
        }
        else {
            File AGENT_HOME;
            if (System.getenv().get("AGENT_HOME")){
                AGENT_HOME = new File(System.getenv().get("AGENT_HOME"))
            }
            if (AGENT_HOME) {
                final def agentInstalledProps = new File(AGENT_HOME, "conf/agent/installed.properties")
                final def agentProps = new Properties();
                try {
                    final def agentInputStream = new FileInputStream(agentInstalledProps);
                    agentProps.load(agentInputStream);
                }
                catch (IOException e) {
                    throw new RuntimeException(e);
                }
                encoding = agentProps['system.default.encoding']
            }
            else {
                encoding = Charset.defaultCharset().name()
            }
        }

        try {

            def Properties properties = new Properties()
            if (propFile.exists() && propFile.isFile()) {
                propFileExists = true
                println "Found existing input property file: ${propFile.canonicalPath}"
                def tempProps = new Properties()
                propFile.withInputStream { stream ->
                    tempProps.load(stream)
                }
                tempProps.each { k,v ->
                    properties.setProperty(startDelimiter + k + endDelimiter, v)

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

            if (explicitTokens) {
                explicitTokens.eachLine {
                    if (it && it.indexOf('->') > 0) {
                        def index = it.indexOf('->')
                        def propName = it.substring(0, index).trim()
                        def propValue = index < (it.length() - 2) ? it.substring(index + 2) : ""
                        properties.setProperty(propName, propValue)
                    }
                    else if (it) {
                        println "Found invalid explicit token $it - missing -> separator"
                    }
                }
            }

            if (!propFileName) {
                propFile = File.createTempFile("tmp", ".properties", new File(workDir))
                propFile.deleteOnExit()
                propFileName = propFile.getName()
            }

            propFile.withOutputStream { outStream ->
                properties.store(outStream, 'Auto generated property file')
            }

            properties.each { k,v ->
                println "added: $k:$v"
            }

            def ant = new AntBuilder()
            if (properties.size() > 0) {
                if (excludes) {
                    ant.replace(
                            dir:dirOffset,
                            summary: 'true',
                            replacefilterfile: propFile.canonicalPath,
                            includes: includes,
                            excludes: excludes,
                            encoding: encoding,
                            defaultexcludes: 'no')

                }
                else {
                    ant.replace(
                            dir:dirOffset,
                            summary: 'true',
                            replacefilterfile: propFile.canonicalPath,
                            includes: includes,
                            encoding: encoding,
                            defaultexcludes: 'no')
                }
            }
            else {
                println("Did not find any properties or explicit tokens for replacement including ${includes}.")
            }
        }
        catch (Exception e) {
            e.printStackTrace()
            println "Error replacing tokens!"
            if (propFile != null && !propFileExists) {
                propFile.delete()
            }
            System.exit(1)
        }
        finally {
            if (propFile != null && !propFileExists) {
                propFile.delete()
            }
        }
    }
}
