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.LogInitializationException;

/*******************************************************************************
 * 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 LogInitializationException {
		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);
	}
}
