/**
 *#########################################################################
 *
 * A component of the Gatherer application, part of the Greenstone digital
 * library suite from the New Zealand Digital Library Project at the
 * University of Waikato, New Zealand.
 *
 * <BR><BR>
 *
 * Author: Sam McIntosh, Greenstone Digital Library, University of Waikato
 *
 * <BR><BR>
 *
 * Copyright (C) 2011 New Zealand Digital Library Project
 *
 * <BR><BR>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * <BR><BR>
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * <BR><BR>
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *########################################################################
 */

package org.greenstone.gatherer.util;

import org.greenstone.gatherer.Configuration;
import org.greenstone.gatherer.DebugStream;

import java.io.File;

/** Class for GS3, for issuing ant commands from GLI */
public class GS3ServerThread extends Thread
{
    String _gsdl3_src_path = "";
    String _ant_command = "";

    // isIndependentServer is true if tomcat was already running when GLI was started up
    // in which case GLI doesn't need start tomcat itself, nor should it need to stop the server on exit
    static private final boolean isIndependentServer = GS3ServerThread.isServerRunning();
    
    public GS3ServerThread(String gsdl3_src_path, String ant_command)
    {
	_gsdl3_src_path = gsdl3_src_path;
	_ant_command = ant_command; // "restart"	
    }
    

    public void run()
    {
	///System.err.println("**** GS3 server : " + _ant_command);
	
	SafeProcess p = null;
	if (Utility.isWindows()) {
	    if(_ant_command.indexOf("start") != -1) { // running an "ant (re)start" command on windows, run start
		_ant_command = "start";
	    }
	    
	    // The path in quotes, and the entire sequence of commands in quotes as well
	    // E.g. the following works in a Runtime.exec() call:
	    // cmd /C "cd "C:\path\to\greenstone3" && ant stop"
	    // and it preserves any spaces in the path to GSDL3SRCHOME (_gsdl3_src_path).
	    p = new SafeProcess("cmd /C \"cd \"" + _gsdl3_src_path + File.separator + "\" && ant " + _ant_command + "\"");
	}
	else {
	    if(_ant_command.indexOf("start") != -1) { // if running an "ant (re)start" command on non-Windows, run restart
		_ant_command = "restart";
	    }
	    p = new SafeProcess(new String[]{"/bin/bash", "-c", "ant " + _ant_command + " -f \"" + _gsdl3_src_path + File.separator + "build.xml\""});
	}
	
        System.err.println("Issuing "+_ant_command+" command to GS3 Server");
	// in order for the process.waitFor() method to work with Java 6 (JRE 6 is included in GS binaries)
	// need to make sure the IOstreams of the process are not blocked. For Java 7, this is not necessary
	// and a waitFor() is sufficient. But with Java 6, the waitFor() causes the server to finally start
	// after the user has quit GLI.
	// Process takes no input, but we will still catch the process' instream too
	// And we'll catch the error and output streams to prevent them from blocking during waitFor()
	// (For normal input and output stream handling using the Gobblers, see FormatConversionDialog.java)


	// prepare our SafeProcess object
	p.setSplitStdErrorNewLines(true);

	// run it
	int result = p.runProcess(); // uses default process streamgobbler behaviours and
	// does the important part: waitFor() the process (ant stop or start or re-start) to terminate.
	// The int result returned is the exitvalue upon Process.waitFor() returning
	
	if(result != 0) {
	    System.err.println("Error: Failed to successfully " + _ant_command + " the GS3 server.");
	}
	///else {
	///System.err.println("**** " + _ant_command + " of the GS3 server successful.");
	///}
	
    }

  // want to call ant configure-servlets-xml in current thread as we need it to have finished before continuing
  public static boolean prepareXML() {
    SafeProcess p = null;
    if (Utility.isWindows()) {
      // cmd /C "cd "C:\path\to\greenstone3" && ant stop"
      p = new SafeProcess("cmd /C \"cd \"" + Configuration.gsdl3_src_path + File.separator + "\" && ant configure-servlets-xml\"");	
    } else {
      p = new SafeProcess(new String[]{"/bin/bash", "-c", "ant configure-servlets-xml -f \"" + Configuration.gsdl3_src_path + File.separator + "build.xml\""});
    }

    int result = p.runProcess();
    return (result == 0 ? true: false);
	
  }

    // can't call ant stop from its own thread - what if GLI has exited by then?
    // issue call to ant stop from the main GLI thread
    //GS3ServerThread thread = new GS3ServerThread(Configuration.gsdl_path, "stop");
    //thread.start();
    // So, static function to issue the command to stop the server from GLI's own thread.
    // This will block the main GLI thread until the server has stopped.
    public static void stopServer() {

	SafeProcess p = null;
	if (Utility.isWindows()) {
	    // cmd /C "cd "C:\path\to\greenstone3" && ant stop"
	    p = new SafeProcess("cmd /C \"cd \"" + Configuration.gsdl3_src_path + File.separator + "\" && ant stop\"");	
	} else {
	    p = new SafeProcess(new String[]{"/bin/bash", "-c", "ant stop -f \"" + Configuration.gsdl3_src_path + File.separator + "build.xml\""});
	}

	System.err.println("Issuing stop command to GS3 Server. Waiting for GS3 server to stop...");
	int result = p.runProcess();
	if(result == 0) {
	    System.err.println("Successfully stopped GS3 server.");
	    //DebugStream.println("********** SUCCESSFULLY stopped THE GS3 SERVER ON EXIT");
	}
	else {
	    System.err.println("********** FAILED TO SUCCESSFULLY stop THE GS3 SERVER ON EXIT");
	}
	
	// doing a p.waitFor() without processing the Process' IOstreams causes blocking with Java 6 
	// (i.e. when JRE 6 included with GS binaries). However, p.waitFor() with Java 7 is fine.
	/*if(p != null && p.waitFor() == 0) {
	  DebugStream.println("********** SUCCESSFULLY stopped THE GS3 SERVER ON EXIT");
	  }
	  else {
	  System.err.println("********** FAILED TO SUCCESSFULLY stop THE GS3 SERVER ON EXIT");
	  //throw new Exception ("Failed to successfully stop the GS3 server on exit.");
	  }*/
	
    }

    public static boolean isServerRunning() {
	String antCmd = "ant check-tomcat-running"; // "ant verbose-check-tomcat-running";
	
	SafeProcess p = null;
	if (Utility.isWindows()) {
	    p = new SafeProcess("cmd /C \"cd \"" + Configuration.gsdl3_src_path + File.separator + "\" && "+antCmd+"\"");	
	} else {
	    p = new SafeProcess(new String[]{"/bin/bash", "-c", antCmd+" -f \"" + Configuration.gsdl3_src_path + File.separator + "build.xml\""});
	}
	
	//System.err.println("**** Checking if tomcat is running");
	p.runProcess();
	String output = p.getStdOutput();

	if(output.contains("Tomcat is running: true")) {
	    //System.err.println("**** Tomcat was running");
	    return true;
	}
	
	//System.err.println("**** Tomcat was not running");
	return false;
    }
    
    // first time, call this on startup, before running GS3ServerThread
    public static boolean wasServerLaunchedOutsideGLI() {
	//System.err.println("@@@ Was server launched outside GLI: " + isIndependentServer);
	return isIndependentServer;
    }
}
