/*
* Licensed Materials - Property of IBM Corp.
* IBM UrbanCode Build
* IBM UrbanCode Deploy
* IBM UrbanCode Release
* IBM AnthillPro
* (c) Copyright IBM Corporation 2002, 2016. 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.websphereliberty;
import com.urbancode.air.CommandHelper;

public class WebSphereLibertyHelper extends AbstractWebSphereLibertyFileSystemHelper {
   def ch

   public WebSphereLibertyHelper(String wlpHome, String wlpUserDir=null) {
       super(wlpHome, wlpUserDir);
       ch = new CommandHelper(new File(".").canonicalFile);
   }

   public void deployViaDropins(String serverName, String source) {
       def serverDir = getServerDirectory(serverName);
       def toDir = new File(serverDir, "dropins");
       def ant = new AntBuilder();
       ant.copy(verbose:"true", todir:toDir, overwrite:"true", file: source, failonerror:"true");
   }

   public void uninstallViaDropins(String serverName, String sourceName) {
       System.out.println("Deleting application ${sourceName}");

       def serverDir = getServerDirectory(serverName);
       def dropinsDir = new File(serverDir, "dropins");
       def ant = new AntBuilder();
       ant.delete(verbose:"true", failonerror:"true", includeemptydirs:'true') {
           fileset(dir:dropinsDir.absolutePath, defaultexcludes:'false', followsymlinks: 'true') {
               include(name:"${sourceName}");
           }
       }
   }

   public String createCollective(String serverName, String keystorePassword, String optionalArgs, def isWindows) {
       File configFile = new File(getServerDirectory(serverName), "collectiveCreate_" + getDateTime() + ".xml");

       def options = "${optionalArgs} --keystorePassword=${keystorePassword} --createConfigFile=\"" + configFile.absolutePath + "\"";
       runCollectiveCommand(serverName, isWindows, "create", options, "Creating collective controller configuration for " + serverName);

       return configFile.absolutePath;
   }

   public String joinCollective(String serverName, String controllerHostName, String controllerPort, String adminUser, String adminPassword, String keystorePassword, String optionalArgs, def isWindows) {
       File configFile = new File(getServerDirectory(serverName), "collectiveJoin_" + getDateTime() + ".xml");

       def options = "${optionalArgs} --host=${controllerHostName} --port=${controllerPort} --user=${adminUser} --password=${adminPassword} --keystorePassword=${keystorePassword} --autoAcceptCertificates --createConfigFile=\"" + configFile.absolutePath + "\"";
       runCollectiveCommand(serverName, isWindows, "join", options, "Adding ${serverName} to Collective");

       return configFile.absolutePath;
   }

   public void registerHost(String hostToRegister, String controllerHostName, String controllerPort, String adminUser, String adminPassword, String rpcUser, String rpcUserPassword, String sshPrivateKey, String sshPrivateKeyPassword, String hostJavaHome, String hostReadPath, String hostWritePath, String optionalArgs, def isWindows) {
       def options = new StringBuffer();
       options.append("--host=${controllerHostName} --port=${controllerPort} --user=${adminUser} --password=${adminPassword} ");
       if (rpcUser?.trim()) {
           options.append("--rpcUser=${rpcUser} ");
       }
       if (sshPrivateKey?.trim()) {
           options.append("--sshPrivateKey=${sshPrivateKey} ");
       } else if (rpcUserPassword?.trim()) {
           options.append("--rpcUserPassword=${rpcUserPassword} ");
       } else {
           println("One authentication option(rpcUserPassword or sshPrivateKey) must be given.");
           System.exit(1);
       }
       if (sshPrivateKeyPassword?.trim()) {
           options.append("--sshPrivateKeyPassword=${sshPrivateKeyPassword} ");
       }
       if (hostJavaHome?.trim()) {
           options.append("--hostJavaHome=\"${hostJavaHome}\" ");
       }
       if (hostReadPath?.trim()) {
           hostReadPath.eachLine {
               options.append("--hostReadPath=\"${it}\" ");
           }
       }
       if (hostWritePath?.trim()) {
           hostWritePath.eachLine {
               options.append("--hostWritePath=\"${it}\" ");
           }
       }
       options.append("--autoAcceptCertificates ${optionalArgs}");
       runCollectiveCommand(hostToRegister, isWindows, "registerHost", options.toString(), "Registering ${hostToRegister} with Collective");
   }

   public void unregisterHost(String hostToUnregister, String controllerHostName, String controllerPort, String adminUser, String adminPassword, def isWindows) {
       def options = new StringBuffer();
       options.append("--host=${controllerHostName} --port=${controllerPort} --user=${adminUser} --password=${adminPassword} --autoAcceptCertificates");
       runCollectiveCommand(hostToUnregister, isWindows, "unregisterHost", options.toString(), "Unregistering ${hostToUnregister} from Collective");
   }

   public void updateHost(String hostToUpdate, String controllerHostName, String controllerPort, String adminUser, String adminPassword, String rpcUser, String rpcUserPassword, String sshPrivateKey, String sshPrivateKeyPassword, String hostJavaHome, String hostReadPath, String hostWritePath, String optionalArgs, def isWindows) {
       def options = new StringBuffer();
       options.append("--host=${controllerHostName} --port=${controllerPort} --user=${adminUser} --password=${adminPassword} ");
       if (rpcUser?.trim()) {
           options.append("--rpcUser=${rpcUser} ");
       }
       if (sshPrivateKey?.trim()) {
           options.append("--sshPrivateKey=${sshPrivateKey} ");
       } else if (rpcUserPassword?.trim()) {
           options.append("--rpcUserPassword=${rpcUserPassword} ");
       } else {
           println("One authentication option(rpcUserPassword or sshPrivateKey) must be given.");
           System.exit(1);
       }
       if (sshPrivateKeyPassword?.trim()) {
           options.append("--sshPrivateKeyPassword=${sshPrivateKeyPassword} ");
       }
       if (hostJavaHome?.trim()) {
           options.append("--hostJavaHome=${hostJavaHome} ");
       }
       if (hostReadPath?.trim()) {
           hostReadPath.eachLine {
               options.append("--hostReadPath=${it} ");
           }
       }
       if (hostWritePath?.trim()) {
           hostWritePath.eachLine {
               options.append("--hostWritePath=${it} ");
           }
       }
       options.append("--autoAcceptCertificates ${optionalArgs}");
       runCollectiveCommand(hostToUpdate, isWindows, "updateHost", options.toString(), "Updating ${hostToUpdate} with Collective");
   }

   public void createServer(String serverName, def isWindows) {
       runServerCommand(serverName, isWindows, "create", "Creating new server named " + serverName);
   }

   public boolean startServer(String serverName, def isWindows) {
       boolean started = false
       def checkServerStarted = { Process proc ->
           proc.out.close() // close   the stdIn  of the process
           proc.consumeProcessErrorStream(System.out) // forward the stdErr of the process
           proc.in.withReader{
                String line = null
                // on Windows machines it run indefinitely when started, so kick out if server starts
                while ((line = it.readLine()) != null && !started)  {
                    println line
                    if (line.startsWith("Server ${serverName} started") ||
                        line.startsWith("Server ${serverName} is already running")) {
                        started = true
                    }
                }
           }
       }
       ch.ignoreExitValue(true)
       runServerCommand(serverName, isWindows, "start", "Starting server named " + serverName, checkServerStarted)
       return started
   }

   public boolean stopServer(String serverName, def isWindows) {
       boolean stopped = false
       def checkServerStopped = { Process proc ->
           proc.out.close() // close   the stdIn  of the process
           proc.consumeProcessErrorStream(System.out) // forward the stdErr of the process
           proc.in.withReader{
                String line = null
                while ((line = it.readLine()) != null && !stopped)  {
                    println line
                    if (line.startsWith("Server ${serverName} stopped") ||
                        line.startsWith("Server ${serverName} is not running")) {
                        stopped = true
                    }
                }
           }
       }
       ch.ignoreExitValue(true)
       runServerCommand(serverName, isWindows, "stop", "Stopping server named " + serverName, checkServerStopped)
       return stopped
   }

   public void deleteServer(String serverName) {
       System.out.println("Deleting server ${serverName}");
       def serverDir = getServerDirectory(serverName);
       def ant = new AntBuilder();
       ant.delete(verbose:"true", failonerror:"true", includeemptydirs:'true') {
           fileset(dir:serverDir.parentFile.absolutePath, defaultexcludes:'false', followsymlinks: 'true') {
               include(name:"${serverName}/**/*");
               include(name:"${serverName}");
           }
       }
   }

   public void installServerArchive(String source, boolean license) {
       System.out.println("Unzipping server archive in : " + wlpHomeFile.absolutePath);
       String extension = ''
       int dotIndex = source.lastIndexOf('.')
       if (dotIndex >= 0) {
           extension = source.substring(dotIndex + 1)
       }
       if (extension.equals('jar')) {
           ArrayList args = ['java']
           args << '-jar'
           args << source
           if (license) {
               args << '--acceptLicense'
           }
           else {
               println ('[error]  Cannot extract jar file without accepting license.')
               println ('[possible solution]  Please update the step configuration by selecting "Accept License".')
               System.exit(1)
           }
           args << wlpHomeFile.absolutePath
           ch.runCommand('[action] Installing Liberty by extracting a Java archive file...', args)
       }
       else {
           def ant = new AntBuilder();
           ant.unzip(src:source, dest:wlpHomeFile.absolutePath);
       }
   }
}
