/*
 * ThresholdRun.java
 *
 * Created on March 16, 2006, 11:17 AM
 *
 */
package usda.weru.erosion;

import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.TFileOutputStream;
import de.schlichtherle.truezip.file.TFileReader;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.beans.*;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Map;
import javax.swing.ProgressMonitor;
import usda.weru.util.Util;
import usda.weru.weps.location.Site;
import usda.weru.weps.location.Station;
import usda.weru.weps.location.WindgenStation;

/**
 *
 * @author wjr
 */
public class ThresholdRun extends usda.weru.erosion.gui.ThresholdRun_n implements PropertyChangeListener {

    private static final long serialVersionUID = 1L;

    private String workingDirectory = ".";
    // todo: get rid of this absolute path
    private String cmdStr = "c:/weps.wrk/weps1.install/arch/windows/bin/tsterode.exe -u -i${input.file} -Emit";
    private DataStore ds;

    private Erosion ero;
//	private usda.weru.util.WindGenDisp wgd;
    private WindDisp wgd;

    /** Creates a new instance of ThresholdRun */
    public ThresholdRun() {
        super();

        setTitle(new TFile(runName).getName());
        setVisible(true);

    }

    /**
     *
     * @param windName
     * @param cliName
     */
    public ThresholdRun(String windName, String cliName) {
        super();
        setTitle(new TFile(runName).getName());
        setVisible(true);

    }
    private String runName = "/weps.wrk/test/barrier_upwind4.in";

    ThresholdRun(String runName, String cmdStr, String workingDirectory, String windIdx, String windDB, Erosion e) {
        this(windIdx, "");
        this.runName = runName;
        this.cmdStr = cmdStr;
//System.out.println("TR: " + cmdStr);        
        this.workingDirectory = workingDirectory;
        setTitle(new TFile(runName).getName());
        ero = e;
        ds = new DataStore();
        ds.addPropertyChangeListener(this);
        addPropertyChangeListener(ds);

        ds.init();
//		//System.out.println("TR_TR: " + runName);
        ds.readTextFile(new TFile(runName));

//		wgd = new usda.weru.util.WindGenDisp("/weps.wrk/weps1.install/data/wind_gen.wdb");
        //System.out.println("TR: windDB " + windDB);
        wgd = new WindDisp(windDB);

        if (lastSite != null) {
            siteChooser.setSelectedSite(lastSite);
        }
        if (lastWindgenStation != null) {
            windgenStationChooser.setSelectedStation(lastWindgenStation);
        }
        addCloseListener();
    }

    /**
     *
     * @param args
     */
    public static void main(String[] args) {
        /*ThresholdRun tr=*/
        new ThresholdRun("WE_data/input_files/test.in",
                "c:/weps.wrk/weps1.install/arch/windows/bin/tsterode.exe -u -i${input.file} -Emit",
                ".",
                "data/wind_gen.idx",
                "data/wind_gen.wdb", null);
    }

    private void addCloseListener() {
        this.addWindowListener(new WindowAdapter(){
            @Override
            public void windowClosing(WindowEvent e) {
                ero.enableThreshold();
            }
        });
    }
    
    /**
     *
     * @param evt
     */
    @Override
    protected void JB_cancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_JB_cancelActionPerformed
        ero.enableThreshold();
        this.dispose();
    }//GEN-LAST:event_JB_cancelActionPerformed
    private final double startingWindSpeed = 6.0;
    private double[][] windTimes;
    private double[][][] windProbs;
    
    private final String[] dirNames = {"N-0", "NNE-22", "NE-45", "ENE-67", "E-90", "ESE-112", "SE-135", "SSE-157",
        "S-180", "SSW-202", "SW-225", "WSW-247", "W-270", "WNW-292", "NW-315", "NNW-337", "ALL"
    };
    private double[] startErosion;
    private int[] startErosionIdx;
    RunProgram rp = null;

    private static Site<?> lastSite;
    private static Station lastWindgenStation;

    /**
     *
     * @param evt
     */
    @Override
    protected void JB_runActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_JB_runActionPerformed

        final ThresholdRun thresh = this;
        final ProgressMonitor progress = new ProgressMonitor(thresh, "Generating Table Data...", "", 0, 15);
        progress.setMillisToDecideToPopup(0);
        progress.setMillisToPopup(0);

        final Thread task = new Thread("Threshold Run") {
            @Override
            public void run() {
                TFile runDir = new TFile(runName.substring(0, runName.lastIndexOf(DataStore.InputExt)));
                if (runDir.exists()) {
                    if (runDir.isDirectory()) {
                        //System.out.println("TR_rAP: directory already exists and will use " + runName);
                    } else {
                        //System.out.println("TR_rAP: file with this name exists -- aborting run " + runName);
                        return;
                    }
                } else {
                    if (!runDir.mkdir()) {
                        return;
                    }
                }

                lastSite = siteChooser.getSelectedSite();
                lastWindgenStation = windgenStationChooser.getSelectedStation();
                WindgenStation windgenStation = (WindgenStation) lastWindgenStation;
                String stationID = String.valueOf(windgenStation.getWBan());

                int sdx = wgd.findStation(stationID);
                wgd.parseWindTimes(sdx);
                wgd.parseWindSpeeds(sdx);
                windTimes = wgd.getWindTimes();
                windProbs = wgd.getCumProb();

                StringBuilder sb = new StringBuilder();
                double windSpeed = startingWindSpeed;
                for (int idx = 0; idx < 24; idx++) {
                    if (idx == 12) {
                        sb.append("\n");
                    }
                    sb.append(" " + windSpeed++);
                }

                firePropertyChange(DataStore.WeaWindWeibull, "", "1");
                firePropertyChange(DataStore.WeaWindSpeeds, "", sb.toString());
                firePropertyChange(DataStore.WeaDailySteps, "", 24);
                startErosion = new double[16];
                startErosionIdx = new int[16];

                for (int ddx = 0; ddx < 16; ddx++) {
                    if (progress.isCanceled()) {
                        return;
                    }
                    progress.setProgress(ddx);
                    progress.setNote("Direction:  " + dirNames[ddx]);
                    firePropertyChange(DataStore.WeaWindDir, "", "" + ddx * 22.5);
                    String curFileName = new TFile(runDir, "" + ddx).getAbsolutePath();
                    ds.writeTextFile(new TFile(curFileName));

                    //parse the command and replace any variables.
                    Map<String, String> props = new HashMap<String, String>();
                    props.put("filename", curFileName + DataStore.InputExt);
                    props.put("FileName", curFileName + DataStore.InputExt);

                    StringTokenizer st = new StringTokenizer(cmdStr);
                    String[] command = new String[st.countTokens()];
                    int i = 0;
                    while (st.hasMoreTokens()) {
                        String token = st.nextToken();
                        if (token.startsWith("-i")) {
                            if (Util.isWindows()) {
                                token = "\"" + token + "\"";
                            }
                        }
                        command[i] = Util.parse(token, props);
                        i++;
                    }
                    rp = new RunProgram(thresh, command, workingDirectory);
                    if (rp.hasErrors()) {
                        //System.err.println("TR_rAP: Execution error.  Aborting runs.");
                        progress.close();
                        return;
                    }
                    readOutput(curFileName, ddx);
                }

                calcProbTable();
                java.text.NumberFormat nf = java.text.NumberFormat.getNumberInstance();
                nf.setMaximumFractionDigits(4);
                nf.setMinimumFractionDigits(4);

                nf.setMaximumFractionDigits(5);
                nf.setMinimumFractionDigits(5);

                try {
                    TFile outf = new TFile(runDir, "winddisp.dat");
                    TFileOutputStream fos = new TFileOutputStream(outf);
                    ObjectOutputStream oos = new ObjectOutputStream(fos);
                    oos.writeObject(startErosion);
                    oos.writeObject(probTable);
                    oos.writeObject(windTimes);
                    //oos.writeObject(((usda.weru.weps.WindCliStation) lp.JCB_WinGen.getSelectedItem()).toString());
                    oos.close();
                } catch (FileNotFoundException fnfe) {
                    //System.err.println("TR_rAP: cannot open file " + fnfe);
                    fnfe.printStackTrace();
                } catch (java.io.IOException fioe) {
                    //System.err.println("TR_rAP: error writing file " + fioe);
                    fioe.printStackTrace();
                }
                wgd.setCellData(startErosion, probTable, windTimes);
                wgd.JL_stationName.setText(windgenStation.getDisplayName());
                wgd.setVisible(true);
                wgd.setTitle(wgd.getTitle() + " " + runDir.getName());
                setVisible(false);
            }
        };
        task.start();

        Thread kill = new Thread("Killer") {
            @Override
            public void run() {
                while (task.isAlive()) {
                    if (progress.isCanceled()) {
                        if (rp != null) {
                            if (rp.exeProcess != null) {
                                rp.exeProcess.destroy();
                            }
                        }
                    }
                    try {
                        Thread.sleep(100);
                    } catch (java.lang.InterruptedException ie) {
                    }

                }

            }
        };
        ero.enableThreshold();
        kill.start();
    }//GEN-LAST:event_JB_runActionPerformed
    
    private String findFirstLine(BufferedReader in, int ddx) {
        String bufLin = "";
        while (true) {
            try {
                bufLin = in.readLine();
                if (bufLin == null) {
                    return null;
                }
            } catch (java.io.IOException e) {
                return null;
            }
            if (bufLin.trim().startsWith("1")) {
                StringTokenizer st = new StringTokenizer(bufLin);
                for (int idx = 0; idx < 4; idx++) {
                    st.nextToken();
                }
                startErosion[ddx] = Double.parseDouble(st.nextToken());
                startErosionIdx[ddx] = (int) Math.round(startErosion[ddx]);
				//System.out.println("TR_fFL: " + ddx + " " + startErosion[ddx]);
                String token = st.nextToken();
                if(token.contains("*")) {
                    System.err.println("ERROR: Token does not contain a number.");
                } else {
                    double val = Double.parseDouble(token);
                    if (val > 0.0) {
                        return bufLin;
                    }
                }
            }
        }
    }

    private void readOutput(String fileName, int ddx) {
        try {
            TFile inpf = new TFile(fileName + ".emit");
            BufferedReader in = new BufferedReader(new TFileReader(inpf));
            /*String rtnStr=*/
            findFirstLine(in, ddx);
            in.close();
//            outputLines+=fileName + " " + rtnStr + "\n";
        } catch (java.io.IOException e) {
        }
    }
    double[][] probTable = new double[12][16];
    double[][] weightedProbTable = new double[12][16];
    double totProb = 0;

    private void calcProbTable() {
        for (int mdx = 0; mdx < 12; mdx++) {
            for (int ddx = 0; ddx < 16; ddx++) {

                // testing testing
                int tdx = startErosionIdx[ddx] - 1;
                double cumPrb = 0.0;
                try {
                    cumPrb = 1 - (windProbs[mdx][ddx][tdx] + windProbs[mdx][ddx][tdx - 1]) / 2;
                    probTable[mdx][ddx] = cumPrb;
                } catch (java.lang.IndexOutOfBoundsException e) {
                    probTable[mdx][ddx] = 0;
                }
            }
        }

        for (int mdx = 0; mdx < 12; mdx++) {
            for (int ddx = 0; ddx < 16; ddx++) {
                weightedProbTable[mdx][ddx] = probTable[mdx][ddx] * windTimes[ddx][mdx] / 1200;
                totProb += weightedProbTable[mdx][ddx];
            }
        }
    }
    Hashtable<String, String> HT_prop = new Hashtable<>();

    /**
     *
     * @param e
     */
    @Override
    public void propertyChange(PropertyChangeEvent e) {
        String prop = e.getPropertyName();
        String val;
        try {
            val = (String) e.getNewValue();
        } catch (ClassCastException cce) {
            // not our type of thing
            return;
        }
        String savedVal = HT_prop.get(prop);
        if (!val.equals(savedVal)) {
            HT_prop.put(prop, val);
            firePropertyChange(prop, savedVal, val);
        }
    }

}
