/*******************************************************************************
 * Copyright (c) 2009, 2017 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
 *     Daniel Kruegler <daniel.kruegler@gmail.com> - Bug 487417
 *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 492963
 *******************************************************************************/
package org.eclipse.e4.core.internal.contexts;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import org.eclipse.e4.core.contexts.IContextFunction;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.contexts.RunAndTrack;
import org.eclipse.e4.core.di.IInjector;
import org.eclipse.e4.core.internal.contexts.osgi.ContextDebugHelper;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventAdmin;

/**
 * This implementation assumes that all contexts are of the class EclipseContext. The external
 * methods of it are exposed via IEclipseContext.
 */
public class EclipseContext implements IEclipseContext {

	/**
	 * A context key identifying the parent context.
	 */
	public static final String PARENT = "parentContext"; //$NON-NLS-1$

	/**
	 * A context key (value "debugString") identifying a value to use in debug statements for a
	 * context. A computed value can be used to embed more complex information in debug statements.
	 */
	public static final String DEBUG_STRING = "debugString"; //$NON-NLS-1$

	/**
	 * String used in {@link #toString()} to name contexts not providing the value
	 * for the {@link #DEBUG_STRING} variable
	 */
	public static final String ANONYMOUS_CONTEXT_NAME = "Anonymous Context"; //$NON-NLS-1$

	static class Scheduled {

		public TrackableComputationExt runnable;
		public ContextChangeEvent event;

		public Scheduled(TrackableComputationExt runnable, ContextChangeEvent event) {
			this.runnable = runnable;
			this.event = event;
		}

		@Override
		public int hashCode() {
			return 31 * (31 + event.hashCode()) + runnable.hashCode();
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			Scheduled other = (Scheduled) obj;
			if (!event.equals(other.event))
				return false;
			return runnable.equals(other.runnable);
		}
	}

	private WeakGroupedListenerList weakListeners = new WeakGroupedListenerList();
	private Map<String, ValueComputation> localValueComputations = Collections.synchronizedMap(new HashMap<String, ValueComputation>());

	final protected Map<String, Object> localValues = Collections.synchronizedMap(new HashMap<String, Object>());

	private Set<String> modifiable;

	private List<Computation> waiting; // list of Computations; null for all non-root entries

	private Set<WeakReference<EclipseContext>> children = new HashSet<>();

	private Set<IContextDisposalListener> notifyOnDisposal = new HashSet<>();

	static private ThreadLocal<Stack<Computation>> currentComputation = new ThreadLocal<>();

	// I don't think we need to sync referenceQueue access
	private ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();

	private Map<Reference<?>, TrackableComputationExt> activeComputations = Collections.synchronizedMap(new HashMap<Reference<?>, TrackableComputationExt>());
	private Set<TrackableComputationExt> activeRATs = Collections.synchronizedSet(new HashSet<TrackableComputationExt>());

	private final static Object[] nullArgs = new Object[] {null};

	/**
	 * A context key (value "activeChildContext") that identifies another {@link IEclipseContext}
	 * that is a child of the context. The meaning of active is up to the application.
	 */
	public static final String ACTIVE_CHILD = "activeChildContext"; //$NON-NLS-1$

	static private final IEclipseContextDebugger debugAddOn = ContextDebugHelper.getDebugger();

	public EclipseContext(IEclipseContext parent) {
		setParent(parent);
		if (parent == null)
			waiting = Collections.synchronizedList(new ArrayList<Computation>());
		if (debugAddOn != null)
			debugAddOn.notify(this, IEclipseContextDebugger.EventType.CONSTRUCTED, null);
	}

	final static private Set<EclipseContext> noChildren = new HashSet<>(0);

	public Set<EclipseContext> getChildren() {
		Set<EclipseContext> result;
		synchronized (children) {
			if (children.size() == 0)
				return noChildren;
			result = new HashSet<>(children.size());
			for (Iterator<WeakReference<EclipseContext>> i = children.iterator(); i.hasNext();) {
				EclipseContext referredContext = i.next().get();
				if (referredContext == null) {
					i.remove();
					continue;
				}
				result.add(referredContext);
			}
		}
		return result;
	}

	@Override
	public boolean containsKey(String name) {
		trackAccess(name);
		return containsKey(name, false);
	}

	public boolean containsKey(String name, boolean localOnly) {
		if (isSetLocally(name))
			return true;
		if (localOnly)
			return false;
		EclipseContext parent = getParent();
		if (parent != null && parent.containsKey(name, localOnly))
			return true;
		return false;
	}

	@Override
	public void dispose() {
		// dispose of child contexts first
		for (EclipseContext childContext : getChildren()) {
			childContext.dispose();
		}

		ContextChangeEvent event = new ContextChangeEvent(this, ContextChangeEvent.DISPOSE, null, null, null);

		Set<Computation> allComputations = new HashSet<>();
		allComputations.addAll(activeComputations.values());
		allComputations.addAll(activeRATs);
		activeComputations.clear();
		activeRATs.clear();

		Set<Scheduled> scheduled = new LinkedHashSet<>();
		allComputations.addAll(getListeners());
		weakListeners.clear();
		for (Computation computation : allComputations) {
			computation.handleInvalid(event, scheduled);
		}
		processScheduled(scheduled);

		synchronized (notifyOnDisposal) {
			for (IContextDisposalListener listener : notifyOnDisposal) {
				listener.disposed(this);
			}
			notifyOnDisposal.clear();
		}

		for (ValueComputation computation : localValueComputations.values()) {
			computation.dipose();
		}
		localValueComputations.clear();

		// if this was the parent's active child, deactivate it
		EclipseContext parent = getParent();
		EclipseContext rootContext = null;
		if (parent != null) {
			rootContext = getRoot();
			if (this == parent.getActiveChild())
				parent.set(ACTIVE_CHILD, null);
		}

		localValues.clear();

		if (parent != null) {
			parent.removeChild(this);
			if (rootContext != null) {
				rootContext.cleanup();
			}

			// inform the OSGi layer via EventAdmin about the context disposal
			// used for example to be able to cleanup cached requestors in
			// ExtendedObjectSupplier implementations
			EventAdmin admin = parent.get(EventAdmin.class);
			if (admin != null) {
				Event osgiEvent = new Event(IEclipseContext.TOPIC_DISPOSE, (Map<String, ?>) null);
				admin.postEvent(osgiEvent);
			}
		}

		if (debugAddOn != null) {
			debugAddOn.notify(this, IEclipseContextDebugger.EventType.DISPOSED, null);
		}
	}

	@Override
	public Object get(String name) {
		trackAccess(name);
		return internalGet(this, name, false);
	}

	@Override
	public Object getLocal(String name) {
		trackAccess(name);
		return internalGet(this, name, true);
	}

	public Object internalGet(EclipseContext originatingContext, String name, boolean local) {
		if (this == originatingContext) {
			ValueComputation valueComputation = localValueComputations.get(name);
			if (valueComputation != null) {
				Object result = valueComputation.get();
				if (result != IInjector.NOT_A_VALUE) {
					return result;
				}
			}
		}

		Object result = null;
		// 1. try for local value
		if (localValues.containsKey(name)) {
			result = localValues.get(name);
			if (result == null)
				return null;
		} else
			result = lookup(name, originatingContext);

		// if we found something, compute the concrete value and return
		if (result != null) {
			if (result instanceof IContextFunction) {
				ValueComputation valueComputation = new ValueComputation(name, originatingContext, ((IContextFunction) result));
				// do calculations before adding listeners
				result = valueComputation.get();
				originatingContext.localValueComputations.put(name, valueComputation);
			}
			if (result != IInjector.NOT_A_VALUE) {
				return result;
			}
		}
		// 3. delegate to parent
		if (!local) {
			IEclipseContext parent = (IEclipseContext) localValues.get(PARENT);
			if (parent != null) {
				return ((EclipseContext) parent).internalGet(originatingContext, name, local);
			}
		}
		return null;
	}

	/**
	 * The given name has been modified or removed in this context. Invalidate all local value
	 * computations and listeners that depend on this name.
	 */
	public void invalidate(String name, int eventType, Object oldValue, Object newValue, Set<Scheduled> scheduled) {
		ContextChangeEvent event = null;
		ValueComputation computation = localValueComputations.get(name);
		if (computation != null) {
			event = new ContextChangeEvent(this, eventType, null, name, oldValue);
			if (computation.shouldRemove(event)) {
				localValueComputations.remove(name);
				weakListeners.remove(computation);
			}
			computation.handleInvalid(event, scheduled);
		}
		Set<Computation> namedComputations = weakListeners.getListeners(name);
		if (namedComputations != null && namedComputations.size() > 0) {
			if (event == null) {
				event = new ContextChangeEvent(this, eventType, null, name, oldValue);
			}
			for (Computation listener : namedComputations) {
				listener.handleInvalid(event, scheduled);
			}
		}

		// invalidate this name in child contexts
		for (EclipseContext childContext : getChildren()) {
			// unless it is already set in this context (and thus hides the change)
			if ((eventType == ContextChangeEvent.ADDED || eventType == ContextChangeEvent.REMOVED) && childContext.isSetLocally(name))
				continue;
			childContext.invalidate(name, eventType, oldValue, newValue, scheduled);
		}
	}

	protected boolean isLocalEquals(String name, Object newValue) {
		if (!localValues.containsKey(name))
			return false;
		return (localValues.get(name) == newValue);
	}

	private boolean isSetLocally(String name) {
		return localValues.containsKey(name);
	}

	@Override
	public void remove(String name) {
		if (isSetLocally(name)) {
			Object oldValue = localValues.remove(name);
			Set<Scheduled> scheduled = new LinkedHashSet<>();
			invalidate(name, ContextChangeEvent.REMOVED, oldValue, IInjector.NOT_A_VALUE, scheduled);
			processScheduled(scheduled);
		}
	}

	@Override
	public void runAndTrack(final RunAndTrack runnable) {
		TrackableComputationExt computation = new TrackableComputationExt(runnable, this);
		ContextChangeEvent event = new ContextChangeEvent(this, ContextChangeEvent.INITIAL, null, null, null);
		boolean result = computation.update(event);
		if (result) {
			Reference<Object> ref = computation.getReference();
			if (ref != null)
				activeComputations.put(ref, computation);
			else
				activeRATs.add(computation);
		}
	}

	public void removeRAT(Computation computation) {
		// remove from listeners
		weakListeners.remove(computation);
		activeRATs.remove(computation);
	}

	protected void processScheduled(Set<Scheduled> scheduledList) {
		for (Scheduled scheduled : scheduledList) {
			scheduled.runnable.update(scheduled.event);
		}
	}

	@Override
	public void set(String name, Object value) {
		if (PARENT.equals(name)) {
			setParent((IEclipseContext) value);
			return;
		}
		boolean containsKey = localValues.containsKey(name);
		Object oldValue = localValues.put(name, value);
		if (!containsKey || oldValue != value) {
			Set<Scheduled> scheduled = new LinkedHashSet<>();
			invalidate(name, ContextChangeEvent.ADDED, oldValue, value, scheduled);
			processScheduled(scheduled);
		}

		// cleanup unused computation listeners
		Reference<?> ref = referenceQueue.poll();
		if (ref != null) {
			ContextChangeEvent event = new ContextChangeEvent(this, ContextChangeEvent.UNINJECTED, nullArgs, null, null);
			for (; ref != null; ref = referenceQueue.poll()) {
				TrackableComputationExt obsoleteComputation = activeComputations.remove(ref);
				if (obsoleteComputation == null)
					continue;
				obsoleteComputation.update(event);
			}
		}
	}

	@Override
	public void modify(String name, Object value) {
		Set<Scheduled> scheduled = new LinkedHashSet<>();
		if (!internalModify(name, value, scheduled))
			set(name, value);
		processScheduled(scheduled);
	}

	public boolean internalModify(String name, Object value, Set<Scheduled> scheduled) {
		boolean containsKey = localValues.containsKey(name);
		if (containsKey) {
			if (!checkModifiable(name)) {
				String tmp = "Variable " + name + " is not modifiable in the context " + toString(); //$NON-NLS-1$ //$NON-NLS-2$
				throw new IllegalArgumentException(tmp);
			}
			Object oldValue = localValues.put(name, value);
			if (oldValue != value)
				invalidate(name, ContextChangeEvent.ADDED, oldValue, value, scheduled);
			return true;
		}

		EclipseContext parent = getParent();
		if (parent != null)
			return parent.internalModify(name, value, scheduled);
		return false;
	}

	@Override
	public EclipseContext getParent() {
		return (EclipseContext) localValues.get(PARENT);
	}

	@Override
	public void setParent(IEclipseContext parent) {
		EclipseContext parentContext = (EclipseContext) localValues.get(PARENT);
		if (parent == parentContext)
			return; // no-op
		if (parentContext != null)
			parentContext.removeChild(this);
		Set<Scheduled> scheduled = new LinkedHashSet<>();
		handleReparent((EclipseContext) parent, scheduled);
		localValues.put(PARENT, parent);
		if (parent != null)
			((EclipseContext) parent).addChild(this);
		processScheduled(scheduled);
		return;
	}

	/**
	 * Returns a string representation of this context for debugging purposes only.
	 */
	@Override
	public String toString() {
		Object debugString = localValues.get(DEBUG_STRING);
		return debugString instanceof String ? ((String) debugString) : ANONYMOUS_CONTEXT_NAME;
	}

	private void trackAccess(String name) {
		Stack<Computation> current = getCalculatedComputations();
		if (current.isEmpty())
			return;
		Computation computation = current.peek(); // only track in the top-most one
		if (computation == null)
			return;
		addDependency(name, computation);
	}

	public void addDependency(String name, Computation computation) {
		weakListeners.add(name, computation);
	}

	@Override
	public void declareModifiable(String name) {
		if (name == null)
			return;
		if (modifiable == null)
			modifiable = new HashSet<>(3);
		modifiable.add(name);
		if (localValues.containsKey(name))
			return;
		localValues.put(name, null);
	}

	private boolean checkModifiable(String name) {
		if (modifiable == null)
			return false;
		return modifiable.contains(name);
	}

	public void removeListenersTo(Object object) {
		if (object == null)
			return;
		ContextChangeEvent event = new ContextChangeEvent(this, ContextChangeEvent.UNINJECTED, new Object[] {object}, null, null);
		Set<Computation> comps = getListeners();
		for (Computation computation : comps) {
			if (computation instanceof TrackableComputationExt)
				((TrackableComputationExt) computation).update(event);
		}
	}

	public Set<Computation> getListeners() {
		return weakListeners.getListeners();
	}

	private void handleReparent(EclipseContext newParent, Set<Scheduled> scheduled) {
		// TBD should we lock waiting list while doing reparent?
		// Add "boolean inReparent" on the root context and process right away?
		processWaiting();
		// 1) everybody who depends on me: I need to collect combined list of names injected
		Set<String> usedNames = new HashSet<>();
		collectDependentNames(usedNames);

		// 2) for each used name:
		for (String name : usedNames) {
			if (localValues.containsKey(name))
				continue; // it is a local value
			Object oldValue = get(name);
			Object newValue = (newParent != null) ? newParent.get(name) : null;
			if (oldValue != newValue)
				invalidate(name, ContextChangeEvent.ADDED, oldValue, newValue, scheduled);
		}

		invalidateLocalComputations(scheduled);
	}

	protected void invalidateLocalComputations(Set<Scheduled> scheduled) {
		ContextChangeEvent event = new ContextChangeEvent(this, ContextChangeEvent.ADDED, null, null, null);
		for (Computation computation : localValueComputations.values()) {
			weakListeners.remove(computation);
			computation.handleInvalid(event, scheduled);
		}
		localValueComputations.clear();

		// We need to cleanup computations recursively see bug 468048
		for (EclipseContext c : getChildren()) {
			c.invalidateLocalComputations(scheduled);
		}
	}

	private void collectDependentNames(Set<String> usedNames) {
		Set<String> names = weakListeners.getNames();
		usedNames.addAll(names);
		for (EclipseContext childContext : getChildren()) {
			childContext.collectDependentNames(usedNames);
		}
	}

	@Override
	public void processWaiting() {
		// traverse to the root node
		EclipseContext parent = getParent();
		if (parent != null) {
			parent.processWaiting();
			return;
		}
		if (waiting == null || waiting.isEmpty())
			return;
		// create update notifications
		Computation[] ls = waiting.toArray(new Computation[waiting.size()]);
		waiting.clear();
		ContextChangeEvent event = new ContextChangeEvent(this, ContextChangeEvent.UPDATE, null, null, null);
		for (Computation element : ls) {
			if (element instanceof TrackableComputationExt)
				((TrackableComputationExt) element).update(event);
		}
	}

	public void addWaiting(Computation cp) {
		// traverse to the root node
		EclipseContext parent = getParent();
		if (parent != null) {
			parent.addWaiting(cp);
			return;
		}
		if (waiting == null) // could happen on re-parent
			waiting = Collections.synchronizedList(new ArrayList<Computation>());
		waiting.add(cp);
	}

	protected EclipseContext getRoot() {
		EclipseContext current = this;
		EclipseContext root;
		do {
			root = current;
			current = current.getParent();
		} while (current != null);
		return root;
	}

	public void addChild(EclipseContext childContext) {
		synchronized (children) {
			children.add(new WeakReference<>(childContext));
		}
	}

	public void removeChild(EclipseContext childContext) {
		synchronized (children) {
			for (Iterator<WeakReference<EclipseContext>> i = children.iterator(); i.hasNext();) {
				EclipseContext referredContext = i.next().get();
				if (referredContext == null) {
					i.remove();
					continue;
				}
				if (referredContext == childContext) {
					i.remove();
					return;
				}
			}
		}
	}

	@Override
	public <T> T get(Class<T> clazz) {
		return clazz.cast(get(clazz.getName()));
	}

	@Override
	public boolean containsKey(Class<?> clazz) {
		return containsKey(clazz.getName());
	}

	@Override
	public <T> void set(Class<T> clazz, T value) {
		set(clazz.getName(), value);
	}

	@Override
	public void remove(Class<?> clazz) {
		remove(clazz.getName());
	}

	@Override
	public <T> T getLocal(Class<T> clazz) {
		return clazz.cast(getLocal(clazz.getName()));
	}

	@Override
	public <T> void modify(Class<T> clazz, T value) {
		modify(clazz.getName(), value);
	}

	@Override
	public void declareModifiable(Class<?> clazz) {
		declareModifiable(clazz.getName());
	}

	@Override
	public IEclipseContext createChild() {
		return new EclipseContext(this); // strategies are not inherited
	}

	@Override
	public IEclipseContext createChild(String name) {
		IEclipseContext result = createChild();
		result.set(DEBUG_STRING, name);
		return result;
	}

	public void notifyOnDisposal(IContextDisposalListener listener) {
		synchronized (notifyOnDisposal) {
			notifyOnDisposal.add(listener);
		}
	}

	@Override
	public IEclipseContext getActiveChild() {
		trackAccess(ACTIVE_CHILD);
		return (EclipseContext) internalGet(this, ACTIVE_CHILD, true);
	}

	@Override
	public IEclipseContext getActiveLeaf() {
		IEclipseContext activeContext = this;
		IEclipseContext child = getActiveChild();
		while (child != null) {
			activeContext = child;
			child = child.getActiveChild();
		}
		return activeContext;
	}

	@Override
	public void activate() {
		EclipseContext parent = getParent();
		if (parent == null)
			return;
		if (this == parent.getActiveChild())
			return;
		parent.set(ACTIVE_CHILD, this);
		if (debugAddOn != null) {
			debugAddOn.notify(this, IEclipseContextDebugger.EventType.ACTIVATED, null);
		}
	}

	@Override
	public void activateBranch() {
		for (IEclipseContext i = this; i != null; i = i.getParent()) {
			i.activate();
		}
	}

	@Override
	public void deactivate() {
		EclipseContext parent = getParent();
		if (parent == null)
			return;
		if (this != parent.getActiveChild())
			return; // this is not an active context; return
		parent.set(ACTIVE_CHILD, null);
		if (debugAddOn != null) {
			debugAddOn.notify(this, IEclipseContextDebugger.EventType.DEACTIVATED, null);
		}
	}

	// This method is for debug only, do not use externally
	public Map<String, Object> localData() {
		Map<String, Object> result = new HashMap<>(localValues.size());
		for (Map.Entry<String, Object> entry : localValues.entrySet()) {
			if (entry.getValue() instanceof IContextFunction) {
				continue;
			}
			result.put(entry.getKey(), entry.getValue());
		}
		return result;
	}

	// This method is for debug only, do not use externally
	public Map<String, Object> localContextFunction() {
		Map<String, Object> result = new HashMap<>(localValues.size());
		for (Map.Entry<String, Object> entry : localValues.entrySet()) {
			if (entry.getValue() instanceof IContextFunction) {
				result.put(entry.getKey(), entry.getValue());
			}
		}
		return result;
	}

	// This method is for debug only, do not use externally
	public Map<String, Object> cachedCachedContextFunctions() {
		Map<String, Object> result = new HashMap<>(localValueComputations.size());
		for (Map.Entry<String, ValueComputation> entry : localValueComputations.entrySet()) {
			if (entry.getValue() != null) {
				Object r = entry.getValue();
				if (r != IInjector.NOT_A_VALUE) {
					result.put(entry.getKey(), entry.getValue());
				}
			}
		}
		return result;
	}

	// This method is for debug only, do not use externally
	public Set<String> getRawListenerNames() {
		return weakListeners.getNames();
	}

	// This method is for debug only, do not use externally
	public Set<Computation> getListeners(String name) {
		return weakListeners.getListeners(name);
	}

	static public Stack<Computation> getCalculatedComputations() {
		Stack<Computation> current = currentComputation.get();
		if (current == null) {
			current = new Stack<>();
			currentComputation.set(current);
		}
		return current;
	}

	public void pushComputation(Computation comp) {
		Stack<Computation> current = getCalculatedComputations();
		current.push(comp);
	}

	public void popComputation(Computation comp) {
		Stack<Computation> current = getCalculatedComputations();
		Computation ended = current.pop();
		if (ended != comp)
			throw new IllegalArgumentException("Internal error: Invalid nested computation processing"); //$NON-NLS-1$
	}

	/**
	 * This method can be overriden to provide additional source for the requested data.
	 * The override is expected to take care of initiating dynamic updates.
	 */
	protected Object lookup(String name, EclipseContext originatingContext) {
		return null;
	}

	@Override
	public <T> T getActive(Class<T> clazz) {
		return clazz.cast(getActive(clazz.getName()));
	}

	@Override
	public Object getActive(final String name) {
		return getActiveLeaf().get(name);
	}

	public WeakReference<Object> trackedWeakReference(Object object) {
		return new WeakReference<>(object, referenceQueue);
	}

	public void cleanup() {
		for (EclipseContext childContext : getChildren()) {
			childContext.cleanup();
		}
		weakListeners.cleanup();
	}
}
