package usda.weru.weps.reports.query.parse;

import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.TFileReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.Types;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.log4j.Logger;
import usda.weru.util.Util;
import usda.weru.weps.reports.query.WepsConnection;
import usda.weru.weps.reports.query.WepsResultSet;

/**
 * This class will assemble the crop interval result set using the parsers.
 * @author jonathanhornbaker
 */
public class ParsedIntervalResultSet extends WepsResultSet
{
    private static final Logger LOGGER = Logger.getLogger(ParsedIntervalResultSet.class);
    
    //hydrobal data
    public static final String NAME = "cropinterval";
    public static final String COLUMN_CROP_CI = "crop";
    public static final String COLUMN_RUNID_CI = "runid";
    public static final String COLUMN_CYCLENUMBER_CI = "cyclenumber";
    public static final String COLUMN_TERMINATEDATE_CI = "terminatedate";
    public static final String COLUMN_PREVIOUSDATE_CI = "previousdate";
    public static final String COLUMN_DURATION_CI = "duration";
    public static final String COLUMN_CROPINDEX_CI = "cropindex";
    public static final String COLUMN_RAIN_CI = "rain";
    public static final String COLUMN_IRRIG_CI = "irrig";
    public static final String COLUMN_INITSWC_CI = "initswc";
    public static final String COLUMN_FINALSWC_CI = "finalswc";
    public static final String COLUMN_DELTASWC_CI = "deltaswc";
    public static final String COLUMN_TRANSP_CI = "transp";
    public static final String COLUMN_EVAP_CI = "evap";
    public static final String COLUMN_RUNOFF_CI = "runoff";
    public static final String COLUMN_DRAIN_CI = "drain";
    public static final String COLUMN_EVAP_LOSS_CI = "evaploss";
    public static final String COLUMN_RUNOFF_LOSS_CI = "runoffloss";
    public static final String COLUMN_DRAIN_LOSS_CI = "drainloss";
    public static final String COLUMN_WUE_CI = "wue";
    public static final String COLUMN_FALLOWEFF_CI = "fallow";
    public static final String COLUMN_WATERSTORAGE_CI = "water_storage";
    public static final String COLUMN_CROP_PERIOD_CI = "period";
    public static final String COLUMN_BIOMASS_CI = "biomass";
    //Season.out data field
    public static final String COLUMN_STANDING_STEM_CI = "standing_stem";
    public static final String COLUMN_STANDING_LEAF_CI = "standing_leaf";
    public static final String COLUMN_AVG_HEIGHT_CI = "avg_height";
    public static final String COLUMN_STEM_COUNT_CI = "stem_count";
    //condition data
    public static final String COLUMN_INT_CI = "crop_int";
    public static final String COLUMN_UNITS_CI = "units";
    public static final String COLUMN_KEY_CI = "key";
    
    private boolean c_filled;
    private final WepsConnection c_con;
    private final SeasonParser season;
    private final HydrobalParser hydro;
    
    public ParsedIntervalResultSet(WepsConnection con)
    {
        c_con = con;
        season = con.getSeasonParser();
        hydro = con.getHydroParser();
        c_filled = false;
        
        addColumn(COLUMN_TERMINATEDATE_CI, Types.DATE, 10, 0);
        addColumn(COLUMN_PREVIOUSDATE_CI, Types.DATE, 10, 0);
        addColumn(COLUMN_DURATION_CI, Types.INTEGER, 10, 0);

        addColumn(COLUMN_CROPINDEX_CI, Types.INTEGER, 10, 0);
        addColumn(COLUMN_RUNID_CI, Types.INTEGER, 10, 0);
        addColumn(COLUMN_CYCLENUMBER_CI, Types.INTEGER, 10, 0);

        addColumn(COLUMN_RAIN_CI, Types.DOUBLE, 10, 3);
        addColumn(COLUMN_IRRIG_CI, Types.DOUBLE, 10, 3);
        addColumn(COLUMN_INITSWC_CI, Types.DOUBLE, 10, 3);
        addColumn(COLUMN_FINALSWC_CI, Types.DOUBLE, 10, 3);
        addColumn(COLUMN_DELTASWC_CI, Types.DOUBLE, 10, 3);
        addColumn(COLUMN_TRANSP_CI, Types.DOUBLE, 10, 3);
        addColumn(COLUMN_EVAP_CI, Types.DOUBLE, 10, 3);
        addColumn(COLUMN_RUNOFF_CI, Types.DOUBLE, 10, 3);
        addColumn(COLUMN_DRAIN_CI, Types.DOUBLE, 10, 3);
        addColumn(COLUMN_EVAP_LOSS_CI, Types.DOUBLE, 10, 3);
        addColumn(COLUMN_RUNOFF_LOSS_CI, Types.DOUBLE, 10, 3);
        addColumn(COLUMN_DRAIN_LOSS_CI, Types.DOUBLE, 10, 3);
        addColumn(COLUMN_WUE_CI, Types.DOUBLE, 10, 3);
        addColumn(COLUMN_FALLOWEFF_CI, Types.DOUBLE, 10, 3);
        addColumn(COLUMN_WATERSTORAGE_CI, Types.DOUBLE, 10, 3);
        addColumn(COLUMN_CROP_PERIOD_CI, Types.VARCHAR, 255, 0);
        addColumn(COLUMN_BIOMASS_CI, Types.DOUBLE, 10, 3);

        //season.out
        addColumn(COLUMN_CROP_CI, Types.VARCHAR, 255, 0);
        addColumn(COLUMN_STANDING_STEM_CI, Types.DOUBLE, 10, 3);
        addColumn(COLUMN_STANDING_LEAF_CI, Types.DOUBLE, 10, 3);
        addColumn(COLUMN_AVG_HEIGHT_CI, Types.DOUBLE, 10, 3);
        addColumn(COLUMN_STEM_COUNT_CI, Types.DOUBLE, 10, 3);

        //booleans
        addColumn(COLUMN_INT_CI, Types.BOOLEAN, 10, 3);
        addColumn(COLUMN_UNITS_CI, Types.BOOLEAN, 10, 3);
        //interval indication
        addColumn(COLUMN_KEY_CI, Types.VARCHAR, 255, 0);
    }
    
    @Override
    public void fill() throws SQLException 
    {
        if(c_filled) return;
        for(int runIndex = 0; runIndex < c_con.getRunFiles().length; runIndex ++)
        {
            boolean US = Util.USUnits.equals(c_con.getUnits());
            int rot_nums = 0;
            try
            {
                TFile manfile = new TFile(c_con.getRunFiles()[runIndex], "mandate.out");
                BufferedReader man_f = new BufferedReader(new TFileReader(manfile));
                String man_line1 = null;
                    man_line1 = man_f.readLine();
                if (man_line1 != null) 
                {
                    String[] line1 = man_line1.split(" ", -1);
                    int index = 0;
                    while(line1[index].equals("")) index ++;
                    rot_nums = Integer.parseInt(line1[index]);
                }
            }
            catch(IOException ioe) { LOGGER.error("Failed to find rotation years in mandate.out.  Defaulting to 0."); }

            String[] seasonLine = {};
            try
            {
                TFile seasonFile = new TFile(c_con.getRunFiles()[0], "season.out");

                if (seasonFile.exists()) 
                {
                    //Reads text from a character-input stream, 
                    //buffering characters so as to provide for the efficient reading of characters, arrays, and lines. 
                    BufferedReader season_f = new BufferedReader(new TFileReader(seasonFile));
                    String season_l = Interval.getLine(season_f);
                    if(season_l == null) return;
                    seasonLine = season_l.split("\\|", -1);
                }
            }
            catch(IOException ioe) {}

            List<Interval> intervals = Interval.generateProperIntervals(seasonLine, rot_nums);
            for(int cycle = 1; cycle <= season.cycle(); cycle ++)
            {
                int counter = 0;
                int duplicateDates = 0;
                Date lastDate = null;
                for(int index = 0; index < intervals.size(); index ++) //We statt base one indexing for proper cycle number.
                {                    
                    Object[] cropIntervalRow = this.createNewRow(true);
                    Interval inter = intervals.get(index);
                    this.setRowValue(cropIntervalRow, COLUMN_CYCLENUMBER_CI, cycle);
                    this.setRowValue(cropIntervalRow, COLUMN_RUNID_CI, runIndex);
                    this.setRowValue(cropIntervalRow, COLUMN_UNITS_CI, US);
                    this.setRowValue(cropIntervalRow, COLUMN_KEY_CI, "CP_N");
                    this.setRowValue(cropIntervalRow, COLUMN_INT_CI, true);
                    this.setRowValue(cropIntervalRow, COLUMN_CROP_PERIOD_CI, "");
                    this.setRowValue(cropIntervalRow, COLUMN_STEM_COUNT_CI, 0.0);
                    this.setRowValue(cropIntervalRow, COLUMN_TERMINATEDATE_CI, new java.sql.Date(inter.getTermin().getTime()));
                    this.setRowValue(cropIntervalRow, COLUMN_PREVIOUSDATE_CI, new java.sql.Date(inter.getBegin().getTime()));
                    this.setRowValue(cropIntervalRow, COLUMN_CROPINDEX_CI, counter);
                    this.setRowValue(cropIntervalRow, COLUMN_CROP_CI, inter.getCrop());
                    counter ++;
                    //1 set for every cropinterval.
                    //1 set for every subinterval.
                    //50 rows per set.
                    
                    //crop interval row data is accumulation of all subinterval row data.
                    //Declaration of accumulation variables.  These variables will pick
                    //up extra data as we iterate through the subintervals.
                    int durAcc = 0;
                    double rainAcc = 0;
                    double irrAcc = 0;
                    boolean firstSWC = true;
                    double swciAcc = 0;
                    double swcfAcc = 0;
                    double snowiAcc = 0.0;
                    double snowfAcc = 0.0;
                    double transpAcc = 0;
                    double evapAcc = 0;
                    double runoffAcc = 0;
                    double drainAcc = 0;
                    double falAcc = 0;
                    double bioAcc = 0;
                    double stStAcc = 0;
                    double stLeAcc = 0;
                    double heightAcc = 0;
                    
                    List<Interval> termins = inter.assembleMultiHarv();
                    if(!inter.getBegin().equals(inter.getPlant()))
                    {
                        Date plantDate = inter.getPlant();
                        Object[] subIntervalRow = this.createNewRow(true);
                        this.setRowValue(subIntervalRow, COLUMN_CYCLENUMBER_CI, cycle);
                        this.setRowValue(subIntervalRow, COLUMN_RUNID_CI, runIndex);
                        this.setRowValue(subIntervalRow, COLUMN_UNITS_CI, US);
                        this.setRowValue(subIntervalRow, COLUMN_KEY_CI, "CP_0");
                        this.setRowValue(subIntervalRow, COLUMN_INT_CI, false);
                        this.setRowValue(subIntervalRow, COLUMN_CROP_PERIOD_CI, "");
                        this.setRowValue(subIntervalRow, COLUMN_STEM_COUNT_CI, 0.0);
                        if(plantDate.equals(lastDate)) duplicateDates ++;
                        else lastDate = plantDate;
                        this.setRowValue(subIntervalRow, COLUMN_TERMINATEDATE_CI, new java.sql.Date(plantDate.getTime()));
                        this.setRowValue(subIntervalRow, COLUMN_PREVIOUSDATE_CI, new java.sql.Date(inter.getBegin().getTime()));
                        this.setRowValue(subIntervalRow, COLUMN_CROPINDEX_CI, counter);
                        this.setRowValue(subIntervalRow, COLUMN_CROP_CI, hydro.getData(cycle, 
                                plantDate, "cropName", duplicateDates));
                        counter ++;
                        
                        //<editor-fold desc="Duration initializer" defaultstate="collapsed">
                        {
                            int dur = 0;
                            long milis;
                            if(inter.getBegin().after(plantDate))
                            {
                                DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
                                milis = 0;
                                try 
                                { 
                                    Date last = dateFormat.parse("31/12/" + rot_nums); 
                                    milis += TimeUnit.DAYS.convert(last.getTime() 
                                        - inter.getBegin().getTime(), TimeUnit.MILLISECONDS);
                                    milis -= Interval.getLeap(last, inter.getBegin());
                                }
                                catch(ParseException pe) { System.out.println("Failed to parse:  " + "31/12/" + rot_nums); }
                                try 
                                { 
                                    Date first = dateFormat.parse(" 1/ 1/ 1"); 
                                    milis += TimeUnit.DAYS.convert(plantDate.getTime() 
                                            - first.getTime(), TimeUnit.MILLISECONDS);
                                    milis -= Interval.getLeap(plantDate, first);
                                }
                                catch(ParseException pe) { System.out.println("Failed to parse:  " + " 1/ 1/ 1"); }
                                milis ++;
                            }
                            else 
                            {
                                milis = TimeUnit.DAYS.convert(plantDate.getTime() 
                                    - inter.getBegin().getTime(), TimeUnit.MILLISECONDS);
                                milis -= Interval.getLeap(inter.getBegin(), plantDate);
                            }
                            dur = (int) milis;
                            durAcc += dur;
                            this.setRowValue(subIntervalRow, COLUMN_DURATION_CI, dur);
                        }
                        //</editor-fold>
                        String temp = "";
                        //<editor-fold desc="Transpiration initializer" defaultstate="collapsed">
                        {
                            double transp = 0.0;
                            temp = hydro.getData(cycle, plantDate, "trans", duplicateDates);
                            try { transp = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse transp from hydrobal:  Line:  " + cycle);
                            }
                            if(US) transp *= 0.0393701;
                            transpAcc += transp;
                            this.setRowValue(subIntervalRow, COLUMN_TRANSP_CI, transp);
                        }
                        //</editor-fold>
                        //<editor-fold desc="Average Height initializer" defaultstate="collapsed">
                        {
                            double height = 0.0;
                            //Season does not contain plants.  Ignore this interval.
                            heightAcc += height;
                            this.setRowValue(subIntervalRow, COLUMN_AVG_HEIGHT_CI, height);
                        }
                        //</editor-fold>
                        //<editor-fold desc="Water Use Efficiency or Fallow Efficiency initializer" defaultstate="collapsed">
                        {
                            double wue = 0.0;
                            temp = hydro.getData(cycle, plantDate, "wateruse_eff", duplicateDates);
                            if(temp != null)
                            {
                                try { wue = Double.parseDouble(temp); }
                                catch(NumberFormatException nfe)
                                {
                                    LOGGER.error("Failure to parse wue from hydrobal:  Line:  " + cycle);
                                }
                            }
                            wue *= 100;
                            this.setRowValue(subIntervalRow, COLUMN_WUE_CI, wue);
                            
                            double falEff = 0.0;
                            temp = hydro.getData(cycle, plantDate, "falloweff", duplicateDates);
                            if(temp != null)
                            {
                                try { falEff = Double.parseDouble(temp); }
                                catch(NumberFormatException nfe)
                                {
                                    LOGGER.error("Failure to parse falEff from hydrobal:  Line:  " + cycle);
                                }
                            }
                            falAcc += falEff;
                            this.setRowValue(subIntervalRow, COLUMN_FALLOWEFF_CI, falEff);
                        }
                        //</editor-fold>
                        
                        //<editor-fold desc="Biomass, Standing stem and Standing leaf initializer" defaultstate="collapsed">
                        {
                            double stSt = 0.0;
                            double stLe = 0.0;
                            double bio = 0.0;
                            //Plant operations shoud not have a line in season.  Ignore this section.
                            bio = stSt + stLe;
                            if(US) bio *= 8921.79;
                            stStAcc += stSt;
                            stLeAcc += stLe;
                            bioAcc += bio;
                            this.setRowValue(subIntervalRow, COLUMN_STANDING_STEM_CI, stSt);
                            this.setRowValue(subIntervalRow, COLUMN_STANDING_LEAF_CI, stLe);
                            this.setRowValue(subIntervalRow, COLUMN_BIOMASS_CI, bio);
                        }
                        //</editor-fold>
                        
                        //<editor-fold desc="SWC, evap, runoff, drain, rain, irrigation and water storage initializer" defaultstate="collapsed">
                        {
                            double rain = 0.0;
                            double irrig = 0.0;
                            double swci = 0.0;
                            double swcf = 0.0;
                            double snowi = 0.0;
                            double snowf = 0.0;
                            double evap = 0.0;
                            double runoff = 0.0;
                            double drain = 0.0;
                            double evapLoss = 0.0;
                            double runoffLoss = 0.0;
                            double drainLoss = 0.0;
                            double ws = 0.0;
                            
                            temp = hydro.getData(cycle, plantDate, "rain", duplicateDates);
                            try { rain = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse rain from hydrobal:  Line:  " + cycle);
                            }
                            if(US) rain *= .0393701;
                            rainAcc += rain;
                            this.setRowValue(subIntervalRow, COLUMN_RAIN_CI, rain);
                            
                            temp = hydro.getData(cycle, plantDate, "irrigation", duplicateDates);
                            try { irrig = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse irrig from hydrobal:  Line:  " + cycle);
                            }
                            if(US) irrig *= 0.0393701;
                            irrAcc += irrig;
                            this.setRowValue(subIntervalRow, COLUMN_IRRIG_CI, irrig);
                            
                            temp = hydro.getData(cycle, plantDate, "Startswc", duplicateDates);
                            try { swci = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse swci from hydrobal:  Line:  " + cycle);
                            }
                            temp = hydro.getData(cycle, plantDate, "Endswc", duplicateDates);
                            try { swcf = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse swcf from hydrobal:  Line:  " + cycle);
                            }
                            if(US) swci *= 0.0393701;
                            if(US) swcf *= 0.0393701;
                            swciAcc = swci;
                            firstSWC = false;
                            swcfAcc = swcf;
                            this.setRowValue(subIntervalRow, COLUMN_INITSWC_CI, swci);
                            this.setRowValue(subIntervalRow, COLUMN_FINALSWC_CI, swcf);
                            this.setRowValue(subIntervalRow, COLUMN_DELTASWC_CI, swcf - swci);
                            
                            temp = hydro.getData(cycle, plantDate, "Startsnow", duplicateDates);
                            try { snowi = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse snowi from hydrobal:  Line:  " + cycle);
                            }
                            temp = hydro.getData(cycle, plantDate, "Endsnow", duplicateDates);
                            try { snowf = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse snowf from hydrobal:  Line:  " + cycle);
                            }
                            if(US) snowi *= 0.0393701;
                            if(US) snowf *= 0.0393701;
                            snowiAcc = snowi;
                            snowfAcc = snowf;
                            
                            temp = hydro.getData(cycle, plantDate, "evap", duplicateDates);
                            try { evap = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse evap from hydrobal:  Line:  " + cycle);
                            }
                            if(US) evap *= 0.0393701;
                            evapAcc += evap;
                            evapLoss = (100 * evap / (rain + irrig + swci + snowi - swcf - snowf));
                            this.setRowValue(subIntervalRow, COLUMN_EVAP_CI, evap);
                            this.setRowValue(subIntervalRow, COLUMN_EVAP_LOSS_CI, evapLoss);
                            
                            temp = hydro.getData(cycle, plantDate, "runoff", duplicateDates);
                            try { runoff = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse runoff from hydrobal:  Line:  " + cycle);
                            }
                            if(US) runoff *= 0.0393701;
                            runoffAcc += runoff;
                            runoffLoss = (100 * runoff / (rain + irrig + swci + snowi - swcf - snowf));
                            this.setRowValue(subIntervalRow, COLUMN_RUNOFF_CI, runoff);
                            this.setRowValue(subIntervalRow, COLUMN_RUNOFF_LOSS_CI, runoffLoss);
                            
                            temp = hydro.getData(cycle, plantDate, "drain", duplicateDates);
                            try { drain = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse drain from hydrobal:  Line:  " + cycle);
                            }
                            if(US) drain *= 0.0393701;
                            drainAcc += drain;
                            drainLoss = (100 * drain / (rain + irrig + swci + snowi - swcf - snowf));
                            this.setRowValue(subIntervalRow, COLUMN_DRAIN_CI, drain);
                            this.setRowValue(subIntervalRow, COLUMN_DRAIN_LOSS_CI, drainLoss);
                            
                            ws = (100 * ((swcf + snowf) - irrig) / ((swci + snowi) + rain));
                            this.setRowValue(subIntervalRow, COLUMN_WATERSTORAGE_CI, ws);
                        }
                        //</editor-fold>
                    }
                    for(int term = 0; term < termins.size(); term ++)
                    {
                        Object[] subIntervalRow = this.createNewRow(true);
                        this.setRowValue(subIntervalRow, COLUMN_CYCLENUMBER_CI, cycle);
                        this.setRowValue(subIntervalRow, COLUMN_RUNID_CI, runIndex);
                        this.setRowValue(subIntervalRow, COLUMN_UNITS_CI, US);
                        this.setRowValue(subIntervalRow, COLUMN_KEY_CI, "CP_" + (term + 1));
                        this.setRowValue(subIntervalRow, COLUMN_INT_CI, false);
                        this.setRowValue(subIntervalRow, COLUMN_CROP_PERIOD_CI, "");
                        this.setRowValue(subIntervalRow, COLUMN_STEM_COUNT_CI, 0.0);
                        inter = termins.get(term);
                        if(inter.getTermin().equals(lastDate)) duplicateDates ++;
                        else lastDate = inter.getTermin();
                        this.setRowValue(subIntervalRow, COLUMN_TERMINATEDATE_CI, new java.sql.Date(inter.getTermin().getTime()));
                        this.setRowValue(subIntervalRow, COLUMN_PREVIOUSDATE_CI, new java.sql.Date(inter.getBegin().getTime()));
                        this.setRowValue(subIntervalRow, COLUMN_CROPINDEX_CI, counter);
                        this.setRowValue(subIntervalRow, COLUMN_CROP_CI, hydro.getData(cycle, 
                                inter.getTermin(), "cropName", duplicateDates));
                        counter ++;
                        
                        //<editor-fold desc="Duration initializer" defaultstate="collapsed">
                        {
                            int dur = 0;
                            long milis;
                            if(inter.getBegin().after(inter.getTermin()))
                            {
                                DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
                                milis = 0;
                                try 
                                { 
                                    Date last = dateFormat.parse("31/12/" + rot_nums); 
                                    milis += TimeUnit.DAYS.convert(last.getTime() 
                                        - inter.getBegin().getTime(), TimeUnit.MILLISECONDS);
                                    milis -= Interval.getLeap(last, inter.getBegin());
                                }
                                catch(ParseException pe) { System.out.println("Failed to parse:  " + "31/12/" + rot_nums); }
                                try 
                                { 
                                    Date first = dateFormat.parse(" 1/ 1/ 1"); 
                                    milis += TimeUnit.DAYS.convert(inter.getTermin().getTime() 
                                            - first.getTime(), TimeUnit.MILLISECONDS);
                                    milis -= Interval.getLeap(inter.getTermin(), first);
                                }
                                catch(ParseException pe) { System.out.println("Failed to parse:  " + " 1/ 1/ 1"); }
                                milis ++;
                            }
                            else 
                            {
                                milis = TimeUnit.DAYS.convert(inter.getTermin().getTime() 
                                    - inter.getBegin().getTime(), TimeUnit.MILLISECONDS);
                                milis -= Interval.getLeap(inter.getBegin(), inter.getTermin());
                            }
                            dur = (int) milis;
                            durAcc += dur;
                            this.setRowValue(subIntervalRow, COLUMN_DURATION_CI, dur);
                        }
                        //</editor-fold>
                        String temp = "";
                        //<editor-fold desc="Transpiration initializer" defaultstate="collapsed">
                        {
                            double transp = 0.0;
                            temp = hydro.getData(cycle, inter.getTermin(), "trans", duplicateDates);
                            try { transp = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse transp from hydrobal:  Line:  " + cycle);
                            }
                            if(US) transp *= 0.0393701;
                            transpAcc += transp;
                            this.setRowValue(subIntervalRow, COLUMN_TRANSP_CI, transp);
                        }
                        //</editor-fold>
                        //<editor-fold desc="Average Height initializer" defaultstate="collapsed">
                        {
                            double height = 0.0;
                            temp = season.getData(cycle, inter.getTermin(), "height", duplicateDates);
                            try { height = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse height from hydrobal:  Line:  " + cycle);
                            }
                            heightAcc += height;
                            this.setRowValue(subIntervalRow, COLUMN_AVG_HEIGHT_CI, height);
                        }
                        //</editor-fold>
                        //<editor-fold desc="Water Use Efficiency or Fallow Efficiency initializer" defaultstate="collapsed">
                        {
                            double wue = 0.0;
                            temp = hydro.getData(cycle, inter.getTermin(), "wateruse_eff", duplicateDates);
                            if(temp != null)
                            {
                                try { wue = Double.parseDouble(temp); }
                                catch(NumberFormatException nfe)
                                {
                                    LOGGER.error("Failure to parse wue from hydrobal:  Line:  " + cycle);
                                }
                            }
                            wue *= 100;
                            this.setRowValue(subIntervalRow, COLUMN_WUE_CI, wue);
                            
                            double falEff = 0.0;
                            temp = hydro.getData(cycle, inter.getTermin(), "falloweff", duplicateDates);
                            if(temp != null)
                            {
                                try { falEff = Double.parseDouble(temp); }
                                catch(NumberFormatException nfe)
                                {
                                    LOGGER.error("Failure to parse falEff from hydrobal:  Line:  " + cycle);
                                }
                            }
                            falAcc += falEff;
                            this.setRowValue(subIntervalRow, COLUMN_FALLOWEFF_CI, falEff);
                        }
                        //</editor-fold>
                        
                        //<editor-fold desc="Biomass, Standing stem and Standing leaf initializer" defaultstate="collapsed">
                        {
                            double stSt = 0.0;
                            double stLe = 0.0;
                            double bio = 0.0;
                            temp = season.getData(cycle, inter.getTermin(), "standingStem", duplicateDates);
                            try { stSt = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse stSt from hydrobal:  Line:  " + cycle);
                            }
                            temp = season.getData(cycle, inter.getTermin(), "standingLeaf", duplicateDates);
                            try { stLe = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse stLe from hydrobal:  Line:  " + cycle);
                            }
                            bio = stSt + stLe;
                            if(US) bio *= 8921.79;
                            stStAcc += stSt;
                            stLeAcc += stLe;
                            bioAcc += bio;
                            this.setRowValue(subIntervalRow, COLUMN_STANDING_STEM_CI, stSt);
                            this.setRowValue(subIntervalRow, COLUMN_STANDING_LEAF_CI, stLe);
                            this.setRowValue(subIntervalRow, COLUMN_BIOMASS_CI, bio);
                        }
                        //</editor-fold>
                        
                        //<editor-fold desc="SWC, evap, runoff, drain, rain, irrigation and water storage initializer" defaultstate="collapsed">
                        {
                            double rain = 0.0;
                            double irrig = 0.0;
                            double swci = 0.0;
                            double swcf = 0.0;
                            double snowi = 0.0;
                            double snowf = 0.0;
                            double evap = 0.0;
                            double runoff = 0.0;
                            double drain = 0.0;
                            double evapLoss = 0.0;
                            double runoffLoss = 0.0;
                            double drainLoss = 0.0;
                            double ws = 0.0;
                            
                            temp = hydro.getData(cycle, inter.getTermin(), "rain", duplicateDates);
                            try { rain = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse rain from hydrobal:  Line:  " + cycle);
                            }
                            if(US) rain *= 0.0393701;
                            rainAcc += rain;
                            this.setRowValue(subIntervalRow, COLUMN_RAIN_CI, rain);
                            
                            temp = hydro.getData(cycle, inter.getTermin(), "irrigation", duplicateDates);
                            try { irrig = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse irrig from hydrobal:  Line:  " + cycle);
                            }
                            if(US) irrig *= 0.0393701;
                            irrAcc += irrig;
                            this.setRowValue(subIntervalRow, COLUMN_IRRIG_CI, irrig);
                            
                            temp = hydro.getData(cycle, inter.getTermin(), "Startswc", duplicateDates);
                            try { swci = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse swci from hydrobal:  Line:  " + cycle);
                            }
                            temp = hydro.getData(cycle, inter.getTermin(), "Endswc", duplicateDates);
                            try { swcf = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse swcf from hydrobal:  Line:  " + cycle);
                            }
                            if(US) swci *= 0.0393701;
                            if(US) swcf *= 0.0393701;
                            swcfAcc = swcf;
                            this.setRowValue(subIntervalRow, COLUMN_INITSWC_CI, swci);
                            this.setRowValue(subIntervalRow, COLUMN_FINALSWC_CI, swcf);
                            this.setRowValue(subIntervalRow, COLUMN_DELTASWC_CI, swcf - swci);
                            
                            temp = hydro.getData(cycle, inter.getTermin(), "Startsnow", duplicateDates);
                            try { snowi = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse snowi from hydrobal:  Line:  " + cycle);
                            }
                            temp = hydro.getData(cycle, inter.getTermin(), "Endsnow", duplicateDates);
                            try { snowf = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse snowf from hydrobal:  Line:  " + cycle);
                            }
                            if(US) snowi *= 0.0393701;
                            if(US) snowf *= 0.0393701;
                            if(firstSWC)
                            {
                                swciAcc = swci;
                                firstSWC = false;
                                snowiAcc = snowi;
                            }
                            snowfAcc = snowf;
                            
                            temp = hydro.getData(cycle, inter.getTermin(), "evap", duplicateDates);
                            try { evap = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse evap from hydrobal:  Line:  " + cycle);
                            }
                            if(US) evap *= 0.0393701;
                            evapAcc += evap;
                            evapLoss = (100 * evap / (rain + irrig + swci + snowi - swcf - snowf));
                            this.setRowValue(subIntervalRow, COLUMN_EVAP_CI, evap);
                            this.setRowValue(subIntervalRow, COLUMN_EVAP_LOSS_CI, evapLoss);
                            
                            temp = hydro.getData(cycle, inter.getTermin(), "runoff", duplicateDates);
                            try { runoff = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse runoff from hydrobal:  Line:  " + cycle);
                            }
                            if(US) runoff *= 0.0393701;
                            runoffAcc += runoff;
                            runoffLoss = (100 * runoff / (rain + irrig + swci + snowi - swcf - snowf));
                            this.setRowValue(subIntervalRow, COLUMN_RUNOFF_CI, runoff);
                            this.setRowValue(subIntervalRow, COLUMN_RUNOFF_LOSS_CI, runoffLoss);
                            
                            temp = hydro.getData(cycle, inter.getTermin(), "drain", duplicateDates);
                            try { drain = Double.parseDouble(temp); }
                            catch(NumberFormatException nfe)
                            {
                                LOGGER.error("Failure to parse drain from hydrobal:  Line:  " + cycle);
                            }
                            if(US) drain *= 0.0393701;
                            drainAcc += drain;
                            drainLoss = (100 * drain / (rain + irrig + swci + snowi - swcf - snowf));
                            this.setRowValue(subIntervalRow, COLUMN_DRAIN_CI, drain);
                            this.setRowValue(subIntervalRow, COLUMN_DRAIN_LOSS_CI, drainLoss);
                            
                            ws = (100 * ((swcf + snowf) - irrig) / ((swci + snowi) + rain));
                            this.setRowValue(subIntervalRow, COLUMN_WATERSTORAGE_CI, ws);
                        }
                        //</editor-fold>
                    }
                    
                    double evapLossAcc = (100 * evapAcc / (rainAcc + irrAcc + swciAcc + snowiAcc - swcfAcc - snowfAcc));
                    double runoffLossAcc = (100 * runoffAcc / (rainAcc + irrAcc + swciAcc + snowiAcc - swcfAcc - snowfAcc));
                    double drainLossAcc = (100 * drainAcc / (rainAcc + irrAcc + swciAcc + snowiAcc - swcfAcc - snowfAcc));
                    double wueAcc = (100 * transpAcc / (rainAcc + irrAcc + swciAcc + snowiAcc - swcfAcc - snowfAcc));
                    double wsAcc = (100 * ((swcfAcc + snowfAcc) - irrAcc) / ((swciAcc + snowiAcc) + rainAcc));
                    
                    this.setRowValue(cropIntervalRow, COLUMN_DURATION_CI, durAcc);
                    this.setRowValue(cropIntervalRow, COLUMN_RAIN_CI, rainAcc);
                    this.setRowValue(cropIntervalRow, COLUMN_IRRIG_CI, irrAcc);
                    this.setRowValue(cropIntervalRow, COLUMN_INITSWC_CI, swciAcc);
                    this.setRowValue(cropIntervalRow, COLUMN_FINALSWC_CI, swcfAcc);
		    this.setRowValue(cropIntervalRow, COLUMN_DELTASWC_CI, swcfAcc - swciAcc);
                    this.setRowValue(cropIntervalRow, COLUMN_TRANSP_CI, transpAcc);
                    this.setRowValue(cropIntervalRow, COLUMN_EVAP_CI, evapAcc);
                    this.setRowValue(cropIntervalRow, COLUMN_RUNOFF_CI, runoffAcc);
                    this.setRowValue(cropIntervalRow, COLUMN_DRAIN_CI, drainAcc);
                    this.setRowValue(cropIntervalRow, COLUMN_EVAP_LOSS_CI, evapLossAcc);
                    this.setRowValue(cropIntervalRow, COLUMN_RUNOFF_LOSS_CI, runoffLossAcc);
                    this.setRowValue(cropIntervalRow, COLUMN_DRAIN_LOSS_CI, drainLossAcc);
                    this.setRowValue(cropIntervalRow, COLUMN_WUE_CI, wueAcc);
                    this.setRowValue(cropIntervalRow, COLUMN_FALLOWEFF_CI, falAcc);
                    this.setRowValue(cropIntervalRow, COLUMN_WATERSTORAGE_CI, wsAcc);
                    this.setRowValue(cropIntervalRow, COLUMN_BIOMASS_CI, bioAcc);
                    this.setRowValue(cropIntervalRow, COLUMN_STANDING_STEM_CI, stStAcc);
                    this.setRowValue(cropIntervalRow, COLUMN_STANDING_LEAF_CI, stLeAcc);
                    this.setRowValue(cropIntervalRow, COLUMN_AVG_HEIGHT_CI, heightAcc);
                }
            }
        }
        c_filled = true;
    }

    @Override
    public String getName() { return NAME; }
    
}
