import com.urbancode.air.AirPluginTool
import com.urbancode.shell.Shell

final def workDir = new File('.').canonicalFile
final String osName = System.getProperty('os.name').toLowerCase(Locale.US)
final boolean windows = (osName =~ /windows/)
final File PLUGIN_HOME = new File(System.getenv().get("PLUGIN_HOME"))
def pluginTool = new AirPluginTool(args[0], args[1])
final def props = pluginTool.getStepProperties()

def launcher = props['launcherLocation']
def options = props['options']
def hostname = props['hostname']?:'localhost'
def port = props['port'] == "" ? null : props['port'].toInteger()
def timeout = props['timeout'] == "" ? null : props['timeout'].toInteger()
def catalinaHome = props['catalinaHome']
def catalinaBase = props['catalinaBase']
def javaHome = props['javaHome']

println "Startup script: $launcher"
println "Startup options: ${options?.split('\n')?.collect {it}}"
println "Timeout: ${timeout?:''}"
println "Hostname: ${hostname?:''}"
println "Port: ${port?:''}"
println "Catalina Base: ${catalinaBase?:''}"
println "Catalina Home: ${catalinaHome?:''}"
println "Java Home: ${javaHome?:''}"

def String getArch() {
    String result
    String arch = System.getProperty("os.arch").toLowerCase(Locale.US)

    if (arch.indexOf("amd64") > -1 || arch.indexOf("x64") > -1 || arch.indexOf("x86_64") > -1) {
        result = "x64"
    }
    else if (arch.indexOf("x86") > -1 || arch.indexOf("386") > -1 || arch.indexOf("486") > -1 ||
             arch.indexOf("586") > -1 || arch.indexOf("686") > -1 || arch.indexOf("pentium") > -1) {
        result = "x86"
    }
    else if (arch.indexOf("ia64") > -1 || arch.indexOf("itanium") > -1 || arch.indexOf("ia-64") > -1) {
        result = "ia64"
    }
    else if (arch.indexOf("ppc") > -1 || arch.indexOf("powerpc") > -1) {
        result = "ppc"
    }
    else if (arch.indexOf("sparc") > -1) {
        result = "sparc"
    }
    else if (arch.indexOf("parisc") > -1 || arch.indexOf("pa_risc") > -1 || arch.indexOf("pa-risc") > -1) {
        result = "parisc"
    }
    else if (arch.indexOf("alpha") > -1) {
        result = "alpha"
    }
    else if (arch.indexOf("mips") > -1) {
        result = "mips"
    }
    else if (arch.indexOf("arm") > -1) {
        result = "arm"
    }
    else {
        result = "unknown"
    }
    return result
}

def startTomcat = { commandArray ->
    // we need to use Shell with daemon option because of Windows and maybe some custom *nix startup scripts that
    // do not close file handles.
    def shell = new Shell(commandArray as String[])
    shell.workingDirectory = workDir
    shell.daemon = true
    def outFile = File.createTempFile('tomcat-start', 'tmp')
    shell.outputFile = outFile
    if (javaHome) {
        shell.addEnvironmentVariable('JAVA_HOME', javaHome)
    }
    if (catalinaBase) {
        shell.addEnvironmentVariable('CATALINA_BASE', catalinaBase)
    }
    if (catalinaHome) {
        shell.addEnvironmentVariable('CATALINA_HOME', catalinaHome)
    }
    shell.execute()

    //try to show some output to help troubleshooting abnormal terminations
    sleep(5000)
    try {
        println "---------------------------"
        def fileSize = outFile.size()
        def buffer
        while (fileSize > 0) {
            buffer = outFile.readBytes()
            print new String(buffer)
            fileSize -= buffer.length
        }
        println "---------------------------"

    }
    catch (Exception e){
    }
    finally{
        outFile.deleteOnExit()
    }
}

if (windows) {
    def arch = getArch()
    def libraryPath = new File(PLUGIN_HOME, "lib/native/${arch}/WinAPI.dll")
    System.setProperty("com.urbancode.winapi.WinAPI.dllPath", libraryPath.absolutePath)
}

if (timeout && !port) {
    println "Port is required when timeout is specified"
    System.exit 1
}

def cmdArgs = [launcher];
if (options) {
    for (String option : options.split('\n')) {
        cmdArgs << option.trim();
    }
}

if (port && timeout) {
    println 'Check if Tomcat is already running...'
    try {
        def socket = new Socket(hostname, port)
        done = true
        try {
            socket.close()
        }
        catch (Exception e) {}
        println 'already running - done.'
    }
    catch (UnknownHostException uhe) {
        println uhe.message
        System.exit 1
    }
    catch (IllegalArgumentException iae) {
        println iae.message
        System.exit 1
    }
    catch (ConnectException ce) {
        println 'not running - starting...'
        println "Executing " + cmdArgs.join(' ')
        startTomcat cmdArgs

        def endTime = System.currentTimeMillis() + (timeout * 1000)
        def done = false
        println 'Waiting for Tomcat boot process to complete...'

        while (!done && System.currentTimeMillis() < endTime) {
            try {
                socket = new Socket(hostname, port)
                done = true
                try {
                    socket.close()
                }
                catch (Exception e) {}
            }
            catch (UnknownHostException uhee) {
                println uhee.message
                System.exit 1
            }
            catch (IllegalArgumentException iaee) {
                println iaee.message
                System.exit 1
            }
            catch (ConnectException cee) {
                try {
                    sleep(1000)
                }
                catch (InterruptedException ie) {
                    println 'Sleep interrupted!'
                    System.exit 1
                }
            }
        }

        if (done) {
            println 'done.'
        }
        else {
            println 'failed - instance did not start in alloted time.'
            System.exit 1
        }
    }
}
else {
    println "Executing " + cmdArgs.join(' ')
    startTomcat cmdArgs
    println 'Timeout and/or port not specified so not waiting for Tomcat boot process to complete.'
}

System.exit 0
