/*******************************************************************************
 * Copyright (c) 2009 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
 *******************************************************************************/

package org.eclipse.stem.analysis.impl;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.stem.analysis.AnalysisFactory;
import org.eclipse.stem.analysis.AnalysisPackage;
import org.eclipse.stem.analysis.ErrorResult;
import org.eclipse.stem.analysis.ReferenceScenarioDataMap;
import org.eclipse.stem.analysis.ThresholdErrorFunction;
import org.eclipse.stem.analysis.impl.ReferenceScenarioDataMapImpl.ReferenceScenarioDataInstance;

/**
 * <!-- begin-user-doc -->
 * An implementation of the model object '<em><b>Threshold Error Function</b></em>'.
 * <!-- end-user-doc -->
 * <p>
 * </p>
 *
 * @generated
 */
public class ThresholdErrorFunctionImpl extends ErrorFunctionImpl implements ThresholdErrorFunction {
	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated NOT
	 */
	public ThresholdErrorFunctionImpl() {
		super();
	}

	/**
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	@Override
	protected EClass eStaticClass() {
		return AnalysisPackage.Literals.THRESHOLD_ERROR_FUNCTION;
	}

	/**
	 * Timeseries data for both data sets with common locations
	 */
	Map<String,List<Double>> commonInfectiousLocationsA = new HashMap<String,List<Double>>();
	Map<String,List<Double>> commonInfectiousLocationsB = new HashMap<String,List<Double>>();

	/**
	 * Max infectious per location
	 */
	Map<String,Double> maxInfA = new HashMap<String,Double>();
	Map<String,Double> maxInfB = new HashMap<String,Double>();
	
	/**
	 * The Result
	 */
	public double[] meanSqDiff;
	
	/*
	 * time
	 */
	public double[] time;
	
	protected AnalysisFactory aFactory = new AnalysisFactoryImpl();

	// This is the threshold of the maximum peak for both data sets
	// where we consider the error
	
	protected static double THRESHOLD = 0.1;
	
	/**
	 * calculate delta for a threshold error function
	 * 
	 * 
	 * @override
	 */
	
	public ErrorResult calculateError(ReferenceScenarioDataMap reference, ReferenceScenarioDataMap data) {
		final ReferenceScenarioDataMapImpl _ref = (ReferenceScenarioDataMapImpl)reference;
		final ReferenceScenarioDataMapImpl _data = (ReferenceScenarioDataMapImpl)data;

		double denominator = 0.0;
		// Clear
		time = null;
		
		Iterator<String> iteratorA = _ref.getLocations().iterator();
		int maxTime = -1;
		while(iteratorA.hasNext()) {
			String id = iteratorA.next();
					
			if(_data.containsLocation(id)) {
				// get the lists of data only for those locations that are common to both maps						ReferenceScenarioDataInstance dataMapA = mapA.getLocation(id);
				ReferenceScenarioDataInstance dataMapA = _ref.getLocation(id);
				List<Double> dataAI = getInfectious(dataMapA);
			
				commonInfectiousLocationsA.put(id,dataAI);
												
				// Map B
				ReferenceScenarioDataInstance dataMapB = _data.getLocation(id);
				List<Double> dataBI = getInfectious(dataMapB);
				commonInfectiousLocationsB.put(id,dataBI);
												
				// Find the peak in both data sets and remember. It will be used
				// to determine the threshold
				
				double maxA = -1;
				for(double d : dataAI) if(d > maxA) maxA = d;
				
				double maxB = -1;
				for(double d : dataBI) if(d > maxB) maxB = d;
	
				maxInfA.put(id, maxA);
				maxInfB.put(id, maxB);
				
				// init the array size
				if (maxTime == -1) maxTime = dataAI.size();
						
				// dimension the arrays to the length of the SMALLEST array for which we have data
				if(maxTime >= dataBI.size() ) maxTime = dataBI.size();
				if(maxTime >= dataAI.size() ) maxTime = dataAI.size();
			}// if
		}// while
		if(maxTime<=0) maxTime = 0;
		if(time==null) {
			time = new double[maxTime];
			meanSqDiff = new double[maxTime];
			for(int i = 0; i < maxTime; i ++) {
				time[i] = i;
				meanSqDiff[i] = 0.0;
			}
		}
		
		// Now figure out the actual error
		
		double[] maxPopulation = new double[time.length];

		for(int icount =0; icount < time.length; icount ++) {
			maxPopulation[icount] = 0.0;
			Iterator<String> iter = commonInfectiousLocationsA.keySet().iterator();
			////////////////////////
			// all locations
			while(iter.hasNext()) {
				String id = iter.next();
				List<Double> dataAI = commonInfectiousLocationsA.get(id);
				List<Double> dataBI = commonInfectiousLocationsB.get(id);
												
				double iA = dataAI.get(icount).doubleValue();
				double iB = dataBI.get(icount).doubleValue();
		
				// double denom = (iA+iB)/2.0;
				// square of the average fraction of infectious people
				// denom *= denom;
				double maxA = maxInfA.get(id);
				double maxB = maxInfB.get(id);

				if ((iA > maxA*THRESHOLD) || (iB > maxB*THRESHOLD)) {
					// we have a location with nonzero data
					// square of the DIFFERENCE
							
					// Changed 2/4/09. Drop the S data comparison
					//double term = ((iA - iB) * (iA - iB))
					//		+ ((sA - sB) * (sA - sB));
							
					double term = Math.abs(iA - iB);
					meanSqDiff[icount] += term;
					if(iA > iB) denominator+= iA; else denominator+= iB; 
				}					
			}// all locations
				
            ////////////////////////
	
		}// for all time
		
		
		// Sum all errors and divide by time
		
		double result = 0.0;
		BasicEList<Double> list = new BasicEList<Double>();
		for(int i=0;i<time.length;++i) {
			meanSqDiff[i] = meanSqDiff[i] / denominator;
			result += meanSqDiff[i];
			list.add(meanSqDiff[i]);
		}
		
		ErrorResult resultobj = aFactory.createErrorResult();
		resultobj.setErrorByTimeStep(list);
		resultobj.setError(result);
		return resultobj;	
	}
	
} //ThresholdErrorFunctionImpl
