/*******************************************************************************
 * Copyright (c) 2006, 2007, 2008, 2011 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.loggers.csv.logger;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
import org.eclipse.emf.edit.provider.IItemPropertySource;
import org.eclipse.stem.adapters.time.TimeProvider;
import org.eclipse.stem.adapters.time.TimeProviderAdapterFactory;
import org.eclipse.stem.core.common.CommonPackage;
import org.eclipse.stem.core.graph.DynamicLabel;
import org.eclipse.stem.core.graph.IntegrationLabel;
import org.eclipse.stem.core.graph.IntegrationLabelValue;
import org.eclipse.stem.core.graph.Node;
import org.eclipse.stem.core.graph.NodeLabel;
import org.eclipse.stem.core.model.Decorator;
import org.eclipse.stem.core.model.IntegrationDecorator;
import org.eclipse.stem.core.model.STEMTime;
import org.eclipse.stem.definitions.adapters.relativevalue.RelativeValueProvider;
import org.eclipse.stem.definitions.adapters.relativevalue.RelativeValueProviderAdapter;
import org.eclipse.stem.definitions.adapters.relativevalue.RelativeValueProviderAdapterFactory;
import org.eclipse.stem.diseasemodels.standard.DiseaseModel;
import org.eclipse.stem.diseasemodels.standard.DiseaseModelLabel;
import org.eclipse.stem.loggers.csv.Activator;
import org.eclipse.stem.loggers.csv.CSVLogger;
import org.eclipse.stem.populationmodels.standard.DemographicPopulationModel;
import org.eclipse.stem.populationmodels.standard.PopulationGroup;
import org.eclipse.stem.populationmodels.standard.PopulationModel;
import org.eclipse.stem.populationmodels.standard.PopulationModelLabel;

/**
 * STEM Decorator logger that writes the output values of node labels for the
 * decorator's properties to a entry-delimeted log file.  This class can be 
 * used to create various types of "separated-value" log files, including
 * comma and tab separated.
 *
 */
public class DelimetedFileDecoratorLogger 
{
	public static final Comparator<Node> NODE_SORTER = new Comparator<Node>() {
		public int compare(Node n1, Node n2) {
			String s1 = n1.getURI().toString();
			String s2 = n2.getURI().toString();
			return s1.compareTo(s2);
		}
	};
	
	
	private final List<String> EXCLUDED_NODES = new ArrayList<String>(Arrays.asList(Constants.EXCLUDED_NODE_DEFAULTS));
	
	private final Map<StateLevelMap, DelimetedWriter> logWriters = new HashMap<StateLevelMap, DelimetedWriter>();
	
	private final Map<Integer, List<Node>> sortedNodeList = new HashMap<Integer, List<Node>>();
	
	private final DelimetedFileSimulationLogger simulationLogger;
	
	private final IntegrationDecorator decorator;
	
	private final CSVLogger logger;


	private File logDirectory;
	
	private Map<Node,Integer> nodeLevels;
	
	private String decoratorName;
	
	private TimeProvider timeProvider;
	
	private int interationCount = 0;

	private boolean logIntegers = false;
	private boolean beforeStart = false;

	private List<Integer> resolutionLevels;


	private List<String> populationIdentifiers = null;
	
	public DelimetedFileDecoratorLogger(
			DelimetedFileSimulationLogger simulationLogger,
			IntegrationDecorator decorator) {
		this.simulationLogger = simulationLogger;
		this.decorator = decorator;
		this.logger = simulationLogger.getLogger();
	}


	/**
	 * Starts the decorator logger.  If enabled, writes the 
	 * simulation parameters then sets up each log writer for the given properties
	 */
	public void start() 
	{
		if (logger.isLogRunParameters()) {
			writeRunParameters();
		}
		
		setupPropertyLoggers();
	}

	/**
	 * Stops the decorator logger.  Flushes and closes each log writer
	 */
	public void stop() 
	{
		flush();
		for (DelimetedWriter fw : logWriters.values()) {
			FileUtils.safeClose(fw);
		}
		logWriters.clear();
		nodeLevels = null;
	}
	
	/**
	 * Flushes the buffer on each of the log writers
	 */
	public void flush()
	{
		for (DelimetedWriter fw : logWriters.values()) {
			try {
				fw.flush();
			} catch (IOException e) {
			}
		}
	}
	
	/**
	 * Writes the current label property values for each node at the given simulation step time
	 * 
	 * @param event
	 */
	public void log() 
	{
		interationCount++;

		List<String> decoratorPopulations = getPopulationIdentifiers();

		for (Integer resolution : getResolutionLevels()) {
			for (Node node : getSortedNodesForAdminlevel(resolution, nodeLevels)) {
				for (String populationIdentifier : decoratorPopulations) {
					NodeLabel label = getMatchingLabel(node, populationIdentifier);
					if(label == null || !(label instanceof IntegrationLabel)) {
						continue;
					}

					IntegrationLabel dmLabel = (IntegrationLabel)label;					
					IntegrationLabelValue labelValue = (IntegrationLabelValue)dmLabel.getCurrentValue();					

					for (IItemPropertyDescriptor itemDescriptor : getPropertiesForLabel(dmLabel)) {
						StateLevelMap key = new StateLevelMap(populationIdentifier, itemDescriptor.getDisplayName(itemDescriptor), resolution);
						DelimetedWriter fw = logWriters.get(key);
						if(fw == null) {
							continue;
						}
						
						try {
							// Before writing the values for the first location,
							// add iteration, time columns
							if(fw.isEmptyLine()) {
								fw.writeEntry(interationCount);
								fw.writeEntry(Constants.LOG_DATE_FORMATTER.format(getScenarioTime().getTime()));
							}
							
							// Get the feature and label value for the feature
							EStructuralFeature feature = (EStructuralFeature) itemDescriptor.getFeature(null);
							double value = ((Double)labelValue.eGet(feature)).doubleValue();

							if(logIntegers) {
								fw.writeEntry((int)Math.rint(value));
							} else {
								fw.writeEntry(value);
							}
						} catch (IOException ioe) {
							// If an IO Exception occurs, then close the log file
							Activator.logError("Error writing to log file", ioe);
							FileUtils.safeClose(fw);
							logWriters.remove(key);
						}
					} // For each property in label
				} // For each population identifier
			} // For each node				
		} //  For each node resolution
		
		// After all iteration data is written, add a new line to the log files where needed
		appendLineToLogWriters();
	}
	
	/**
	 * Adds a new line character to each log file writer if there is content on the line
	 */
	private void appendLineToLogWriters()
	{
		Iterator<Entry<StateLevelMap, DelimetedWriter>> writers = logWriters.entrySet().iterator();
		
		// Make sure we're at a new line for each log writer that was modified
		while (writers.hasNext()) {
			DelimetedWriter fw = writers.next().getValue();
			if (!fw.isEmptyLine()) {
				try {
					fw.newLine();
				} catch (IOException ioe) {
					// If an IO Exception occurs, then close the log file
					Activator.logError("Error writing to log file", ioe);
					FileUtils.safeClose(fw);
					writers.remove();
				}
			}
		}
	}

	/**
	 * @return The human readable name of the decorator
	 */
	private String getDecoratorName()
	{
		if (decoratorName == null) {
			if(decorator instanceof DiseaseModel) {
				decoratorName = ((DiseaseModel)decorator).getDiseaseName().trim();
			} else if (decorator instanceof PopulationModel) {
				decoratorName = ((PopulationModel)decorator).getName().trim();
			} else {
				decoratorName = decorator.eClass().toString();
			}
		}
		return decoratorName;
	}


	/**
	 * @return The base directory for all log files for this simulation & decorator
	 */
	protected File getLogDirectory()
	{
		if (logDirectory == null) {
			logDirectory = new File(simulationLogger.getLogDirectory(), getDecoratorName());
			if (!logDirectory.exists() && !logDirectory.mkdirs()) {
				Activator.logError("Unable to create log directory for decorator "+ getDecoratorName(), new IOException("Error creating directory "+ logDirectory.getAbsolutePath()));
			}
		}
		
		return logDirectory;
	}

	/**
	 * @return The path to the file containing simulation parameters
	 */
	private File getRunParametersFile() 
	{
		return new File(getLogDirectory(), Constants.RUN_PARAMETER_FILE_NAME);
	}

	/**
	 * @return The correct sequencer time for the simulation
	 */
	private STEMTime getScenarioTime()
	{
		STEMTime time = getTimeProvider().getTime();
		if(time == null) {
			time = simulationLogger.getSimulation().getScenario().getSequencer().getStartTime();
		}
		if(!beforeStart) {
			time = time.addIncrement(simulationLogger.getSimulation().getScenario().getSequencer().getTimeDelta());
		}
		return time;
	}


	/**
	 * Create and write the parameters for this simulation
	 */
	private void writeRunParameters() 
	{
		if (decorator == null) {
			return;
		}

		DelimetedWriter fwp = null;
		try {
			fwp = new DelimetedWriter(logger.getDelimeter(), logger.getBufferSize(), new FileWriter(getRunParametersFile()));

			final ComposedAdapterFactory itemProviderFactory = new ComposedAdapterFactory(
					ComposedAdapterFactory.Descriptor.Registry.INSTANCE);
			final IItemPropertySource propertySource = (IItemPropertySource) itemProviderFactory
					.adapt(decorator, IItemPropertySource.class);
			final List<IItemPropertyDescriptor> properties = propertySource
					.getPropertyDescriptors(decorator);

			List<String> header = new ArrayList<String>();
			List<String> values = new ArrayList<String>();

			for (IItemPropertyDescriptor descriptor : properties) {
				final EStructuralFeature feature = (EStructuralFeature) descriptor.getFeature(null);
				
				// Omit Dublin Core values from the log file
				if (CommonPackage.eINSTANCE.getDublinCore().equals(feature.getEContainingClass())) {
					continue;
				}
				
				header.add(feature.getName());
				values.add(((EObject) decorator).eGet(feature).toString());
			}

			fwp.writeLine(header);
			fwp.writeLine(values);

		} catch (final IOException e) {
			Activator.logError("Error will writing to the run parameters log file", e);
		} finally {
			FileUtils.safeClose(fwp);
		}
	}

	
	/**
	 * Get the path to the log file to write for the simulation/population/decorator property/admin level
	 * 
	 * @param populationIdentifier
	 * @param decoratoryPropertyName
	 * @param adminLevel
	 * @return
	 */
	private File getLogFileForProperty(String populationIdentifier, String decoratoryPropertyName, int adminLevel)
	{
		File populationDirectory = new File(getLogDirectory(), populationIdentifier);
		if (!populationDirectory.exists() && !populationDirectory.mkdirs()) {
			Activator.logWarning("Failed to create log directory "+ populationDirectory.toString(), null);
		}
		
		StringBuilder fileName = new StringBuilder();
		fileName.append(decoratoryPropertyName);
		fileName.append("_");
		fileName.append(adminLevel);
		fileName.append(".");
		fileName.append(Constants.LOG_FILE_SUFFIX);
		
		return new File(populationDirectory, fileName.toString());
	}
	

	
	/**
	 * Creates a log file writer for a Property and Population for a given admin level.  Creates the
	 * log file and 
	 * @param populationIdentifier
	 * @param propertyDisplayName
	 * @param adminLevel
	 * @return
	 */
	private DelimetedWriter createLogger(String populationIdentifier, String propertyDisplayName, int adminLevel)
	{
		File propertyLogFile = getLogFileForProperty(populationIdentifier, propertyDisplayName, adminLevel);
		
		DelimetedWriter fw = null;
		boolean fileHasData = false;
		try {
			fw = new DelimetedWriter(logger.getDelimeter(), logger.getBufferSize(),  new FileWriter(propertyLogFile));

			fw.writeEntry(Constants.ITERATION_LABEL);
			fw.writeEntry(Constants.TIME_LABEL);
			
			for (Node node : getSortedNodesForAdminlevel(adminLevel, nodeLevels)) {
				NodeLabel labelToWrite = getMatchingLabel(node, populationIdentifier);
				if(labelToWrite != null) {
					fileHasData = true;
					fw.writeEntry(filterLocationId(node.getURI().toString()));
				}
			}

			fw.newLine();
		} catch (IOException ioe) {
			Activator.logError("Exception while setting up the log file "+ propertyLogFile.toString(), ioe);
			fileHasData = false;
		} finally {
			if (!fileHasData) {
				FileUtils.safeClose(fw);
				fw = null;
				try {
					propertyLogFile.delete();
				} catch (Throwable t) {
					// do nothing
				}
			}
		}
		return fw;
	}
	
	/**
	 * Setup and create log file writers for each individual property in 
	 * the decorator that contains data to write.
	 */
	private void setupPropertyLoggers()
	{
		nodeLevels = SimulationUtils.getNodeLevelsForScenario(simulationLogger.getSimulation().getScenario());

		// Get the first label we'll write for the decorator
		IntegrationLabel label = getFirstLabelForDecorator();
		if (label == null) {
			Activator.logError("No labels found for decorator "+ getDecoratorName(), new Exception());
			return;
		}
		
		// Get the properties for that label
		List<IItemPropertyDescriptor>properties = getPropertiesForLabel(label);
		if (properties == null) {
			Activator.logError("Cannot retrieve properties for "+label, null);
			return;
		}
			
		// Get the population identifiers for the label
		List<String> populationIdentifiers = getPopulationIdentifiers();
		if (populationIdentifiers == null) {
			Activator.logError("No populations found for decorator "+ getDecoratorName(), null);
			return;
		}
		
		// The log file is setup as:
		// Population / Level / Decorator
		// Iterate through the individual lists to setup the individual log files
		
		for (IItemPropertyDescriptor decoratorProperty : properties) {
			for (Integer level : getResolutionLevels()) {
				for (String populationIdentifier : populationIdentifiers) {
					String propertyName = decoratorProperty.getDisplayName(decoratorProperty);
					DelimetedWriter fw = createLogger(populationIdentifier, propertyName, level);
					if (fw != null) {
						logWriters.put(new StateLevelMap(populationIdentifier, propertyName, level), fw);
					}
				}
			}
		}
	}
	
	/**
	 * @return The first log-able label for the decorator
	 */
	private IntegrationLabel getFirstLabelForDecorator()
	{
		for (DynamicLabel label : ((Decorator)decorator).getLabelsToUpdate()) {
			if(label instanceof IntegrationLabel) {
				return (IntegrationLabel)label;
			}
		}
		return null;
	}
	

	/**
	 * Gets the relative value properties for the given label
	 * @param label
	 * @return
	 */
	private List<IItemPropertyDescriptor> getPropertiesForLabel(DynamicLabel label)
	{
		final RelativeValueProviderAdapter rvp = (RelativeValueProviderAdapter) RelativeValueProviderAdapterFactory.INSTANCE.adapt(label, RelativeValueProvider.class);
		return rvp.getProperties();
	}
	
	
	/**
	 * @return The population identifiers for the decorator
	 */
	private List<String> getPopulationIdentifiers() {
		if (decorator instanceof DiseaseModel) {
			return ((DiseaseModel) decorator).getAllLabelIdentifiers();
		} else if (decorator instanceof PopulationModel) {
			return ((PopulationModel) decorator).getAllLabelIdentifiers();
		}
		
		return new ArrayList<String>();
	}
	
	/**
	 * @return The list of admin levels in the list of nodes
	 */
	private List<Integer> getResolutionLevels() {
		if(resolutionLevels == null) {
			resolutionLevels = new ArrayList<Integer>();
			for(Integer level : nodeLevels.values()) {
				if(!resolutionLevels.contains(level)) {
					resolutionLevels.add(level);
				}
			}
		}
		
		return resolutionLevels;
	}
	

	/**
	 * @param node The node to test
	 * @return Whether the node is to be excluded from logging
	 */
	private boolean isExcludedNode(Node node)
	{
		for (String key : EXCLUDED_NODES) {
			if (node.getURI().toString().contains(key)) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * Gets and sorts all nodes assigned to a specific administrative level.
	 * 
	 * @param level The admin level to get nodes for
	 * @param nodeLevels The node level list to scan
	 * @return
	 */
	private List<Node> getSortedNodesForAdminlevel(int level, Map<Node, Integer>nodeLevels)
	{
		List<Node> list = sortedNodeList.get(level);
		if (list == null) {
			list = new ArrayList<Node>();
			// Iterate through the list of nodes
			for (Entry<Node,Integer> entry : nodeLevels.entrySet()) {
				// If node level is equal to the current level
				if (entry.getValue() == level) {
					Node node = entry.getKey();
					
					// Look through the labels to determin if we're going to write this node
					for (NodeLabel s : node.getLabels()) {
						if (s instanceof IntegrationLabel) {
							// If the node contains an integration label and is 
							// not in the exclusion list, then add to the list for writing
							if (!isExcludedNode(node)) {
								list.add(entry.getKey());
							}
							break;
						}
					}
				}
			}
			// Sort the list by applying the comparator
			Collections.sort(list, NODE_SORTER);
			
			sortedNodeList.put(level, list);
		}
		return list;
	}
	
	
	
	/**
	 * Gets the correct label for the given node, decorator, and population identifier
	 * 
	 * @param n Node to get label from
	 * @param popId Population identifier to test
	 * @return The matching node label
	 */
	private NodeLabel getMatchingLabel(Node n, String popId) {
		for(NodeLabel label:n.getLabels()) {
			if (decorator instanceof DiseaseModel 
					&& label instanceof DiseaseModelLabel 
						&& ((DiseaseModelLabel)label).getDecorator().equals(decorator) 
							&& ((DiseaseModelLabel)label).getPopulationModelLabel().getPopulationIdentifier().equals(popId)) {
				return label;		
			} else if (decorator instanceof PopulationModel 
						&& label instanceof PopulationModelLabel
							&& ((PopulationModelLabel)label).getDecorator().equals(decorator) 
								&& ((PopulationModelLabel)label).getPopulationIdentifier().equals(popId)) {
				return label;
			}
		
		}
		return null;
	}
	
	/**
	 * filters the location id prefix from the beginning of
	 *  a nodes ID for generation of a file name
	 * @param unfiltered
	 * @return the filtered file name using location id.
	 */
	private String filterLocationId(String unfiltered) {
		int last = unfiltered.indexOf(Constants.LOCATION_ID_PREFIX);
		if (last >= 0) {
			last += Constants.LOCATION_ID_PREFIX.length();
			return unfiltered.substring(last, unfiltered.length());
		} 
		return unfiltered;
	}
	
	
	/**
	 * @return The time provider for the canonical graph
	 */
	private TimeProvider getTimeProvider()
	{
		if (timeProvider == null) {
			timeProvider = (TimeProvider) TimeProviderAdapterFactory.INSTANCE
					.adapt(simulationLogger.getSimulation().getScenario().getCanonicalGraph(), TimeProvider.class);
		}
		
		return timeProvider;
	}
	
	
	/**
	 * Used as key in map with FileWriters. FileWriters are key'd by
	 * the label (i.e. disease state) and by 
	 */
	private static class StateLevelMap {
		private final String popId;
		private final String state;
		private final int level;
		
		public StateLevelMap(String popId,String state, int level) {
			this.popId = popId;
			this.state = state;
			this.level = level;
		}
		
		public String getPopulationId() {return this.popId;}
		public int getLevel() {return this.level;}
		public String getState() {return this.state;}
		
		@Override
		public int hashCode() {
			return state.hashCode()+popId.hashCode() + level; // ugh
		}
		
		@Override
		public boolean equals(Object o) {
			if(!(o instanceof StateLevelMap)) return false;
			StateLevelMap slm = (StateLevelMap)o;
			return (slm.getState().equals(this.state) && slm.getPopulationId().equals(this.popId) && slm.getLevel() == level);
		}
		
		@Override
		public String toString() {
			return this.popId+" - "+this.state+"_"+this.level;
		}
	}
}
