/**
 * Copyright (c) 2005 by Kevin Bierhoff
 */
package edu.cmu.cs.l3.trace;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.util.HashMap;
import java.util.Iterator;

/**
 * @author Kevin
 *
 */
public class TraceAnalysis {
	
	private HashMap counters = new HashMap();
	
	public static final String DEFAULT_TRACE_FILE_NAME = "trace.out";

	/**
	 * 
	 */
	public TraceAnalysis() {
		this(DEFAULT_TRACE_FILE_NAME);
	}
	
	public TraceAnalysis(String traceFileName) {
		try {
			LineNumberReader trace = new LineNumberReader(new FileReader(traceFileName));
			// TODO adjust this number to speed up trace file parsing / read the complete file
			int max = 10000000;
			String line = trace.readLine();
			while(line != null && --max > 0) {
				int pos = line.indexOf(':');
				if(pos < 0)
					// malformed line
					continue;
				
				Integer fct = Integer.valueOf(line.substring(0, pos));
				Integer path = Integer.valueOf(line.substring(pos + 1));
				addPath(fct, path);
				
				line = trace.readLine();
			}
			trace.close();
		} 
		catch (NumberFormatException e) {
			System.out.println("Number formatting error in trace file.");
		}
		catch (FileNotFoundException e) {
			System.out.println("No trace file found.");
		} 
		catch (IOException e) {
			System.err.println("Error reading trace file.");
			e.printStackTrace();
		}
	}
	
	/* public TraceAnalysis(String traceFileName) {
		try {
			LineNumberReader trace = new LineNumberReader(new FileReader(traceFileName));
			// TODO adjust this number to speed up trace file parsing / read the complete file
			int max = 10000000;
			String line = trace.readLine();
			while(line != null && --max > 0) {
				int pos = line.indexOf(':');
				if(pos < 0)
					// malformed line
					continue;
				
				try {
					Integer fct = Integer.valueOf(line.substring(0, pos));
					Integer path = Integer.valueOf(line.substring(pos + 1));
					addPath(fct, path);
				} 
				catch (NumberFormatException e) {
					// malformed line
				}
				
				try {
					line = trace.readLine();
				} 
				catch (IOException e) {
					// try again
					line = trace.readLine();			}
			}
			trace.close();
		} 
		catch (FileNotFoundException e) {
			System.out.println("No trace file found.");
		} 
		catch (IOException e) {
			System.err.println("Error reading trace file.");
			e.printStackTrace();
		}
	}*/
	
	public int getMostFrequentPath(int function) {
		Integer f = new Integer(function);
		HashMap trace = getFunctionTrace(f);
		return highestCount(trace);
	}
	
	private static int highestCount(HashMap trace) {
		Integer result = null;
		int maxValue = -1;
		for(Iterator it = trace.keySet().iterator(); it.hasNext(); ) {
			Integer p = (Integer) it.next();
			if(((Integer) trace.get(p)).intValue() > maxValue) {
				maxValue = ((Integer) trace.get(p)).intValue();
				result = p;
			}
		}
		return result == null ? -1 : result.intValue();
	}
	
	protected HashMap getFunctionTrace(Integer functionIndex) {
		HashMap result = (HashMap) counters.get(functionIndex);
		if(result == null) {
			result = new HashMap();
			counters.put(functionIndex, result);
		}
		return result;
	}
	
	protected void addPath(Integer function, Integer path) {
		HashMap functionTrace = getFunctionTrace(function);
		functionTrace.put(path, new Integer(getPathCount(functionTrace, path) + 1));
	}

	private static int getPathCount(HashMap functionTrace, Integer path) {
		Integer result = (Integer) functionTrace.get(path);
		if(result == null)
			return 0;
		return result.intValue();
	}
	
}
