package org.eclipse.stem.analysis.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;

import org.eclipse.stem.analysis.ScenarioInitializationException;

/*******************************************************************************
 * Copyright (c) 2007, 2008 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/


/**
 * Adds methods for streaming data instead of loading all data files into memory
 */
public class CSVScenarioStreamer extends CSVscenarioLoader {

	public static final int NUM_LEAD_COLS = 2;
	
	Map<Integer, Map<String, BufferedReader>> streamReaders = new HashMap<Integer, Map<String, BufferedReader>>();
	Map<Integer, Map<String, Integer>> streamReaderCurrentRow = new HashMap<Integer, Map<String, Integer>>();
	Map<Integer, Map<String, List<Double>>> streamReadersLastRow = new HashMap<Integer, Map<String, List<Double>>>();
	
	Map<Integer, List<String>> headersMap = new HashMap<Integer, List<String>>();
	
	private int row = -1; // Which row
	
	/**
	 * @param path
	 */
	
	public CSVScenarioStreamer(String path) throws ScenarioInitializationException {
		super(path);
	}
	
	
	/**
	 * prepareForStreaming
	 * 
	 * @param resolution The desired resolution, or -1 of all files should be streamed
	 */
	
	public void prepareForStreaming(int resolution) throws IOException {
		
		for(int i = 0; i < diseaseData.size(); i ++) {
			File f = diseaseData.get(i);
			String name = f.getName();
			if(f.getName().startsWith(".")) continue;//$NON-NLS-1$
			int _idx = name.lastIndexOf('_');
			int dotidx = name.lastIndexOf('.');
			if(_idx <0 || dotidx < 0 || dotidx < _idx) continue; // not a data file
			String state = name.substring(0, _idx);

			// discovered a state
			registerKey(state);
			
			int res = Integer.parseInt(name.substring(_idx+1, dotidx));
			if(resolution != -1 && res != resolution) continue; // wrong resolution
			openFile(state, f, res);
		}
	}
	
	/**
	 * openFile. Open data file and prepare for streaming
	 * 
	 * @param state The state
	 * @param File file
	 * @param adminLevel
	 */
	
	public void openFile(String state, File f, int adminLevel) throws IOException {
		BufferedReader reader = new BufferedReader(new FileReader(f));
		
		if(!streamReaders.containsKey(adminLevel)) {
			streamReaders.put(adminLevel, new HashMap<String, BufferedReader>());
			streamReaderCurrentRow.put(adminLevel, new HashMap<String, Integer>());
			streamReadersLastRow.put(adminLevel, new HashMap<String, List<Double>>());
		}
		Map<String, BufferedReader>stateReaderMap = streamReaders.get(adminLevel);
		Map<String, Integer>stateRowMap = streamReaderCurrentRow.get(adminLevel);
		Map<String, List<Double>>stateRowData = streamReadersLastRow.get(adminLevel);
		stateReaderMap.put(state, reader);
		stateRowMap.put(state, -1); // no row read yet, first row is row 0
		stateRowData.put(state, null); // no data yet
		String header;
		
		if ( (header=reader.readLine()) != null ) { 
			if(!headersMap.containsKey(adminLevel)) {
				List<String>headerElements = new ArrayList<String>();
				headersMap.put(adminLevel, headerElements);
				StringTokenizer st = new StringTokenizer(header, ",");//$NON-NLS-1$
	
				int col = 0;
				while (st.hasMoreTokens()) {
					String val = st.nextToken().trim();
					if(col < NUM_LEAD_COLS) {++col;continue;}
					headerElements.add(val);
					++col;
				}
			}
		} // read the header
		/////////////////////
	}
	
	/**
	 * streamRow Stream next row of data
	 * 
	 * 
	 * @param adminLevel which admin level
	 * @param state Which state (e.g. S)
	 * @return List<Double> The data, or null if end of line is encountered;
	 */
	
	public List<Double>streamRow(int adminLevel, String state) throws IOException {
		BufferedReader br = streamReaders.get(adminLevel).get(state);
		if(br == null) return null; // stream is closed
		String data;
		if ( (data=br.readLine()) != null ) { 
			
			if(streamReadersLastRow.get(adminLevel).get(state) == null) 
				streamReadersLastRow.get(adminLevel).put(state, new ArrayList<Double>());
			List<Double>result = streamReadersLastRow.get(adminLevel).get(state);
			result.clear();
			StringTokenizer st = new StringTokenizer(data, ",");//$NON-NLS-1$
			
			int col = 0;
			while (st.hasMoreTokens()) {
				String val = st.nextToken().trim();
				if(col < NUM_LEAD_COLS) {++col;continue;}
				result.add(Double.parseDouble(val));
				++col;
			}
			streamReaderCurrentRow.get(adminLevel).put(state, streamReaderCurrentRow.get(adminLevel).get(state)+1);
			
			return result;
		}
		br.close();
		streamReaders.get(adminLevel).put(state, null);// gc reader
		return null; // end of file reached
	}
	
	public int getCurrentRow(int adminLevel, String state) {
		return streamReaderCurrentRow.get(adminLevel).get(state);
	}
	
	/**
	 * streamRow Stream next row of data
	 * 
	 * 
	 * @param adminLevel which admin level
	 * @param state Which state (e.g. S)
	 * @return List<Double> The data
	 */
	
	public List<Double>getLastFetchedRow(int adminLevel, String state) {
		List<Double>result = streamReadersLastRow.get(adminLevel).get(state);
		return result;
	}

	public int getDataPosition(int adminLevel, String key) {
		return headersMap.get(adminLevel).indexOf(key);
	}
}
