/*******************************************************************************
 * Copyright (c) 2000, 2016, 2019 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Francis Upton <francisu@ieee.org> -
 *     		Fix for Bug 216667 [Decorators] DecorationScheduler hangs onto objects forever sometimes
 *     Stefan Winkler <stefan@winklerweb.net> - bug 417255 - Race Condition in DecorationScheduler
 *******************************************************************************/
package org.eclipse.ui.internal.decorators;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.jface.resource.ResourceManager;
import org.eclipse.jface.viewers.DecorationContext;
import org.eclipse.jface.viewers.IDecorationContext;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.WorkbenchMessages;
import org.eclipse.ui.progress.UIJob;
import org.eclipse.ui.progress.WorkbenchJob;

/**
 * The DecorationScheduler is the class that handles the decoration of elements
 * using a background thread.
 *
 * <p>
 * In detail, it works as follows:
 * </p>
 * <ol>
 * <li>When a client (usually the method
 * {@link DecoratorManager#prepareDecoration(Object, String, IDecorationContext)}
 * needs an element decorated, it calls <code>queueForDecoration</code>.</li>
 *
 * <li><code>queueForDecoration</code> inserts (or, if already present, updates)
 * the <code>element</code> into <code>awaitingDecoration</code> and an
 * associated <code>DecorationReference</code> into
 * <code>awaitingDecorationValues</code> and schedules the
 * <code>decorationJob</code> to be executed asynchonously.</li>
 *
 * <li>The <code>decorationJob</code> processes the list of elements in
 * <code>awaitingDecoration</code> one by one. For each element, it calls
 * <code>ensureResultCached</code>, which in turn calls the actual lightweight
 * decorator(s) for the element and stores the decoration result in the
 * <code>resultCache</code> and adds the element to the
 * <code>pendingUpdate</code> collection to remember that it needs to be updated
 * in the UI.</li>
 *
 * <li>When the <code>decorationJob</code> has finished processing all elements
 * in <code>awaitingDecoration</code>, it finally schedules the
 * <code>updateJob</code>.</li>
 *
 * <li>
 * <p>
 * The <code>updateJob</code> runs in the UI thread and fires
 * {@link LabelProviderChangedEvent}s for all elements in
 * <code>pendingUpdate</code>. The {@link LabelProviderChangedEvent} causes the
 * respective viewers to trigger an <code>update</code> for the given elements.
 * </p>
 * <p>
 * Effectively, this again calls
 * {@link DecoratorManager#prepareDecoration(Object, String, IDecorationContext)}
 * (see step 1.). But this time, before calling <code>queueForDecoration</code>,
 * the <code>DecoratorManager</code> first checks <code>isDecorationReady</code>
 * and because a decoration is ready (because it has been computed in the
 * meantime), the decoration result is obtained directly from the
 * <code>resultCache</code> and updated in the UI.
 * </p>
 * <p>
 * Note that <code>isDecorationReady</code> must only return <code>true</code>
 * if the call originates from the <code>updateJob</code>. In all other cases,
 * the original call originates from the application code (possibly to trigger
 * an update of the decoration). This is why the <code>updateJob</code> uses the
 * <code>isUpdateJobRunning</code> flag to indicate that it is currently running
 * in the UI thread.
 * </p>
 * </li>
 * </ol>
 *
 * So, in summary, a decoration is first enqueued, then calculated
 * asynchronously by the <code>decorationJob</code> and enqueued for UI-update,
 * and finally, the <code>updateJob</code> fires events which cause the viewers
 * to update the UI using the now available decoration results.
 */
public class DecorationScheduler {

	private static final ILabelProviderListener[] EMPTY_LISTENER_LIST = new ILabelProviderListener[0];

	// When decorations are computed they are added to this cache via
	// decorated() method
	private Map<IDecorationContext, Map<Object, DecorationResult>> resultCache = new ConcurrentHashMap<>();

	// Objects that need an icon and text computed for display to the user
	private List<Object> awaitingDecoration = new ArrayList<>();

	// Objects that are awaiting a label update.
	private Set<Object> pendingUpdate = new HashSet<>();

	// Key to lock write access to the pending update set
	private Object pendingKey = new Object();

	private Map<Object, DecorationReference> awaitingDecorationValues = new HashMap<>();

	private DecoratorManager decoratorManager;

	private boolean shutdown = false;

	private Job decorationJob;

	// Notifies about updateJob or clearJob finishing
	private final class JobChangeListener extends JobChangeAdapter {

		// is called after changeState(job, Job.NONE);
		@Override
		public void done(IJobChangeEvent event) {
			synchronized (this) {
				if (!updatesPending()) { // signal only if no more updates pending
					this.notifyAll(); // also notify if nobody is waiting.
				}
			}
		}

		void sleep(long timeoutMillis) throws InterruptedException {
			synchronized (this) {
				if (updatesPending()) { // avoid wait if no updates pending
					this.wait(timeoutMillis);
				}
			}
		}
	}

	private final JobChangeListener jobFinishListener = new JobChangeListener();

	private UIJob updateJob;

	private Collection<ILabelProviderListener> removedListeners = Collections.synchronizedSet(new HashSet<>());

	private Job clearJob;

	// Static used for the updates to indicate an update is required
	private static final int NEEDS_INIT = -1;

	/** Amount of time to delay the update notification when max reached. */
	private static final int UPDATE_DELAY = 100;

	/**
	 * Flag which is used to indicate that the update job is running in the UI
	 * thread
	 */
	private boolean isUpdateJobRunning = false;

	/**
	 * Return a new instance of the receiver configured for the supplied
	 * DecoratorManager.
	 *
	 * @param manager
	 */
	DecorationScheduler(DecoratorManager manager) {
		decoratorManager = manager;
		createDecorationJob();
	}

	/**
	 * Decorate the text for the receiver. If it has already been done then return
	 * the result, otherwise queue it for decoration.
	 *
	 * @return String
	 * @param text
	 * @param element
	 * @param adaptedElement The adapted value of element. May be null.
	 * @param context        the decoration context
	 */

	public String decorateWithText(String text, Object element, Object adaptedElement, IDecorationContext context) {

		DecorationResult decoration = getResult(element, adaptedElement, context);

		if (decoration == null) {
			return text;
		}

		return decoration.decorateWithText(text);

	}

	/**
	 * Queue the element and its adapted value if it has not been already.
	 *
	 * @param element
	 * @param adaptedElement  The adapted value of element. May be null.
	 * @param forceUpdate     If true then a labelProviderChanged is fired whether
	 *                        decoration occurred or not.
	 * @param undecoratedText The original text for the element if it is known.
	 * @param context         The decoration context
	 */

	synchronized void queueForDecoration(Object element, Object adaptedElement, boolean forceUpdate,
			String undecoratedText, IDecorationContext context) {

		Assert.isNotNull(context);
		DecorationReference reference = awaitingDecorationValues.get(element);
		if (reference != null) {
			if (forceUpdate) {// Make sure we don't loose a force
				reference.setForceUpdate(forceUpdate);
			}
			reference.addContext(context);
		} else {
			reference = new DecorationReference(element, adaptedElement, context);
			reference.setForceUpdate(forceUpdate);
			reference.setUndecoratedText(undecoratedText);
			awaitingDecorationValues.put(element, reference);
			awaitingDecoration.add(element);
			if (shutdown) {
				return;
			}
			decorationJob.schedule();
		}

	}

	/**
	 * Decorate the supplied image, element and its adapted value.
	 *
	 * @return Image
	 * @param image
	 * @param element
	 * @param adaptedElement The adapted value of element. May be null.
	 * @param context        the decoration context
	 * @param manager
	 *
	 */
	public Image decorateWithOverlays(Image image, Object element, Object adaptedElement, IDecorationContext context,
			ResourceManager manager) {

		DecorationResult decoration = getResult(element, adaptedElement, context);

		if (decoration == null) {
			return image;
		}
		return decoration.decorateWithOverlays(image, manager);
	}

	/**
	 * Return the DecorationResult for element. If there isn't one queue for
	 * decoration and return <code>null</code>.
	 *
	 * @param element        The element to be decorated. If it is <code>null</code>
	 *                       return <code>null</code>.
	 * @param adaptedElement It's adapted value.
	 * @param context        The deocration context
	 * @return DecorationResult or <code>null</code>
	 */
	private DecorationResult getResult(Object element, Object adaptedElement, IDecorationContext context) {

		// We do not support decoration of null
		if (element == null) {
			return null;
		}

		DecorationResult decoration = internalGetResult(element, context);

		if (decoration == null) {
			queueForDecoration(element, adaptedElement, false, null, context);
			return null;
		}
		return decoration;

	}

	private DecorationResult internalGetResult(Object element, IDecorationContext context) {
		Map<Object, DecorationResult> results = resultCache.get(context);
		if (results != null) {
			return results.get(element);
		}
		return null;
	}

	protected void internalPutResult(Object element, IDecorationContext context, DecorationResult result) {
		Map<Object, DecorationResult> results = resultCache.computeIfAbsent(context, ctx -> new ConcurrentHashMap<>());
		results.put(element, result);
	}

	/**
	 * Execute a label update using the pending decorations.
	 */
	synchronized void decorated() {

		// Don't bother if we are shutdown now
		if (shutdown) {
			return;
		}

		// Lazy initialize the job
		if (updateJob == null) {
			updateJob = getUpdateJob();
		}

		// Give it a bit of a lag for other updates to occur
		updateJob.schedule(UPDATE_DELAY);
	}

	/**
	 * Shutdown the decoration.
	 */
	synchronized void shutdown() {
		shutdown = true;
	}

	/**
	 * Get the next resource to be decorated.
	 *
	 * @return IResource
	 */
	synchronized DecorationReference nextElement() {

		if (shutdown || awaitingDecoration.isEmpty()) {
			return null;
		}
		Object element = awaitingDecoration.remove(0);

		return awaitingDecorationValues.remove(element);
	}

	/**
	 * Create the Thread used for running decoration.
	 */
	private void createDecorationJob() {
		decorationJob = new Job(WorkbenchMessages.DecorationScheduler_CalculationJobName) {
			@Override
			public IStatus run(IProgressMonitor monitor) {

				synchronized (DecorationScheduler.this) {
					if (shutdown) {
						return Status.CANCEL_STATUS;
					}
				}

				while (updatesPending()) {

					try {
						jobFinishListener.sleep(100);
					} catch (InterruptedException e) {
						// Cancel and try again if there was an error
						schedule();
						return Status.CANCEL_STATUS;
					}
				}

				SubMonitor subMonitor = SubMonitor.convert(monitor);
				subMonitor.setTaskName(WorkbenchMessages.DecorationScheduler_CalculatingTask);
				// will block if there are no resources to be decorated
				DecorationReference reference;

				while ((reference = nextElement()) != null) {

					SubMonitor loopMonitor = subMonitor.setWorkRemaining(100).split(1);
					Object element = reference.getElement();
					boolean force = reference.shouldForceUpdate();
					Collection<IDecorationContext> contexts = reference.getContexts();
					loopMonitor.setWorkRemaining(contexts.size());
					for (IDecorationContext context : contexts) {
						ensureResultCached(element, force, context);
						loopMonitor.split(1);
					}
					// Only notify listeners when we have exhausted the
					// queue of decoration requests.
					synchronized (DecorationScheduler.this) {
						if (awaitingDecoration.isEmpty()) {
							decorated();
						}
					}
				}
				return Status.OK_STATUS;
			}

			/**
			 * Ensure that a result is cached for the given element and context
			 *
			 * @param element the elements
			 * @param force   whether an update should be forced
			 * @param context the decoration context
			 */
			private void ensureResultCached(Object element, boolean force, IDecorationContext context) {
				DecorationBuilder cacheResult = new DecorationBuilder(context);
				// Calculate the decoration
				decoratorManager.getLightweightManager().getDecorations(element, cacheResult);

				// If we should update regardless then put a result
				// anyways
				if (cacheResult.hasValue() || force) {

					// Synchronize on the result lock as we want to
					// be sure that we do not try and decorate during
					// label update servicing.
					// Note: resultCache and pendingUpdate modifications
					// must be done atomically.

					// Add the decoration even if it's empty in
					// order to indicate that the decoration is
					// ready

					internalPutResult(element, context, cacheResult.createResult());

					// Add an update for only the original element
					// to
					// prevent multiple updates and clear the cache.
					synchronized (pendingKey) {
						pendingUpdate.add(element);
					}
				}
			}

			@Override
			public boolean belongsTo(Object family) {
				return DecoratorManager.FAMILY_DECORATE == family;
			}

			@Override
			public boolean shouldRun() {
				return PlatformUI.isWorkbenchRunning();
			}
		};

		decorationJob.setSystem(true);
		decorationJob.setPriority(Job.DECORATE);
		decorationJob.schedule();
	}

	/**
	 * Return whether or not we are waiting on updated
	 *
	 * @return <code>true</code> if there are updates waiting to be served
	 */
	protected boolean updatesPending() {
		if (updateJob != null && updateJob.getState() != Job.NONE) {
			return true;
		}
		if (clearJob != null && clearJob.getState() != Job.NONE) {
			return true;
		}
		return false;
	}

	/**
	 * An external update request has been made. Clear the results as they are
	 * likely obsolete now.
	 */
	void clearResults() {
		if (clearJob == null) {
			clearJob = getClearJob();
		}
		clearJob.schedule();
	}

	private Job getClearJob() {
		Job clear = new Job(WorkbenchMessages.DecorationScheduler_ClearResultsJob) {

			@Override
			protected IStatus run(IProgressMonitor monitor) {
				resultCache.clear();
				return Status.OK_STATUS;
			}

			@Override
			public boolean shouldRun() {
				return PlatformUI.isWorkbenchRunning();
			}

		};
		clear.setSystem(true);
		clear.addJobChangeListener(jobFinishListener);
		return clear;
	}

	/**
	 * Get the update WorkbenchJob.
	 *
	 * @return WorkbenchJob
	 */
	private WorkbenchJob getUpdateJob() {
		WorkbenchJob job = new WorkbenchJob(WorkbenchMessages.DecorationScheduler_UpdateJobName) {

			int currentIndex = NEEDS_INIT;

			LabelProviderChangedEvent labelProviderChangedEvent;

			ILabelProviderListener[] listeners;

			@Override
			public IStatus runInUIThread(IProgressMonitor monitor) {
				// set the flag to true while the job is running
				isUpdateJobRunning = true;

				try {
					synchronized (DecorationScheduler.this) {
						if (shutdown) {
							return Status.CANCEL_STATUS;
						}
					}

					// If this is the first one check again in case
					// someone has already cleared it out.
					if (currentIndex == NEEDS_INIT) {
						if (hasPendingUpdates()) {
							resetState();
							return Status.OK_STATUS;
						}
						setUpUpdates();
					}

					if (listeners.length == 0) {
						resetState();
						return Status.OK_STATUS;
					}

					monitor.beginTask(WorkbenchMessages.DecorationScheduler_UpdatingTask, IProgressMonitor.UNKNOWN);

					long startTime = System.currentTimeMillis();
					while (currentIndex < listeners.length) {
						ILabelProviderListener listener = listeners[currentIndex];
						currentIndex++;

						// If it was removed in the meantime then skip it.
						if (!removedListeners.contains(listener)) {
							decoratorManager.fireListener(labelProviderChangedEvent, listener);
						}

						// If it is taking long enough for the user to notice then
						// cancel the updates.
						if ((System.currentTimeMillis() - startTime) >= UPDATE_DELAY / 2) {
							break;
						}
					}

					monitor.done();

					if (currentIndex >= listeners.length) {
						resetState();
						if (!hasPendingUpdates()) {
							decorated();
						}
						labelProviderChangedEvent = null;
						listeners = EMPTY_LISTENER_LIST;
					} else {
						schedule(UPDATE_DELAY);// Reschedule if we are not done
					}
					return Status.OK_STATUS;
				}
				finally {
					// reset the flag
					isUpdateJobRunning = false;
				}
			}

			/**
			 * Clear any cached information.
			 */
			private void resetState() {
				currentIndex = NEEDS_INIT;// Reset
				removedListeners.clear();
				// Other decoration requests may have occurred due to
				// updates or we may have timed out updating listeners.
				// Only clear the results if there are none pending.
				if (awaitingDecoration.isEmpty()) {
					resultCache.clear();
				}
			}

			private void setUpUpdates() {
				// Get the elements awaiting update and then
				// clear the list
				removedListeners.clear();
				currentIndex = 0;
				synchronized (pendingKey) {
					Object[] elements = pendingUpdate.toArray(new Object[pendingUpdate.size()]);
					pendingUpdate.clear();
					labelProviderChangedEvent = new LabelProviderChangedEvent(decoratorManager, elements);
				}
				listeners = decoratorManager.getListeners();
			}

			@Override
			public boolean belongsTo(Object family) {
				return DecoratorManager.FAMILY_DECORATE == family;
			}

			@Override
			public boolean shouldRun() {
				return PlatformUI.isWorkbenchRunning();
			}
		};

		job.setSystem(true);
		job.addJobChangeListener(jobFinishListener);
		return job;
	}

	/**
	 * Return whether or not there is a decoration for this element ready.
	 *
	 * @param element
	 * @param context The decoration context
	 * @return boolean true if the element is ready.
	 */
	public boolean isDecorationReady(Object element, IDecorationContext context) {
		// the decoration is only reported as ready, if we are in the UI thread and if
		// the update job is running.
		// Because the update job is running in the UI thread, it can be the only caller
		// of this method if the flag isUpdateJobRunning is TRUE
		if (isUpdateJobRunning) {
			return internalGetResult(element, context) != null;
		}

		// in all other cases, some other logic than the update job is asking and that
		// should always be answered with false - see Bug 417255
		return false;
	}

	/**
	 * Return the background Color for element. If there is no result cue for
	 * decoration and return null, otherwise return the value in the result.
	 *
	 * @param element        The Object to be decorated
	 * @param adaptedElement
	 * @return Color or <code>null</code> if there is no value or if it is has not
	 *         been decorated yet.
	 */
	public Color getBackgroundColor(Object element, Object adaptedElement) {
		DecorationResult decoration = getResult(element, adaptedElement, DecorationContext.DEFAULT_CONTEXT);

		if (decoration == null) {
			return null;
		}
		return decoration.getBackgroundColor();
	}

	/**
	 * Return the font for element. If there is no result cue for decoration and
	 * return null, otherwise return the value in the result.
	 *
	 * @param element        The Object to be decorated
	 * @param adaptedElement
	 * @return Font or <code>null</code> if there is no value or if it is has not
	 *         been decorated yet.
	 */
	public Font getFont(Object element, Object adaptedElement) {
		DecorationResult decoration = getResult(element, adaptedElement, DecorationContext.DEFAULT_CONTEXT);

		if (decoration == null) {
			return null;
		}
		return decoration.getFont();
	}

	/**
	 * Return the foreground Color for element. If there is no result cue for
	 * decoration and return null, otherwise return the value in the result.
	 *
	 * @param element        The Object to be decorated
	 * @param adaptedElement
	 * @return Color or <code>null</code> if there is no value or if it is has not
	 *         been decorated yet.
	 */
	public Color getForegroundColor(Object element, Object adaptedElement) {
		DecorationResult decoration = getResult(element, adaptedElement, DecorationContext.DEFAULT_CONTEXT);

		if (decoration == null) {
			return null;
		}
		return decoration.getForegroundColor();
	}

	/**
	 * Return whether or not any updates are being processed/
	 *
	 * @return boolean
	 */
	public boolean processingUpdates() {
		return !hasPendingUpdates() && !awaitingDecoration.isEmpty();
	}

	/**
	 * A listener has been removed. If we are updating then skip it.
	 *
	 * @param listener
	 */
	void listenerRemoved(ILabelProviderListener listener) {
		if (updatesPending()) {// Only keep track of them if there are updates
			// pending
			removedListeners.add(listener);
		}
		if (!updatesPending()) {
			removedListeners.remove(listener);
		}

	}

	/**
	 * Return whether or not there are any updates pending.
	 *
	 * @return boolean <code>true</code> if the updates are empty
	 */
	boolean hasPendingUpdates() {
		synchronized (pendingKey) {
			return pendingUpdate.isEmpty();
		}

	}
}
