/*
* Licensed Materials - Property of IBM Corp.
* IBM UrbanCode Build
* IBM UrbanCode Deploy
* IBM UrbanCode Release
* IBM AnthillPro
* (c) Copyright IBM Corporation 2002, 2013. All Rights Reserved.
*
* U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
* GSA ADP Schedule Contract with IBM Corp.
*/
package com.urbancode.air.plugin.jboss.helper

public class JBossHelper {
    def pb = new ProcessBuilder(['echo'] as String[]).directory(new File('.').canonicalFile)
    def cmdArgs = []
    def scriptData
    def out = System.out
    def err = System.err

    public JBossHelper(def cmdArgsIn) {
        cmdArgs = cmdArgsIn
    }

    public JBossHelper(def cmdArgsIn, def scriptDataIn) {
        cmdArgs = cmdArgsIn
        scriptData = scriptDataIn
    }

    def runCommand(def message, Closure closure) {
        runCommand(message, null, closure)
    }
    
    def runCommand(def message, def timeout, Closure closure) {
        pb.command(cmdArgs as String[])
        pb.environment()['NOPAUSE'] = 'true'
        println()
        if (message) {
            println(message)
        }
        println("command: ${pb.command().join(' ')}")
        def proc = pb.start()
        def tOut = null
        def tErr = null
        def closureThread = null
        
        if (closure) {
            closureThread = Thread.start{ 
                closure(proc)
            }
        }
        else {
            proc.out.close()
            tOut = proc.consumeProcessOutputStream(this.out)
            tErr = proc.consumeProcessErrorStream(this.err)
        }
        
        if (timeout == null) {
            proc.waitFor()
        }
        else {
            proc.waitForOrKill(timeout)
        }

        closureThread?.join(5000)
        tOut?.join(5000)
        tErr?.join(5000)
        
        if (proc.exitValue()) {
            throw new Exception("Command failed with exit code: "+proc.exitValue())
        }
        return proc.exitValue()
        
    }

    def runStartCommand(def message, def timeout, def host, def port) {
        def builder = new com.urbancode.process.jdk7.ProcessBuilder(cmdArgs)
        def outputFile = new File("outputStartFile.txt")
        
        builder.redirectOutput(outputFile)
        builder.redirectInput(outputFile)
        builder.redirectError(outputFile)
        builder.start()
        
        def s = new Socket()
        def addr = new InetSocketAddress(host, port)
        
        try {
            s.connect(addr)
        }
        catch (IOException e) {
            System.out.println("Could not create Connection!")
        }
        finally {
            if (s != null) {
                if (s.isConnected()) {
                   println "The server is already running, exiting with success"
                   s.close()
                   System.exit(0)
                }
                else {
                    s.close()
                }
            }
        }
        
        def startTime = System.currentTimeMillis()
        def gotConnection = false        
        s = new Socket()
        addr = new InetSocketAddress(host, port)
        while (!gotConnection && System.currentTimeMillis() - startTime < timeout) {
            try {
                s.connect(addr)
                gotConnection = s.isConnected()
            }
            catch (IOException e) {
                System.out.println("Could not create Connection!")
            }
            finally {
                if (s != null) {
                    s.close()
                    s = new Socket()
                }
            }
        }
        
        if (!gotConnection) {
            throw new Exception("Server not started in a timely manner.")
        }
        else {
            println "Achieved a connection to the server. Server has been started"
        }
        
        System.exit(0)
    }
    
    def runUndeployCommand(def message) {
        def foundLines = false
        runCommand(message) {Process proc ->
            proc.out.close()

            proc.in.eachLine { line ->
                println line
                if (line && line.trim().length() > 0) {
                    foundLines = true
                }
            }

            proc.consumeProcessErrorStream(System.out)
        }

        if (foundLines) {
            println "Error: The application was not undeployed"
            System.exit(1)
        }
        else {
            println "Undeployment successful"
        }
    }
    
    def runDeployCommand(def message) {
        def foundLines = false
        runCommand(message) {Process proc ->
            proc.out.close()

            proc.in.eachLine { line ->
                println line
                if (line && line.trim().length() > 0) {
                    foundLines = true
                }
            }

            proc.consumeProcessErrorStream(System.out)
        }
    
        if (foundLines) {
            println "Error: The application was not deployed to the server"
            System.exit(1)
        }
        else {
            println "Deployment successful"
        }
    }
    
    def runStopCommand(def message) {
        def outputFile = new File("outputStopFile.txt")
        def baos = new ByteArrayOutputStream()
        def ps = new PrintStream(baos)
        def outcomeHit = false
    
        runCommand(message) {proc ->
                //outputFile.write(proc.getText())
                proc.consumeProcessOutputStream(ps)
                ps.flush()
                
        }
        
        println baos.toString()
        outputFile.write(baos.toString())
        
        for (line in outputFile.readLines()) {
            if (line.contains("outcome")) {
                outcomeHit = true
                if (!line.contains("success")) {
                    println "Could not shut down server. Check to see if your server is in standalone or domain mode"
                    System.exit(1)
                }
                else {
                    println "JBoss Server shut down successfully"
                }
            }
        }
        if (!outcomeHit) {
            println "Could not shut down the server. The server may not have been running"
            System.exit(1)
        }
    }
    
    def runSourceCommand(def message) {
        def foundErrors = false
        def errorMessage = ''
        runCommand(message) {Process proc ->
            proc.out.close()

            proc.in.eachLine { line ->
                println line
                if (line && line.trim().length() > 0) {
                    if (line.startsWith("JBAS")) {
                        foundErrors = true
                        errorMessage = "Error creating data source. Exiting"
                    }
                    if (line.startsWith("Unrecognized argument")) {
                        foundErrors = true
                        errorMessage = "Error creating data source, bad argument. Exiting"
                    }
                }
            }

            proc.consumeProcessErrorStream(System.out)
        }

        if (foundErrors) {
            println errorMessage
            System.exit(1)
        }
        else {
            println "Data source created"
        }
    }
    
    def runQueueCommand(def message) {
        def foundLines = false
        runCommand(message) {Process proc ->
            proc.out.close()

            proc.in.eachLine { line ->
                println line
                if (line && line.trim().length() > 0) {
                    foundLines = true
                }
            }

            proc.consumeProcessErrorStream(System.out)
        }

        if (foundLines) {
            println "Error: The Queue/Topic could not be created"
            System.exit(1)
        }
        else {
            println "Queue/Topic creation successful"
        }
    }
    
        
    def runFactoryCommand(def message) {
        def foundLines = false
        runCommand(message) {Process proc ->
            proc.out.close()

            proc.in.eachLine { line ->
                println line
                if (line && line.trim().length() > 0) {
                    foundLines = true
                }
            }

            proc.consumeProcessErrorStream(System.out)
        }

        if (foundLines) {
            println "Error: The factory could not be created/deleted"
            System.exit(1)
        }
        else {
            println "Factory management successful"
        }
    }
    
    def runServerCommand(def message) {
        def foundErrors = false
        def foundOutcome = false
        runCommand(message) {Process proc ->
            proc.out.close()

            proc.in.eachLine { line ->
                println line
                if (line && line.trim().length() > 0) {
                    if (line.contains("outcome")) {
                        foundOutcome = true
                        if (!line.contains("success")) {
                            foundErrors = true
                        }
                    }
                }
            }

            proc.consumeProcessErrorStream(System.out)
        }

        if (foundErrors || !foundOutcome) {
            println "Could not create server group/server."
            System.exit(1)
        }
        else {
            println "Server Group/Server created successfully."
        }
    }
    
    def runRestartServerGroupsCommand(def message, def timeout) {
        def foundErrors = false
        def foundOutcome = false
        def startTime = System.currentTimeMillis()        
        
        runCommand(message, timeout) { Process proc ->
            proc.out.close()

            proc.in.eachLine { line ->
                println line
                if (line && line.trim().length() > 0) {
                    if (line.contains("outcome")) {
                        foundOutcome = true
                        if (!line.contains("success")) {
                            foundErrors = true
                        }
                    }
                    else if (line.contains("not a valid")) {
                        foundErrors = true
                    }
                }
            }
        }
        
        if (foundErrors || !foundOutcome) {
            println "Could not restart all specified server groups."
            System.exit(1)
        }
        else {
            println "Server Group restarted successfully."
        }
    }

            
    def runScriptCommand(def message) {
        runCommand(message, null)
    }

    def runDisableCommand(def message) {
        def foundLines = false
        runCommand(message) {Process proc ->
            proc.out.close()

            proc.in.eachLine { line ->
                println line
                if (line && line.trim().length() > 0) {
                    foundLines = true
                }
            }

            proc.consumeProcessErrorStream(System.out)
        }

        if (foundLines) {
            println "Error: The application was not disabled"
            System.exit(1)
        }
        else {
            println "Disabled successful"
        }
    }

    def createTempFile() {
        def tmpFile = File.createTempFile('ud-jboss-', '.cli')
        tmpFile.deleteOnExit()
        return tmpFile
    }
}
