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.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author jonathanhornbaker
 */
public class HarvestParser 
{
    private DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
    /**
     * harvestData contains the entirety of the harvest file in this structure:
     * 
     * List<Map<Date, List<Map<String, String> > > >:  A one to one relationship
     *              between the elements of this struct and the lines in the file.
     * Map<Date, List<Map<String, String> > >:  For each date, we keep track of the data.
     *              the termination date is our unique key, so we can coordinate between files.
     * List<Map<String, String> >:  In case of multiple events in a day, we need a list to
     *              keep the data in order.
     * Map<String, String>:  A direct mapping of key to value.
     * 
     * Please note that this structure SHOULD NOT ever be edited outside of the parse method,
     * only read.
     */
    private List<Map<Date, List<Map<String, String> > > > harvestData;
    private String[] keySet = { "date", "cropName", "dryYield", "unitsDY", "dryResidue",
                "unitsDR",  "harvInd", "unitsHI", "wetYield", "unitsWY", "moistCont", "unitsMC"};
    
    public HarvestParser()
    {
        harvestData = new ArrayList<Map<Date, List<Map<String, String> > > >();
    }
    
    /**
     * This will take any valid harvest file and parse it, with each line in the file
     * corresponding to an item in the harvestData list.  Each item will consist of a
     * hashmap, using termination date as the unique key to identify all data in another
     * map where the header is the key and the data is the double.
     * @param fileName 
     */
    public void parse(String fileName)
    {
        try
        {
            TFile file = new TFile(fileName);
            BufferedReader reader = new BufferedReader(new TFileReader(file));
            String line;
            while(((line = Interval.getLine(reader)) != null))
            {
                Map<Date, List<Map<String, String> > > lineData = new HashMap<Date, List<Map<String, String> > >();
                String[] seasonLine = line.split("\\|", -1);
                Date curDate;
                Map<String, String> dateData = new HashMap<String, String>();
                List<Map<String, String> > multiDate = new ArrayList<Map<String, String> >();
                for(int index = 0; index < seasonLine.length; index ++)
                {
                    if((index % keySet.length) == 0)
                    {
                        try
                        {
                            if(seasonLine[index].trim().equals("")) continue;
                            curDate = dateFormat.parse(seasonLine[index].trim()); 
                            dateData = new HashMap<String, String>();
                            multiDate = lineData.get(curDate);
                            if(multiDate == null)
                            {
                                multiDate = new ArrayList<Map<String, String> >();
                                lineData.put(curDate, multiDate);
                            }
                            multiDate.add(dateData);
                        }
                        catch(ParseException pe) { throw new IOException("Termination Date out of place:  " + index); }
                    }
                    else
                    {
                        dateData.put(keySet[index % keySet.length], seasonLine[index]);
                    }
                }
                harvestData.add(lineData);
            }
        }
        catch(IOException ioe) { ioe.printStackTrace(); }
    }
    
    /**
     * Returns the data associated with the set of inputs.
     * @param cycleNum The line number (base one indexing)
     * @param termination The termination date
     * @param dataName The key of the column of output.
     * @param order  If there are multiple terminations on this day, the index of
     *                      the requested date (base zero indexing.
     * @return 
     */
    public String getData(int cycleNum, Date termination, String dataName, int order)
    {
        cycleNum --;
        Map<Date, List<Map<String, String> > > dateMap = harvestData.get(cycleNum);
        List<Map<String, String> > dateList = dateMap.get(termination);
        if(!(order < dateList.size())) return null;
        Map<String, String> keyMap = dateList.get(order);
        return keyMap.get(dataName);
    }
    
    /**
     * Returns true if the harvestData struct is empty.
     * @return 
     */
    public boolean isEmpty()
    {
        return harvestData.isEmpty();
    }
    
    /**
     * Returns the total number of cycles, i.e. lines.
     * @return 
     */
    public int cycle() { return harvestData.size(); }
    
    public static void main(String[] args)
    {
        HarvestParser parse = new HarvestParser();
        parse.parse("/home/jonathanhornbaker/Documents/WEPSFiles/Runs/alfalfa_4_nospray_cycletest_1.wjr/harvest_si.out");
        
        int hello = 5;
    }
}
