/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package usda.weru.util.windgen;

import de.schlichtherle.io.File;
import de.schlichtherle.io.FileReader;
import de.schlichtherle.io.FileWriter;
import java.awt.Component;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.DecimalFormat;
import java.text.Format;
import java.util.Vector;

import javax.swing.JFrame;
import org.apache.log4j.Logger;
import usda.weru.util.About;
import usda.weru.util.Util;
import usda.weru.weps.location.Station;
import usda.weru.weps.location.WindgenDataModel;

/**
 *
 * @author wjr
 */
public class MakeInterpolatedStation implements Runnable {
    private static final Logger LOGGER = Logger.getLogger(MakeInterpolatedStation.class);

    public static final int INTERPOLATE1_EXE = 0;
    public static final int INTERPOLATE2_EXE = 10;
    public static final int IDX_FILE = 1;
    public static final int POL_FILE = 2;
    public static final int LAT = 3;
    public static final int LON = 4;
    public static final int WDB = 5;
    public static final int WINDGEN_EXE = 6;
    public static final int WINFILE_NAME = 7;
    public static final int SIM_START = 8;
    public static final int SIM_LENGTH = 9;
    public static final int WEIGHTSFILE_NAME = 11;

    private boolean c_cleanup = true;

    public void setParameter(int cdx, String val) {
        switch (cdx) {
            case INTERPOLATE1_EXE:
                commandArray[0] = "\"" + new File(val).getAbsolutePath() + "\"";
                break;
            case IDX_FILE:
                commandArray[2] = "\"" + new File(val).getAbsolutePath() + "\"";
                break;
            case POL_FILE:
                commandArray[4] = "\"" + new File(val).getAbsolutePath() + "\"";
                break;
            case LAT:
                if(val != null){
                    //round down to two decimal places
                    try{
                        double d = Double.valueOf(val.trim());
                        Format format = new DecimalFormat("#0.00");
                        String temp = format.format(d);
                        if(!val.equals(temp)){
                            LOGGER.debug("Input Latitude: " + val);
                            val = temp;
                            LOGGER.debug("Latitude trimmed to " + val);
                        }
                    }
                    catch(Exception e){
                        //do nothing
                        LOGGER.debug("Unable to parse latitude. \"" + val + "\"", e);
                    }
                }

                //set the fixed up value
                commandArray[6] = val;
                break;
            case LON:
                 if(val != null){
                    //round down to two decimal places
                    try{
                        double d = Double.valueOf(val.trim());
                        Format format = new DecimalFormat("#0.00");
                        String temp = format.format(d);
                        if(!val.equals(temp)){
                            LOGGER.debug("Input Logitude: " + val);
                            val = temp;
                            LOGGER.debug("Longitude trimmed to " + val);
                        }
                    }
                    catch(Exception e){
                        //do nothing
                        LOGGER.debug("Unable to Longitude. \"" + val + "\"", e);
                    }
                }

                //set the fixed up value
                commandArray[8] = val;
                break;
            case WDB:
                wdbName = val;
                break;
            case WINDGEN_EXE:
                windgenArr[0] = val;
                break;
            case WINFILE_NAME:
                windgenArr[4] = new File(val).getAbsolutePath();
                break;
            case WEIGHTSFILE_NAME:
                windgenArr[11] = new File(val).getAbsolutePath();
                break;
            case SIM_START:
                windgenArr[8] = val;
                break;
            case SIM_LENGTH:
                windgenArr[10] = val;
                break;
            case INTERPOLATE2_EXE:
                exeInterp = val;
                break;
        }
    }
    String[] commandArray = {
        "c:/weps.svn/weps.install/bin/windows/interpolate.exe",
        "-f",
        "c:/weps.svn/weps.install/db/wind_gen/wind_gen_his_upper_US_NRCS.idx",
        "-p",
        "c:/weps.svn/weps.install/db/wind_gen/windgen_select_areas/windgen_select_areas.pol",
        "-lat",
        "30.7",
        "-lon",
        "-100.2",
        "-o",
        "weights.txt"
    };
    String wdbName = "c:/weps.svn/weps.install/db/wind_gen/wind_gen_his_upper_US.wdb";
    String outDir = "c:/weps.svn/weps.install/test";
//
    String exeInterp = "c:/weps.svn/windgen/src/interpolate/interpxxx_wdb.exe";
    String wdbOut = "test.wdb";
    String wrkDir = "c:/weps.svn/weps.install/test";
//
//    String exeWindGen = "c:/weps.svn/weps.install/bin/windows/wind_gen4.exe";
    String[] windgenArr = {
        "c:/weps.svn/weps.install/bin/windows/wind_gen4.exe",
        "-s",
        "999999",
        "-o",
        wrkDir + "/" + "wind_gen.win",
        "-f",
        wrkDir + "/" + wdbOut,
        "-b",
        "1",
        "-y",
        "20",
        null
    };
    Component parent;

    public MakeInterpolatedStation(Component parent) {
        this.parent = parent;
    }

    public static void main(String[] args) {
        JFrame jf = new JFrame();
        MakeInterpolatedStation mis = new MakeInterpolatedStation(jf);
        mis.run();
    }

    public File getOutputFile(){
        return new File(wrkDir, wdbOut);
    }

    public void setCleanUp(boolean cleanup){
        c_cleanup = cleanup;
    }
    PrintWriter stdout = null;
    PrintWriter stderr = null;

    public void setOut(PrintWriter out, PrintWriter err) {
        stdout = out;
        stderr = err;
    }

    private static int c_tmpDirCounter;

    private static synchronized int getNextTmpDirNumber(){
        return c_tmpDirCounter++;
    }


    @Override
    public void run() {

        // make a temporary work directory
        File tmpDir = null;
        
        tmpDir = new File(About.getUserWeps(), "tmp/windgen_interpolate/" + getNextTmpDirNumber());
        if(tmpDir.exists()){
            Util.deleteAll(tmpDir);
        }
        tmpDir.mkdirs();
        wrkDir = tmpDir.getAbsolutePath();
        
        

        try{

            new RunProgram(parent, commandArray, wrkDir, stdout, stderr);
            File outf = new File(wrkDir, commandArray[10]);
            BufferedReader br = null;
            BufferedWriter bw = null;
            try {
                br = new BufferedReader(new FileReader(outf));
            } catch (IOException ex) {
                LOGGER.error("IO Error: " + outf.getAbsolutePath(), ex);
            }

            File weightsOut = null;
            if(windgenArr[11] != null){
                try{
                    weightsOut = new File(windgenArr[11]);
                    bw = new BufferedWriter(new FileWriter(weightsOut));
                    bw.write("#ID    |WEIGHT             |NAME");
                    bw.newLine();

                }
                catch(IOException ioe){
                    LOGGER.error("IO Error: " + weightsOut.getAbsolutePath(), ioe);
                }
            }

            Vector<String> cmdVec = new Vector<String>();
            cmdVec.add(exeInterp);
            cmdVec.add(/*wrkDir + "/" + */wdbOut);
            Vector<String> filVec = new Vector<String>();
            try{
            if(br != null){
                while (true) {
                    try {
                        String inpLin = null;
                        try {
                            inpLin = br.readLine();
                        } catch (IOException ex) {
                            LOGGER.error("IO Error: " + outf.getAbsolutePath(), ex);
                        }
                        if (inpLin == null) {
                            break;
                        }
                        String[] inpArr = inpLin.trim().split(" ");

                        if(bw != null){
                            try{
                                long stationId = Long.valueOf(inpArr[0]);
                                double stationWeight = Double.valueOf(inpArr[1]);
                                Station station = WindgenDataModel.getInstance().getStation(stationId);
                                String name = station != null ? station.getDisplayName() : "UNKNOWN";
                                bw.write(String.valueOf(stationId) + " |" + String.valueOf(stationWeight) + " |" + name);
                                bw.newLine();
                            }
                            catch(Exception e){
                                LOGGER.error("Unable to write weight line.", e);
                            }
                        }




                        ExtractStationFromWDB esf = new ExtractStationFromWDB(new File(wdbName), wrkDir, inpArr[0]);
                        cmdVec.add(/*tmpDir + "/" + */inpArr[0]);
                        filVec.add(/*tmpDir + "/" + */inpArr[0]);
                        cmdVec.add(String.valueOf(inpArr[1]));
                    } catch (IOException ex) {
                        LOGGER.error("IO Error: " + outf.getAbsolutePath(), ex);
                    }
                }
            }
            }
            finally{
                if(br != null){
                    try{
                        br.close();
                    }
                    catch(Exception e){
                        LOGGER.error("Unable to close stream: " + outf.getAbsolutePath(), e);
                    }
                }
                if(bw != null){
                    try{
                        bw.close();
                    }
                    catch(Exception e){
                        LOGGER.error("Unable to close stream: " + weightsOut.getAbsolutePath(), e);
                    }
                }
            }
    //        System.out.println("done");
            String[] cmdArr = cmdVec.toArray(new String[0]);
    //        for (String str : cmdArr) {
    //            System.out.println("" + str);
    //        }
            new RunProgram(parent, cmdArr, wrkDir, stdout, stderr);
    //        for (String temp : filVec) {
    //            (new File(temp)).delete();
    //        }
    //        String winFileName = commandArray[6] + "-" + commandArray[8];
    //        winFileName = winFileName.replace(".", "_");
    //        windgenArr[4] = wrkDir + "/" + winFileName + ".win";
    //        windgenArr[4] = wrkDir + "/" + "wind_gen.win";
    //        windgenArr[6] = wrkDir  + "/" + wdbOut;
    //        windgenArr[4] = "./wind_gen.win";
            windgenArr[6] = wdbOut;
            if (windgenArr[0] != null) {
                new RunProgram(parent, windgenArr, wrkDir, stdout, stderr);
            }
        }
        finally{
            if(c_cleanup){
                boolean deleted = Util.deleteAll(tmpDir);
                if(!deleted){
                    LOGGER.error("Unable to delete tmp directory: " + tmpDir.getAbsolutePath());
                }
            }
            
        }
    }
}
