package usda.weru.util.windgen;

//import usda.weru.erosion.*;
import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.TFileWriter;
import java.util.*;
import java.awt.*;
import javax.swing.*;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;

/**
 * This class makes simulation RUNS for the wind and climate generation data files using the model and shows all the
 * analysis and report genration screens with the data from it.
 */
public class RunProgram implements Runnable {

    String[] commandArray;
    String commandString;
    Component parent;
    Process exeProcess;
    private boolean stopFlag = false;
    private final Vector<String> warnVec = new Vector<>();
    private boolean isDone = false;
    private boolean hasErrors = false;
    private String workingDirectory = "c:/weps.wrk/test";
    /**
     * The current project name to which this simulation RUN is associated.
     */
    public String projName = "";

    /**
     * Copies files into run directory for weps.exe and starts a thread to make a simulation run.
     *
     */
    public RunProgram() {
    }

	/**
	 *
	 * @param parent
	 * @param commandArray
	 * @param workingDir
	 */
	public RunProgram(Component parent, String[] commandArray, String workingDir) {

        this.parent = parent;
        this.workingDirectory = workingDir;
        this.commandArray = commandArray.clone();
        commandString = "";
        for (String arg : commandArray) {
            commandString = commandString + arg + " ";
        }
        run();
    }

	/**
	 *
	 * @param parent
	 * @param commandArray
	 * @param workingDir
	 * @param out
	 * @param err
	 */
	public RunProgram(Component parent, String[] commandArray, String workingDir, PrintWriter out, PrintWriter err) {

        this.parent = parent;
        this.workingDirectory = workingDir;
        this.commandArray = commandArray.clone();
        commandString = "";
        for (String arg : commandArray) {
            commandString = commandString + arg + " ";
        }
        outout = out;
        outerr = err;
        run();
    }

    PrintWriter outerr = null;
    PrintWriter outout = null;

//    /**
//     * Allows existing stdout & stderr to be used by this process
//     */
//
//    public void setOut(PrintWriter stdout, PrintWriter stderr) {
//        outerr = stderr;
//        outout = stdout;
//    }

    /**
     * The runnable thread method ( for implements part of Runnable) used to concurrently execute similar
     * programs for additional load bearing like using multiple run files to check more results and generate
     * reports on different files, etc.
     *
     */
    @Override
    public void run() {
        PipeIn pipout = null;
        PipeIn piperr = null;

        boolean createdOut = false;
        boolean createdErr = false;

        try {
            if (outerr == null) {
                outerr = new PrintWriter(new BufferedWriter(new TFileWriter(new TFile(workingDirectory, "stderr.txt"))));// SEP01	RUN08
                createdErr = true;
            }
            outerr.println("Begin: " + new Date(System.currentTimeMillis()) + " " + commandString);
            if (outout == null) { 
                outout = new PrintWriter(new BufferedWriter(new TFileWriter(new TFile(workingDirectory, "stdout.txt"))));// SEP01	RUN08
                createdOut = true;
            }
            outout.println("Begin: " + new Date(System.currentTimeMillis()) + " " + commandString);
        } catch (java.io.IOException i) {
            throw new RuntimeException("can't open output files");
        //System.err.println("RP_run: " + i);
        }

//		runDialog.JTF_status.setText("running");

        try {

//            exeProcess = new ProcessBuilder().command(commandArray).directory(new File(workingDirectory)).start();
            if(System.getProperty("os.name").equals("Linux"))
            {
                for(int index = 0; index < commandArray.length; index ++)
                {
                    while(commandArray[index].startsWith("\"")) commandArray[index] = commandArray[index].substring(1, commandArray[index].length() - 1);
                    TFile exe = new TFile(commandArray[index]);
                    if(commandArray[index].startsWith("bin")) commandArray[0] = exe.getAbsolutePath();
                }
            }
            System.out.println(Arrays.toString(commandArray));
            exeProcess = Runtime.getRuntime().exec(commandArray, null, new TFile(workingDirectory));

            pipout = new PipeIn(outout, exeProcess.getInputStream(), this);
            pipout.start();
            piperr = new PipeIn(outerr, exeProcess.getErrorStream(), this);
            piperr.start();
            int rtnVal = exeProcess.waitFor();
//System.out.println("RP_r: " + rtnVal);            
            if (rtnVal != 0) {
                if (!stopFlag) {
                    JOptionPane.showMessageDialog(parent, "Error executing " + commandString,
                            "Abnormal Termination", JOptionPane.ERROR_MESSAGE);
                } else {
                    JOptionPane.showMessageDialog(parent, "Run canceled by user " + workingDirectory,
                            "Abnormal Termination", JOptionPane.WARNING_MESSAGE);
                }
            }
        } catch (java.io.IOException i) {
            JOptionPane.showMessageDialog(parent, "Error executing " + commandString + "\n" + i,
                    "IO Exception", JOptionPane.ERROR_MESSAGE);
        } catch (java.lang.InterruptedException j) {
            exeProcess.destroy();
//			JOptionPane.showMessageDialog(parent, "Error executing " + commandArray + "\n" + j,
//										  "Interrupted Exception", JOptionPane.ERROR_MESSAGE );
        }
        finally{
            outout.println("End: " + new Date(System.currentTimeMillis()) + " " + commandString);
            outerr.println("End: " + new Date(System.currentTimeMillis()) + " " + commandString);


            //only clsoe the streams if this RunProgram owns the writers

            if(createdOut){
                outout.close();
            }
            else{
                outout.flush();
            }

            if(createdErr){
                outerr.close();
            }
            else{
                outerr.flush();
            }



        }



//        runDialog.setVisible(false);
//        runDialog.dispose();
//        runDialog = null;



        try {

            /* weps run completed successfully */
            if (exeProcess == null || exeProcess.exitValue() != 0) {
                hasErrors = true;
                /* weps run either canceled or ended
                 * should have some code to tell what happened
                 */

                JOptionPane.showMessageDialog(parent, "Program returned error code.",
                        "Run failed", JOptionPane.ERROR_MESSAGE);

            }
        } catch (IllegalThreadStateException e) {
            //System.err.println("process terminating failed");
        }

        isDone = true;

    }

	/**
	 *
	 * @return
	 */
	public boolean isDone() {
        return isDone;
    }

	/**
	 *
	 * @return
	 */
	public boolean hasErrors() {
        return hasErrors;
    }

    /**
     * Thread to receive weps.exe stdout or stderr.
     * Directs all output into a file.
     * Parses stdout and updates RunDialog
     * @author wjr
     */
    class PipeIn extends Thread {

        InputStream from;
        PrintWriter to;
        RunProgram rp;

        public PipeIn(PrintWriter to, InputStream from, RunProgram rp) {
            this.from = from;
            this.to = to;
            this.rp = rp;
        }

        @Override
        public void run() {

            String inpstr, trimstr = null;
            BufferedReader bid = new BufferedReader(new InputStreamReader(from), 10);

            try {
                while ((inpstr = bid.readLine()) != null) {
                    to.println(inpstr);
                    if (rp != null) {
                        //trim the input string so that the leading white spaces are removed-neha
                        trimstr = inpstr.trim();
                        if (trimstr.startsWith("Year")) {
                            // if (!runTypeDisp.equals(ConfigData.NRCS)) {
                            //rp.runDialog.JTF_status.setText(inpstr);
                            // } else {
                            // 	rp.runDialog.JTF_status.setText("NRCS run");
                            // }
                            StringTokenizer st = new StringTokenizer(inpstr);
                            st.nextToken();
                        //                           rp.runDialog.JPB_weps.setValue(Integer.parseInt(st.nextToken()));
//							rp.runDialog.JTF_curyr.setText(st.nextToken());
                        } else if (trimstr.startsWith("Warning")) {
                            warnVec.add(inpstr);
                        }
                    }
                }
            } catch (IOException e) {
                //System.err.println("PipeIn: " + e);
            }
        }
    }
}

