/*
 * ThresholdRun.java
 *
 * Created on March 16, 2006, 11:17 AM
 *
 * To change this template, choose Tools | Options and locate the template under
 * the Source Creation and Management node. Right-click the template and choose
 * Open. You can then make changes to the template in the Source Editor.
 */
package usda.weru.erosion;

import de.schlichtherle.io.File;
import de.schlichtherle.io.FileOutputStream;
import de.schlichtherle.io.FileReader;
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.Station;
import usda.weru.weps.location.WindgenStation;

/**
 *
 * @author wjr
 */
public class ThresholdRun extends usda.weru.erosion.gui.ThresholdRun_n implements PropertyChangeListener {
    private String workingDirectory=".";
    private String cmdStr="c:/weps.wrk/weps1.install/arch/windows/bin/tsterode.exe -u -i${input.file} -Emit";
    private DataStore ds;
    
//	private usda.weru.util.WindGenDisp wgd;
    private WindDisp wgd;



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

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


    }

    public ThresholdRun(String windName, String cliName) {
        super();        
        setTitle(new File(runName).getName());
        setVisible(true);


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

    ThresholdRun(String runName, String cmdStr, String workingDirectory, String windIdx, String windDB) {
        this(windIdx, "");
        this.runName=runName;
        this.cmdStr=cmdStr;
//System.out.println("TR: " + cmdStr);        
        this.workingDirectory=workingDirectory;
        setTitle(new File(runName).getName());

        ds=new DataStore();
        ds.addPropertyChangeListener(this);
        addPropertyChangeListener(ds);

        ds.init();
//		//System.out.println("TR_TR: " + runName);
        ds.readTextFile(new File(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);
    }

    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");
    }

    @Override
    protected void JB_cancelActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_JB_cancelActionPerformed

        this.dispose();
    }//GEN-LAST:event_JB_cancelActionPerformed
    private double startingWindSpeed=6.0;
    private double[][] windTimes;
    private double[][][] windProbs;
//    private final double[] boundaries={1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5,
//        9.5, 10.5, 11.5, 12.5, 13.5, 14.5, 15.5, 16.5, 17.5,
//        18.5, 19.5, 20.5, 25.5, 30.5, 35.5, 40.5, 45.5
//    };
//    private final int[] threshold={0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 20, 20, 20, 20, 21, 21, 21, 21, 21, 22};
//    private String[] monthNames={"Jan", "Feb", "Mar", "Apr", "May", "Jun",
//        "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
//    };
    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;

    @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() {
                //progress.setMillisToDecideToPopup(350);
                //progress.setMillisToPopup(500);

                File runDir=new File(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;
                    }
                }

                Station station = windgenStationChooser.getSelectedStation();
                WindgenStation windgenStation = (WindgenStation)station;
                String stationID= String.valueOf(windgenStation.getWBan());

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

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

                firePropertyChange(DataStore.WeaWindWeibull, "", "1");
//                firePropertyChange(DataStore.WeaWindSpeeds, "", windSpeeds);
                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 File(runDir, "" + ddx).getAbsolutePath();
                    ds.writeTextFile(new File(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")) {
                            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 {
                    File outf=new File(runDir, "winddisp.dat");
                    FileOutputStream fos=new FileOutputStream(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) {
                    }


                }

            }
        };
        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]);
                double val=Double.parseDouble(st.nextToken());
                if (val > 0.0) {
                    return bufLin;
                }
            }
        }
    }

    private void readOutput(String fileName, int ddx) {
        try {
            File inpf=new File(fileName + ".emit");
            BufferedReader in=new BufferedReader(new FileReader(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 HT_prop=new Hashtable();

    @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=(String) HT_prop.get(prop);
        if (!val.equals(savedVal)) {
            HT_prop.put(prop, val);
            firePropertyChange(prop, savedVal, val);
        }
    }



}
