package artistmetrics.actions;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;


/**
 * This class tracks the focus of all items on the workbench of Eclipse
 * In doing so, it creates a map of all tracked files and/or workbench items,
 * having an individual set of timers for each focus change that relates to that file.
 * 
 *  This class has a setting to allow for editor-only tracking, rather than full workbench
 *  tracking.
 */
public class FocusTracker 
{
	private Map<String, ArrayList<Timer>> focusTrackers;
	private String current; // the current item being tracked
	private String lastUpdate; // the last updated item
	private boolean editorsOnly; // setting for editor-tracking only

	/**
	 * Creates a base focustracker, with no timers in it. The current timer is
	 * set to null, and a new empty map of timers is created
	 * @param editorsOnly Setting for tracking only editors
	 */
	public FocusTracker(User user, boolean editorsOnly)
    {
		focusTrackers = new HashMap<String, ArrayList<Timer>>();
		current = null;
		this.editorsOnly = editorsOnly;
		focusChanged(user);
		
	}

	/**
	 * Checks to see what has changed when the current focus changes.
	 * 
	 * @param user
	 * @return true if focus has changed, and the tracker has updated
	 */
	public boolean focusChanged(User user) {
		// Find the active workbench
		IWorkbench editors = PlatformUI.getWorkbench();
		IWorkbenchWindow window = editors.getActiveWorkbenchWindow();
		IWorkbenchPage activePage = window.getActivePage();
		IWorkbenchPart activePart = activePage.getActivePart();
		
		// update the current timer, taking into account the settings
		if ((editorsOnly && activePart.getTitle().matches(activePage.getActiveEditor().getTitle())) || !editorsOnly)
		{
			if (current != null) {
				stopTracker();
				ArrayList<Timer> timers = focusTrackers.get(current);
				Timer currentTimer = timers.get(timers.size() - 1);
				if (currentTimer.getTimePassed() > 1000) // Only update if a second or more has passed since last focus change
				{
					updateLog(currentTimer);
					updateServer(user, currentTimer);
				}
				else return false;
			}
			current = activePart.getTitle();
			startTracker(current);
			return true;
		}
		else return false;
	}

	/**
	 * Starts tracking the file (which is now in focus) If the file has not
	 * previously been tracked, a new list of timers is added If the file has
	 * previously been tracked, the new focus timer is added to the list
	 * 
	 * @param fileName the name of the file to be tracked		//
	 */
	public void startTracker(String fileName) {
		ArrayList<Timer> timers = null;
		
		if (focusTrackers.get(fileName) == null) {
			focusTrackers.put(fileName, new ArrayList<Timer>());
		}
		current = fileName;
		timers = focusTrackers.get(fileName);
		timers.add(new Timer());
		focusTrackers.put(fileName, timers);
	}

	/**
	 * Stops the current timer, updating it.
	 */
	private void stopTracker() {
		ArrayList<Timer> timers = focusTrackers.get(current);
		timers.get(timers.size() - 1).updateTimer();
	}

	/**
	 * Updates the log file to show the newest focus changes in the format: "<file>
	 * left focus at: <date> <Timer.toString>"
	 * @param currentTimer the timer that holds information to write to the log
	 */
	private void updateLog(Timer currentTimer) {
		String timerString = currentTimer.toString();
		lastUpdate = current + " left focus at: " + new Date() + "\n"
				+ timerString;

	}

	/**
	 * Updates the server with the new data
	 * 
	 * @param user The user that this tracker is tracking
	 * @param currentTimer the timer that holds information to be sent to server
	 */
	private void updateServer(User user, Timer currentTimer) {
		Map<String, String> metricData = new HashMap<String, String>();
		metricData.put("time", "" + currentTimer.getTimePassed() / 1000);
		metricData.put("pane", current);

		user.sendMetric("focus", metricData);
	}

	/**
	 * Returns the last timer updated by this tracker.
	 * @return the last timer updated
	 */
	public String lastUpdatedTimer() {
		return lastUpdate;
	}

	/**
	 * Ends any tracking currently being run by the tracker, updating the log
	 * and server.
	 */
	public void endTracking(User user) {
		stopTracker(); // End the current timer
		ArrayList<Timer> timers = focusTrackers.get(current); // find timer to update
		Timer currentTimer = timers.get(timers.size() - 1);
		updateLog(currentTimer);
		updateServer(user, currentTimer);
	}

}
