package org.greenstone.util;

import java.io.IOException;
import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;

import org.greenstone.util.LogStreamGobbler;

import org.apache.log4j.*;

public abstract class RunTarget extends Thread 
{
    protected String targetCmd = "";
    protected String launchDir = null;
    
    protected static Logger logger = Logger.getLogger(RunTarget.class.getName());

    protected int state = -1; //success: 0 error: 1    
    public static int SUCCESS = 0;
    public static int FAILED  = 1; 

    protected String targetSuccess;
    protected String targetFailed;
    protected String targetFinished;

    public void run() 
    {
	 
	 try {
	     state = -1;
	     String targetCmd = getTargetCmd();
	     logger.info("Target: " + targetCmd);

	     /*
	     Runtime run = Runtime.getRuntime();
             Process process = run.exec(targetCmd);
	     BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));
	     String line = null;
             
	     while ((line = br.readLine()) != null) {

		 logger.info(line);

		 if (line.equals(targetSuccess)){
		     state = 0;
		 }
		 
		 if (line.equals(targetFailed)){
		     state = 1; 
		 }

		 if(line.startsWith(targetFinished)){
		     break;		 
		 }
	     }
	     
	     br.close();
	     */
	     
	     SafeProcess process;
	     if(this.launchDir != null) {
		 //System.err.printf("*** RunTarget.run() - launch dir for %s: |%s|***\n",
		 //		   this.targetCmd, this.launchDir);		 
		 // launchDir set, so use constructor of form
		 //   SafeProcess(String[] cmd_args, String[] envparams, File launchDir)
		 // where envparams of null means inheriting parent process' environment
		 process = new SafeProcess(targetCmd.split(" +"),
					   null,
					   new File(this.launchDir));
	     } else { // do what we always did		 
		 process = new SafeProcess(targetCmd);
	     }
	     process.setSplitStdOutputNewLines(true);
	     process.runProcess();	     
	     String output = process.getStdOutput();
	     String[] lines = output.split("[\\r\\n]+"); // http://stackoverflow.com/questions/454908/split-java-string-by-new-line
	     for(int i = 0; i < lines.length; i++) {
		 //System.err.println("*** RunTarget.run() - Got line:|" + lines[i] + "|***");
		 String line = lines[i].trim();
		 if (line.equals(targetSuccess)){
		     state = 0;
		 }
		 
		 if (line.equals(targetFailed)){
		     state = 1; 
		 }

		 if(line.startsWith(targetFinished)){
		     break;		 
		 }
	     }
	     //System.err.println("\n\n");

	     
	     if(state < 0) {
		 logger.info("Unexpected end of input when running target: " + targetCmd);
		 // Output of process/runnning cmd is useful information to log when things
		 // go wrong, otherwise we're left in the dark while told to check the logs,
		 // where we only see "Unexpected end of input when running target targetCmd"
		 // I was none the wiser as the output was different between automated testing
		 // restarting the GSI server and restarting the GSI server normally.
		 logger.info("*** Output from target cmd process just run was:*******\n"
			     + Arrays.toString(lines)
			     + "\n***********");
	     }
	 } catch (Exception e) {
	     e.printStackTrace();
	     logger.error(e);
	     state = 1;
	 } 
    }
  
    public int getTargetState()
    {
	return state;     
    }
    
    public abstract void setTargetCmd(String cmd);

    public String getTargetCmd() 
    {
	return this.targetCmd;
    }

    public void setLaunchDir(String dirPath) {
	this.launchDir = dirPath;
    }

    public String getLaunchDir() 
    {
	return this.launchDir;
    }
}
