package usda.weru.weps.wepsRunControl;

import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.TFileReader;
import de.schlichtherle.truezip.file.TFileWriter;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; 
import usda.weru.util.ConfigData;
import usda.weru.util.Util;
import usda.weru.weps.location.Station;
import usda.weru.weps.location.WindgenDataModel;

/**
 *
 * @author mhaas
 */
public class WrcRunModelWindInterpolate extends WrcRunModel {
    
    WrcRunModelWindInterpolateGetStations modelGenStations;
    WrcRunModelWindInterpolateGenRecord modelGenRecord;
    
    protected String genDataWeightsOutFilename;
    
    // specified is the main output dir for this run
    protected String specifiedOutDirName;
    protected String interpDirName;
    protected TFile interpDir;
    
    String windgenDataBaseFileName;
    String interpWeightsOutFileName;
    String interpGeneratedDataBaseFileName;

    protected ConfigData configData;

    public WrcRunModelWindInterpolate () {
        this("", null, null, null);
    }
        
    public WrcRunModelWindInterpolate (String runDir, Logger log, WrcBackgroundIf bgIf) {
        super (runDir, log, bgIf);
        
        dlgIdx = 0;
        emptyCmdsMsg = "Wind file supplied";
        
        specifiedOutDirName = runDir;
        genDataWeightsOutFilename = null;
        
        configData = ConfigData.getDefault();

        interpWeightsOutFileName = "interpolated_weights.out";
        interpGeneratedDataBaseFileName = "test.wdb";
        windgenDataBaseFileName = configData.getDataParsed(ConfigData.WinData);
        
        // make the interpolate directory
        interpDirName = runDir + "/interpolate";

        interpDir = new TFile(interpDirName);
        if (interpDir.exists()) {
            Util.deleteAll(interpDir);
        }
        interpDir.mkdirs();
        
        modelGenStations = new WrcRunModelWindInterpolateGetStations (interpDirName, log, bgIf);
        modelGenRecord = new WrcRunModelWindInterpolateGenRecord (interpDirName, log, bgIf);
        
        // default value;
        addCmds_outputFile("weights.txt");

        rtnVal += 1;  //debugging only
    }
    
    public WrcRunModelWindInterpolate (String runDir, String[] commandsArr, Logger log, WrcBackgroundIf bgIf) {
        super (runDir, commandsArr, log, bgIf);
    }
    
    public int getStationNum () {
        return 999999;
    }
    
    public String getWdbFileName () {
        return interpGeneratedDataBaseFileName;
    }
    
    public String getWeightsOutName () {
        return new TFile(specifiedOutDirName, interpWeightsOutFileName).getAbsolutePath();
    }
    
    public String getInterpDirName () {
        return interpDir.getAbsolutePath();
    }
    
    public void addCmds_latlon (String latlonStr, WrcRunModelWindInterpolateGetStations.latlonFlag flag) throws WrcException {
        modelGenStations.addCmds_latlon(latlonStr, flag);
    }
    
    public void addCmds_idxFile (String fileStr) {
        modelGenStations.addCmds_idxFile(fileStr);
    }
    
    public void addCmds_polFile (String fileStr) {
        modelGenStations.addCmds_polFile(fileStr);
    }
    
    public void addCmds_outputFile (String fileStr) {
        // if executing local, we are NOT running in the interpDir,
        // so add that to the output file specification.
        String s = configData.getDataParsed("CD-SC-windgen-interpolate-execOnServer");
        if (!configData.getDataParsed("CD-SC-windgen-interpolate-execOnServer").contentEquals("1")) {
            File f = new File (fileStr);
            File newFile = new File (interpDir, f.getName());
            String newFileStr = newFile.getAbsolutePath();
            modelGenStations.addCmds_outputFile(newFileStr);
            modelGenStations.addCmds_outputFile(fileStr);
            // leave genDataWeightsOutFilename alone, the path will get added to it later.
            // when executing on server, the filename does not have a path.
            // so when using genDataWeightsOutFilename, a path is always prepended.
        } else {
            modelGenStations.addCmds_outputFile(fileStr);
        }
        genDataWeightsOutFilename = fileStr;
    }

    @Override
    public Integer execModel() throws Exception {
       
//        int retVal;
        if (skipExec) {
            rtnVal = 0;
        } else {


            bgIf.bkgndDlgWriteMsg(dlgIdx, "interpolate 1A");

            modelGenStations.setOutputWriters(writerStdErr, writerStdOut);
            rtnVal = modelGenStations.execModel();

            if(rtnVal != 0) 
            {
                bgIf.bkgndDlgWriteMsg(dlgIdx, "interpolate 1A err");
                return rtnVal;
            }

            File outf = new TFile(interpDirName, genDataWeightsOutFilename);
            BufferedReader br = null;
            BufferedWriter bw = null;
            try {
                br = new BufferedReader(new TFileReader(outf));
            } catch (FileNotFoundException ex) {
                throw new WrcException ("WrcRunModelWindInterpolate IO Error: file not found", ex).
                        addLog(LOGGER, "WrcRunModelWindInterpolate IO Error: file not found: " + outf.getAbsolutePath() + ex);
            }

            TFile weightsOut = null;
            try {
                weightsOut = new TFile(specifiedOutDirName, interpWeightsOutFileName);
                bw = new BufferedWriter(new TFileWriter(weightsOut));
                bw.write("#ID    |WEIGHT             |NAME");
                bw.newLine();

            } catch (IOException ioe) {
                throw new WrcException ("WrcRunModelWindInterpolate IO Error", ioe).
                        addLog(LOGGER, "WrcRunModelWindInterpolate IO Error: " + weightsOut.getAbsolutePath() + ioe);
            }

            modelGenRecord.addCmds_outputFile(interpGeneratedDataBaseFileName);

            // Are we execing on server, then which service
            boolean isNewServerVer = modelGenRecord.IsNewServerVer();

            try {
                if (br != null) {
                    while (true) {
                        String inpLin = null;
                        try {
                            inpLin = br.readLine();
                        } catch (IOException ex) {
                            throw new WrcException ("WrcRunModelWindInterpolate IO Error", ex).
                                    addLog(LOGGER, "WrcRunModelWindInterpolate IO Error: " + outf.getAbsolutePath() + ex);
                        }
                        if (inpLin == null) {
                            break;
                        }
                        String[] inpArr = inpLin.trim().split(" +");

                        if (bw != null) {
                            try {
                                //For some reason, Linux outputs a different weights.txt file than Windows.
                                if(inpArr[0].startsWith("#")) continue;
                                if(inpArr.length != 2) continue;
                                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 (NumberFormatException | IOException e) {
                                throw new WrcException ("WrcRunModelWindInterpolate Unable to write weight line.", e).
                                        addLog(LOGGER, "WrcRunModelWindInterpolate Unable to write weight line." + e);
                            }
                        }
                        if(!inpArr[0].startsWith("#")) {
                            if (!isNewServerVer) {
                                // If new server ver, don't extract files
                                // (The server code will do it there)
                                ExtractStationFromWDB esf = new ExtractStationFromWDB(new TFile(windgenDataBaseFileName), interpDirName, inpArr[0]);
                            }
                            modelGenRecord.addCmds_StationAndWeight(inpArr[0],inpArr[1]);
                        }
                    }
                }
            } finally {
                if (br != null) {
                    try {
                        br.close();
                    } catch (IOException e) {
                            throw new WrcException ("WrcRunModelWindInterpolate Unable to close stream", e).
                                    addLog(LOGGER, "WrcRunModelWindInterpolate Unable to close stream: " + outf.getAbsolutePath() + e);
                    }
                }
                if (bw != null) {
                    try {
                        bw.close();
                    } catch (IOException e) {
                        throw new WrcException ("WrcRunModelWindInterpolate Unable to close stream", e).
                                addLog(LOGGER, "WrcRunModelWindInterpolate Unable to close stream: " + weightsOut.getAbsolutePath() + e);
                    }
                }
            }

            bgIf.bkgndDlgWriteMsg(dlgIdx, "interpolating 2");
            modelGenRecord.setOutputWriters(writerStdErr, writerStdOut);
            rtnVal = modelGenRecord.execModel();

            if(rtnVal != 0) {
                bgIf.bkgndDlgWriteMsg(dlgIdx, "error 2");
                return rtnVal;
            }

            bgIf.bkgndDlgWriteMsg(dlgIdx, "finished");
        }
        return rtnVal;
    }
    
}
