/*******************************************************************************
 * Copyright (c) 2004, 2009 Tasktop Technologies 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:
 *     Tasktop Technologies - initial API and implementation
 *******************************************************************************/

package org.eclipse.mylyn.internal.monitor.usage;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeListener;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.internal.monitor.core.collection.IUsageCollector;
import org.eclipse.mylyn.internal.monitor.core.collection.IUsageScanner;
import org.eclipse.mylyn.internal.monitor.core.collection.InteractionEventComparator;
import org.eclipse.mylyn.internal.monitor.core.collection.InteractionEventSummary;
import org.eclipse.mylyn.internal.monitor.core.collection.InteractionEventUtil;
import org.eclipse.mylyn.monitor.core.InteractionEvent;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.progress.IProgressService;

/**
 * Used for generating reports of user activity.
 * 
 * @author Mik Kersten
 * @since 3.0
 */
public class ReportGenerator {

	public static final String SUMMARY_SEPARATOR = "<hr><br>"; //$NON-NLS-1$

	private final InteractionEventLogger logger;

	private UsageStatisticsSummary lastParsedSummary = null;

	private final Set<Integer> userIds = new HashSet<Integer>();

	private final List<IUsageCollector> collectors;

	private List<IUsageScanner> scanners;

	private Map<Integer, Map<String, SortedSet<InteractionEvent>>> allUserEvents;

	private boolean saveAllUserEvents = false;

	private IJobChangeListener listener = null;

	private boolean forceSyncForTesting = false;

	public ReportGenerator(InteractionEventLogger logger, IUsageCollector collector, boolean saveAllUserEvents) {
		this(logger, collector);
		this.saveAllUserEvents = saveAllUserEvents;
	}

	public ReportGenerator(InteractionEventLogger logger, List<IUsageCollector> collectors, boolean saveAllUserEvents) {
		this(logger, collectors);
		this.saveAllUserEvents = saveAllUserEvents;
	}

	public ReportGenerator(InteractionEventLogger logger, IUsageCollector collector) {
		List<IUsageCollector> collectors = new ArrayList<IUsageCollector>();
		collectors.add(collector);
		this.logger = logger;
		this.collectors = collectors;
	}

	public ReportGenerator(InteractionEventLogger logger, List<IUsageCollector> collectors) {
		this.logger = logger;
		this.collectors = collectors;
	}

	public ReportGenerator(InteractionEventLogger logger, List<IUsageCollector> collectors,
			List<IUsageScanner> scanners, IJobChangeListener listener) {
		this(logger, collectors);
		this.scanners = scanners;
	}

	public ReportGenerator(InteractionEventLogger logger, IUsageCollector collector, IJobChangeListener listener) {
		this(logger, collector);
		this.listener = listener;
	}

	public ReportGenerator(InteractionEventLogger logger, List<IUsageCollector> collectors,
			IJobChangeListener listener, boolean forceSyncForTesting) {
		this(logger, collectors);
		this.listener = listener;
		this.forceSyncForTesting = forceSyncForTesting;
	}

	public void setScanners(List<IUsageScanner> scanners) {
		this.scanners = scanners;
	}

	// XXX clean up code and methods
	public void getStatisticsFromInteractionHistory(File source, IJobChangeListener listener) {
		List<File> sources = new ArrayList<File>();
		sources.add(source);
		getStatisticsFromInteractionHistories(sources, listener);
	}

	public void getStatisticsFromInteractionHistories(List<File> sources, IProgressMonitor monitor) {
		final GenerateStatisticsJob job = new GenerateStatisticsJob(this, sources);
		job.run(monitor);
	}

	public void getStatisticsFromInteractionHistories(List<File> sources, IJobChangeListener jobChangeListener) {

		final GenerateStatisticsJob job = new GenerateStatisticsJob(this, sources);
		if (jobChangeListener == null) {
			IProgressService service = PlatformUI.getWorkbench().getProgressService();
			try {
				service.run(true, false, new IRunnableWithProgress() {

					public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
						job.run(monitor);
					}

				});
			} catch (InvocationTargetException e) {
				StatusHandler.log(new Status(IStatus.ERROR, UiUsageMonitorPlugin.ID_PLUGIN, e.getMessage(), e));
			} catch (InterruptedException e) {
				StatusHandler.log(new Status(IStatus.ERROR, UiUsageMonitorPlugin.ID_PLUGIN, e.getMessage(), e));
			}

		} else {

			if (jobChangeListener != null) {
				job.addJobChangeListener(jobChangeListener);
			}
			if (this.listener != null) {
				job.addJobChangeListener(this.listener);
			}
			job.setPriority(Job.LONG);
			if (forceSyncForTesting) {
				job.run(new NullProgressMonitor());
			} else {
				job.schedule();
			}
		}

	}

	public UsageStatisticsSummary getLastParsedSummary() {
		return lastParsedSummary;
	}

	/**
	 * Assuming the file naming convention of <phase>-<version>-usage-<userID>-<date and time>.zip
	 */
	private int getUserId(File source) {
		String userIDText = source.getName();
		int userId = -1;
		String prefix = "-usage-"; //$NON-NLS-1$

		if (source.getName().indexOf(prefix) >= 0) {
			try {
				userIDText = userIDText.substring(userIDText.indexOf(prefix) + prefix.length(), userIDText.length());
				userIDText = userIDText.substring(0, userIDText.indexOf("-")); //$NON-NLS-1$
				userId = Integer.valueOf(userIDText);
			} catch (Throwable t) {
				StatusHandler.log(new Status(IStatus.ERROR, UiUsageMonitorPlugin.ID_PLUGIN,
						"Could not parse user ID from source file", t)); //$NON-NLS-1$
			}
		}

		return userId;
	}

	private String getPhase(File source) {
		String userIDText = source.getName();
		String phase = "unknown"; //$NON-NLS-1$
		String terminator = "-"; //$NON-NLS-1$

		if (source.getName().indexOf(terminator) >= 0) {
			try {
				phase = userIDText.substring(0, userIDText.indexOf(terminator) - 1);
			} catch (Throwable t) {
				StatusHandler.log(new Status(IStatus.ERROR, UiUsageMonitorPlugin.ID_PLUGIN,
						"Could not parse user ID from source file", t)); //$NON-NLS-1$
			}
		}
		return phase;
	}

	class GenerateStatisticsJob extends Job {

		private final ReportGenerator generator;

		private final List<File> sources;

		public GenerateStatisticsJob(ReportGenerator generator, List<File> sources) {
			super(Messages.ReportGenerator_Generate_Statistics_Job);
			this.generator = generator;
			this.sources = sources;
		}

		@Override
		public IStatus run(IProgressMonitor monitor) {

			if (saveAllUserEvents) {
				allUserEvents = new HashMap<Integer, Map<String, SortedSet<InteractionEvent>>>();
			}

			UsageStatisticsSummary statistics = new UsageStatisticsSummary();
			Map<Integer, Map<String, InteractionEventSummary>> summaryMap = new HashMap<Integer, Map<String, InteractionEventSummary>>();

			Map<Integer, List<File>> filesPerUser = new HashMap<Integer, List<File>>();
			try {

				// Go through the files to determine which users we have to
				// process (by user id)
				for (File source : sources) {
					int userId = getUserId(source);
					userIds.add(userId);
					List<File> filesForUser = null;
					if (filesPerUser.containsKey(userId)) {
						filesForUser = filesPerUser.get(userId);
					}
					if (filesForUser == null) {
						filesForUser = new ArrayList<File>();
					}
					filesForUser.add(source);
					filesPerUser.put(userId, filesForUser);
				}
			} catch (Throwable t) {
				StatusHandler.log(new Status(IStatus.ERROR, UiUsageMonitorPlugin.ID_PLUGIN,
						"Could not generate usage report", t)); //$NON-NLS-1$
			}

			try {
				// There are three processing events per user
				monitor.beginTask(Messages.ReportGenerator_Mylyn_Usage_Summary_Generation, userIds.size() * 3);

				// Process the files for each user
				for (Integer aUser : filesPerUser.keySet()) {
					Map<String, SortedSet<InteractionEvent>> userEvents = new HashMap<String, SortedSet<InteractionEvent>>();

					for (File aFile : filesPerUser.get(aUser)) {
						String phase = getPhase(aFile);

						// orderedEvents must be a set because the
						// monitor-log.xml file contains some duplicate
						// events and we want to be sure that we ignore the
						// duplicates in the reporting. Sets
						// cannot contain duplicates, so orderedEvents will only
						// accept the unique events.
						SortedSet<InteractionEvent> orderedEvents;
						if (userEvents.get(phase) == null) {
							orderedEvents = new TreeSet<InteractionEvent>(new InteractionEventComparator());
							orderedEvents.addAll(this.generator.logger.getHistoryFromFile(aFile));
						} else {
							orderedEvents = userEvents.get(phase);
							orderedEvents.addAll(this.generator.logger.getHistoryFromFile(aFile));
						}
						userEvents.put(phase, orderedEvents);
					}
					monitor.worked(1);

					// If there are scanners registered, give each event to each
					// scanner in turn
					if (this.generator.scanners != null && this.generator.scanners.size() > 0) {

						for (Map.Entry<String, SortedSet<InteractionEvent>> eventsPerPhase : userEvents.entrySet()) {
							// String phaseToProcess = eventsPerPhase.getKey();
							SortedSet<InteractionEvent> events = eventsPerPhase.getValue();

							for (InteractionEvent event : events) {
								for (IUsageScanner scanner : this.generator.scanners) {
									scanner.scanEvent(event, aUser);
								}
							}
						}
					}
					monitor.worked(1);

					if (allUserEvents != null) {
						allUserEvents.put(aUser, userEvents);
					}

					// Consume all events
					for (Map.Entry<String, SortedSet<InteractionEvent>> eventsPerPhase : userEvents.entrySet()) {
						// String phaseToProcess = eventsPerPhase.getKey();
						SortedSet<InteractionEvent> events = eventsPerPhase.getValue();

						for (InteractionEvent event : events) {

							if (event.getKind().isUserEvent()) { // TODO:
								// some
								// collectors
								// may want
								// non-user
								// events
								for (IUsageCollector collector : this.generator.collectors) {
									collector.consumeEvent(event, aUser);
								}
							}
							createUsageTableData(summaryMap, event, aUser);
						}
					}
					monitor.worked(1);
				}

				for (IUsageCollector collector : this.generator.collectors) {
					statistics.add(collector);
				}

				// Flatten the summaries for the command usage table
				List<InteractionEventSummary> flattenedSummaries = new ArrayList<InteractionEventSummary>();
				Map<String, InteractionEventSummary> combinedUserSummary = new HashMap<String, InteractionEventSummary>();

				// Go through the summary for each user and combine the
				// information into a table sorted by the command
				for (Map<String, InteractionEventSummary> userSummary : summaryMap.values()) {
					for (InteractionEventSummary aSummary : userSummary.values()) {
						if (!combinedUserSummary.containsKey(aSummary.getName())) {
							combinedUserSummary.put(aSummary.getName(), new InteractionEventSummary(aSummary));
						} else {
							// Could be simplified; but written this way for
							// clarity
							InteractionEventSummary combinedSummary = combinedUserSummary.get(aSummary.getName());
							combinedSummary.combine(aSummary);
							combinedUserSummary.put(aSummary.getName(), combinedSummary);
						}
					}

				}

				flattenedSummaries.addAll(combinedUserSummary.values());

				statistics.setSingleSummaries(flattenedSummaries);
				this.generator.lastParsedSummary = statistics;
				monitor.done();

			} catch (Throwable t) {
				StatusHandler.log(new Status(IStatus.ERROR, UiUsageMonitorPlugin.ID_PLUGIN,
						"Could not generate usage report", t)); //$NON-NLS-1$
			}

			return Status.OK_STATUS;
		}

		private void createUsageTableData(Map<Integer, Map<String, InteractionEventSummary>> summaryMap,
				InteractionEvent event, int userId) {
			Map<String, InteractionEventSummary> usersSummary = summaryMap.get(userId);
			if (usersSummary == null) {
				usersSummary = new HashMap<String, InteractionEventSummary>();
				summaryMap.put(userId, usersSummary);
			}

			InteractionEventSummary summary = usersSummary.get(getIdentifier(event));
			if (summary == null) {
				summary = new InteractionEventSummary(event.getKind().toString(),
						InteractionEventUtil.getCleanOriginId(event), 0);
				usersSummary.put(getIdentifier(event), summary);
			}
			summary.setUsageCount(summary.getUsageCount() + 1);
			summary.setInterestContribution(summary.getInterestContribution() + event.getInterestContribution());
			summary.setDelta(event.getDelta());
			summary.addUserId(userId);
		}

		public String getIdentifier(InteractionEvent event) {
			return event.getKind().toString() + ':' + InteractionEventUtil.getCleanOriginId(event);
		}

	}

	public static String formatPercentage(float percentage) {
		String percentageString = "" + percentage; //$NON-NLS-1$
		int indexOf2ndDecimal = percentageString.indexOf('.') + 3;
		if (indexOf2ndDecimal <= percentageString.length()) {
			percentageString = percentageString.substring(0, indexOf2ndDecimal);
		}
		return percentageString;
	}

	public List<IUsageCollector> getCollectors() {
		return collectors;
	}

	public Map<Integer, Map<String, SortedSet<InteractionEvent>>> getAllUsers() {
		return allUserEvents;
	}

	public void forceSyncForTesting(boolean syncForTesting) {
		this.forceSyncForTesting = syncForTesting;

	}
}
