package org.eclipse.stem.util.analysis;

/*******************************************************************************
 * 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
 *******************************************************************************/

import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.eclipse.emf.common.util.EList;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.stem.analysis.ErrorFunction;
import org.eclipse.stem.analysis.ErrorResult;
import org.eclipse.stem.analysis.LogInitializationException;
import org.eclipse.stem.analysis.impl.ReferenceScenarioDataMapImpl;
import org.eclipse.stem.analysis.impl.ReferenceScenarioDataMapImpl.ReferenceScenarioDataInstance;
import org.eclipse.stem.analysis.util.CSVscenarioLoader;
import org.eclipse.stem.core.scenario.Scenario;
import org.eclipse.stem.util.analysis.views.AnalysisControl;
import org.eclipse.stem.util.analysis.views.EstimatorControl;
import org.eclipse.stem.util.analysis.views.Messages;
import org.eclipse.swt.widgets.TaskBar;

/**
 * Analyzes a {@link Scenario} and compares scenarios
 */
public class ScenarioAnalysisSuite {
	/**
	 * For testing
	 */
	public static final String REFERENCE_ROOT_DIRECTORY = AggregateDataWriter.ANALYSISFOLDER;

	/**
	 * Where we start looking for recorded scenario files
	 */
	public static String REFERENCE_TESTING_DIRECTORY = REFERENCE_ROOT_DIRECTORY;

	/**
	 * Set to an actual folder below (if found)
	 */
	public static String REFERENCE_TESTING_AGGREGATE_FILE = REFERENCE_ROOT_DIRECTORY+File.separator+AggregateDataWriter.AGGREGATE_FOLDERNAME+File.separator+"aggregate.csv";
	
	private static String DEFAULT_AGGREGATE_FILENAME = "aggregate";
	
	private static String COMPARISON_FILE_NAME = "RMSComparisonResults";
		
	/**
	 * Message if directory not found
	 */
	public static final String NOT_FOUND_MSG = Messages.getString("COMMON.NOTFOUND");
	
	/**
	 * Message if data not valid
	 */
	public static final String INVALID_DATA_MSG = Messages.getString("COMMON.NOTDATA");
	
	/**
	 * Message if done
	 */
	public static final String DONE_MSG = Messages.getString("COMMON.DONE");
	
	/**
	 * Message if Ready
	 */
	public static final String READY_MSG = Messages.getString("COMMON.READY");
	
	/**
	 * Message if Working
	 */
	public static final String WORKING_MSG = Messages.getString("COMMON.WORKING");
	
	
	/**
	 * Contains all reference scenario data
	 */
	ReferenceScenarioDataMapImpl referenceScenarioDataMap = null;
	
	/**
	 * Contains all reference scenario data (for comparison)
	 */
	ReferenceScenarioDataMapImpl comparisonScenarioDataMap = null;
	
	/** 
	 * the Estimator instance
	 */
	ScenarioParameterEstimator estimator = null;
	
	AnalysisControl control = null;
	
	
	/**
	 * @param ctrl 
	 * 
	 */
	public ScenarioAnalysisSuite(AnalysisControl ctrl) {
		control = ctrl;
		// Nothing
	}

	/**
	 * Aggregate data
	 * 
	 * @param folder Scenario folder
	 * @param runnableContext Runnable context
	 * @param alpha the Immunity Loss Rate. This is needed to compute the incidence
	 * @return String[] filename where filename[0] = aggregate data file and filename[1] = incidence data file
	 * @throws LogInitializationException Thrown if problem reading data
	 */
	
	public String aggregateData(String folder, IRunnableContext runnableContext, double alpha) throws LogInitializationException{	
		CSVscenarioLoader loader = new CSVscenarioLoader(folder);
		int maxResolution = loader.getMaxResolution(CSVscenarioLoader.UNKNOWN_POP_IDENTIFIER_KEY);
        ReferenceScenarioDataMapImpl map = loader.parseAllFiles(CSVscenarioLoader.UNKNOWN_POP_IDENTIFIER_KEY, maxResolution);
        String aggregateFileName = getAggregateFileName(folder);
        ReferenceScenarioDataInstance aggregatedData = map.aggregateScenarioData(runnableContext);
        AggregateDataWriter writer = new AggregateDataWriter(folder, aggregateFileName);
     
		return writer.logDataInstance(aggregatedData, alpha);
	}
	
	
	/**
	 * Aggregate data but filter the locations that get aggregate to match the locations
	 * in the referenceFolder
	 * @param referenceFolder 
	 * @param folder Scenario folder
	 * @param runnableContext Runnable context
	 * @param alpha the Immunity Loss Rate. This is needed to compute the incidence
	 * @return String[] filename where filename[0] = aggregate data file and filename[1] = incidence data file
	 * @throws LogInitializationException Thrown if problem reading data
	 */
	
	public String aggregateByFilter(String referenceFolder, String folder, IRunnableContext runnableContext, double alpha) throws LogInitializationException{			
		CSVscenarioLoader refLoader = new CSVscenarioLoader(referenceFolder);
		int maxRes = refLoader.getMaxResolution(CSVscenarioLoader.UNKNOWN_POP_IDENTIFIER_KEY);
		Set<String> locationsToAggregate = refLoader.getLocations(CSVscenarioLoader.UNKNOWN_POP_IDENTIFIER_KEY, maxRes);	
		CSVscenarioLoader loader = new CSVscenarioLoader(folder);
		int maxResolution = loader.getMaxResolution(CSVscenarioLoader.UNKNOWN_POP_IDENTIFIER_KEY);
        ReferenceScenarioDataMapImpl map = loader.parseAllFiles(locationsToAggregate, CSVscenarioLoader.UNKNOWN_POP_IDENTIFIER_KEY, maxResolution);
        String aggregateFileName = getAggregateFileName(folder);
        ReferenceScenarioDataInstance aggregatedData = map.aggregateScenarioData(runnableContext);
        AggregateDataWriter writer = new AggregateDataWriter(folder, aggregateFileName);
          
		return writer.logDataInstance(aggregatedData, alpha);
	}
	
	/**
	 * Estimates the model parameters for scenario data located in the referenceDirectory
	 * @param dataMap Data
	 * @param parameterEstimatorMethod Which method do we use to estimate
	 * @param runnableContext Context used for long running tasks
	 * @return a set of fitted model parameters
	 */
	public ModelParameters estimateParameters(ReferenceScenarioDataMapImpl dataMap, ParameterEstimatorMethod parameterEstimatorMethod, IRunnableContext runnableContext) {	
			this.referenceScenarioDataMap = dataMap;
			estimator = new ScenarioParameterEstimator(this.referenceScenarioDataMap, parameterEstimatorMethod);
			
			ModelParameters bestEstimate = new ModelParameters();
			
			// The user can set this
			boolean sumAllLocations = false;
			Map<String,Object> controlParametersMap = control.getControlParametersMap();
			if(controlParametersMap != null) {
				sumAllLocations = ((Boolean) controlParametersMap.get(EstimatorControl.SUM_LOCATIONS_KEY)).booleanValue();
			}
			
			if(sumAllLocations) {
				bestEstimate = estimator.averageThenEstimateParameters(controlParametersMap, runnableContext);
			} else {
				Map<String,ModelParameters> fittedParameters = estimator.estimateParameters(controlParametersMap, runnableContext);		
				bestEstimate.average(fittedParameters);
			}
			
			
		    return bestEstimate;
	}
	
	/**
	 * The aggregate file is named after the data directory under csv
	 * @param dir
	 * @return
	 */
	private static String getAggregateFileName(String dir) {
		int start = dir.lastIndexOf(File.separatorChar);
		
		String filename = DEFAULT_AGGREGATE_FILENAME;
		if(start >=0) {
			filename = dir.substring(start+1,dir.length());
		}
		filename = filename +".csv";
		return filename;
	}
	
	/**
	 * Root Mean Square Difference Comparison
	 * Compares data from two scenarios: the referenceDirectory and the comparisonDirectory
	 * The comparison directory will recursively traverse directories to search for log files.
	 * When found, a comparison is done and the results is written to the comparison directory
	 * including the parameters used for the simulation
	 * 
	 * @param referenceDirectory
	 * @param comparisonDirectory
	 * @param runnableContext Context for long running task
	 * @return ErrorResult
	 * @throws LogInitializationException 
	 */
	
	public ErrorResult compare(String referenceDirectory, String comparisonDirectory, IRunnableContext runnableContext, ErrorFunction errorfunc) throws LogInitializationException {
		CSVscenarioLoader referenceLoader = new CSVscenarioLoader(referenceDirectory);
		// We will write the result to a file in the comparison directory folder
		String resultFile = COMPARISON_FILE_NAME;
		
		CSVAnalysisWriter resultWriter = new CSVAnalysisWriter(resultFile);	
		Map<Map<String, String>, ErrorResult> result = new HashMap<Map<String, String>, ErrorResult>();
		compareRecursive(referenceLoader, comparisonDirectory, result, runnableContext, errorfunc);
		resultWriter.logData(result);
		resultWriter.flushLoggerData();
		resultWriter.closeLoggerData();
		// Find the smallest RMS difference and return its double list
		double smallestError = Double.MAX_VALUE;
		ErrorResult returnError=null;
		for(Entry<Map<String, String>,ErrorResult> entry : result.entrySet()) {
			ErrorResult res = entry.getValue();
			// Compute average
			double error = 0.0;
			if(res !=null) {
				error = res.getError();
			}
			if(error < smallestError) {smallestError = error;returnError = res;}
		}
		return returnError;
	}
	
	/**
	 * Root Mean Square Difference Comparison
	 * Compares data from two scenarios: the referenceDirectory and the comparisonDirectory
	 * The comparison directory will recursively traverse directories to search for log files.
	 * When found, a comparison is done and the results is written to the comparison directory
	 * including the parameters used for the simulation
	 * 
	 * @param referenceLoader
	 * @param comparisonDirectory
	 * @param result
	 * @param runnableContext Context for long running task
	 * @throws LogInitializationException 
	 */
	public void compareRecursive(CSVscenarioLoader referenceLoader, String comparisonDirectory, Map<Map<String, String>, ErrorResult> result, IRunnableContext runnableContext, ErrorFunction errorfunc) throws LogInitializationException {		
		try {
			CSVscenarioLoader comparisonLoader = new CSVscenarioLoader(comparisonDirectory);
			// A valid scenario folder was found. Do the comparison
			ErrorResult res = _compare(referenceLoader, comparisonLoader, runnableContext, errorfunc);
			Map<String, String>runParms = comparisonLoader.getRunParameters();
			result.put(runParms, res);
		} catch(LogInitializationException sie) {
			// The folder did not contain valid log files. Recurse down subdirectories
			// looking for log files
			File f = new File(comparisonDirectory);
			String [] dirs = f.list();
			if(dirs != null) 
				for(String dir : dirs) compareRecursive(referenceLoader, comparisonDirectory+File.separator+dir, result, runnableContext, errorfunc);
		}
	}

		
	/**
	 * Root Mean Square Difference Comparison
	 * Compares data from two scenarios: the referenceDirectory and the comparisonDirectory
	 * @param refLoader
	 * @param compLoader
	 * @param runnableContext Context for long running {@link TaskBar}
	 * @param ErrorFunc Error function
	 * @return the mean square diff
	 * @throws LogInitializationException 
	 */
	private ErrorResult _compare(CSVscenarioLoader refLoader, CSVscenarioLoader compLoader, IRunnableContext runnableContext, ErrorFunction errorfunc) throws LogInitializationException {
			int maxRef = refLoader.getMaxResolution(CSVscenarioLoader.UNKNOWN_POP_IDENTIFIER_KEY);		
			int maxComp = compLoader.getMaxResolution(CSVscenarioLoader.UNKNOWN_POP_IDENTIFIER_KEY);				
			// Find the highest resolution common two both locations and 
			// use it for comparison.
			int actualRes = (maxRef > maxComp)?maxComp:maxRef;
				
			this.referenceScenarioDataMap = refLoader.parseAllFiles(CSVscenarioLoader.UNKNOWN_POP_IDENTIFIER_KEY,actualRes);
					
			this.comparisonScenarioDataMap = compLoader.parseAllFiles(CSVscenarioLoader.UNKNOWN_POP_IDENTIFIER_KEY, actualRes);
					
			ErrorCalculator msd = new ErrorCalculator(referenceScenarioDataMap, comparisonScenarioDataMap, errorfunc);
					
			ErrorResult result = 	msd.solve(runnableContext);	
			return result;
	}
	
	/**
	 * 
	 * @param directory
	 * @return true is a data directory exists
	 */
	public boolean validate(String directory) {
		return CSVscenarioLoader.validate(directory);
	}
	
	/**
	 * Root Mean Square Difference Comparison
	 * Compares data from two scenarios: the referenceDirectory and the comparisonDirectory
	 * @param referenceDirectory
	 * @param comparisonDirectory
	 * @param runnableContext Context for long running tasks
	 * @return the mean square diff
	 * @throws LogInitializationException Thrown if problems encountered reading data
	 */
	
	public List<PhaseSpaceCoordinate[]> getLyapunovTrajectory(String referenceDirectory, String comparisonDirectory, IRunnableContext runnableContext) throws LogInitializationException {
		   
			// for reference and for single scenario analysis
			CSVscenarioLoader refLoader = new CSVscenarioLoader(referenceDirectory);
			int maxRef = refLoader.getMaxResolution(CSVscenarioLoader.UNKNOWN_POP_IDENTIFIER_KEY);
			if(maxRef <=-1) return null;
			// for testing comparison functions
			CSVscenarioLoader compLoader = new CSVscenarioLoader(comparisonDirectory);
			int maxComp = compLoader.getMaxResolution(CSVscenarioLoader.UNKNOWN_POP_IDENTIFIER_KEY);
			int actualRes = (maxRef > maxComp)?maxComp:maxRef;
			if(actualRes<=-1) return null;
			this.referenceScenarioDataMap = refLoader.parseAllFiles(CSVscenarioLoader.UNKNOWN_POP_IDENTIFIER_KEY,actualRes);
			this.comparisonScenarioDataMap = compLoader.parseAllFiles(CSVscenarioLoader.UNKNOWN_POP_IDENTIFIER_KEY,actualRes);
			
			LyapunovAnalysis lyap = new LyapunovAnalysis(referenceScenarioDataMap, comparisonScenarioDataMap, runnableContext);
			
			List<PhaseSpaceCoordinate[]> retVal = lyap.getLyapunovTrajectory(runnableContext);	
			return retVal;
	}
	
	/**
	 * 
	 * @param trajectoryList
	 * @return the deviation as List(double[])
	 */
	public static List<EList<Double>> getCumulativePhaseSpaceDeviation(List<PhaseSpaceCoordinate[]> trajectoryList) {
		List<EList<Double>> deviation = LyapunovAnalysis.getCumulativePhaseSpaceDeviation(trajectoryList);
		return deviation;
		
	}
	
	/**
	 * 
	 * @return the current estimator
	 */
	public ParameterEstimator getEstimator() {
		return estimator.getEstimator();
	}



}
