/*******************************************************************************
 * Copyright (c) 2000, 2017 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
 *
 *******************************************************************************/
package org.eclipse.dltk.internal.ui.workingsets;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.IElementComparer;
import org.eclipse.ui.ILocalWorkingSetManager;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.IWorkingSetUpdater;
import org.eclipse.ui.PlatformUI;

public class WorkingSetModel {

	public static final String CHANGE_WORKING_SET_MODEL_CONTENT = "workingSetModelChanged"; //$NON-NLS-1$

	public static final IElementComparer COMPARER = new WorkingSetComparar();

	private static final String TAG_LOCAL_WORKING_SET_MANAGER = "localWorkingSetManager"; //$NON-NLS-1$
	private static final String TAG_ACTIVE_WORKING_SET = "activeWorkingSet"; //$NON-NLS-1$
	private static final String TAG_WORKING_SET_NAME = "workingSetName"; //$NON-NLS-1$
	private static final String TAG_CONFIGURED = "configured"; //$NON-NLS-1$

	private ILocalWorkingSetManager fLocalWorkingSetManager;
	private List<IWorkingSet> fActiveWorkingSets;
	private ListenerList<IPropertyChangeListener> fListeners;
	private IPropertyChangeListener fWorkingSetManagerListener;
	private OthersWorkingSetUpdater fOthersWorkingSetUpdater;

	private ElementMapper fElementMapper = new ElementMapper();

	private boolean fConfigured;

	private static class WorkingSetComparar implements IElementComparer {
		@Override
		public boolean equals(Object o1, Object o2) {
			IWorkingSet w1 = o1 instanceof IWorkingSet ? (IWorkingSet) o1
					: null;
			IWorkingSet w2 = o2 instanceof IWorkingSet ? (IWorkingSet) o2
					: null;
			if (w1 == null || w2 == null)
				return o1.equals(o2);
			return w1 == w2;
		}

		@Override
		public int hashCode(Object element) {
			if (element instanceof IWorkingSet)
				return System.identityHashCode(element);
			return element.hashCode();
		}
	}

	private static class ElementMapper {
		private Map fElementToWorkingSet = new HashMap();
		private Map fWorkingSetToElement = new IdentityHashMap();

		private Map fResourceToWorkingSet = new HashMap();
		private List fNonProjectTopLevelElements = new ArrayList();

		public void clear() {
			fElementToWorkingSet.clear();
			fWorkingSetToElement.clear();
			fResourceToWorkingSet.clear();
			fNonProjectTopLevelElements.clear();
		}

		public void rebuild(IWorkingSet[] workingSets) {
			clear();
			for (int i = 0; i < workingSets.length; i++) {
				put(workingSets[i]);
			}
		}

		public IAdaptable[] refresh(IWorkingSet ws) {
			IAdaptable[] oldElements = (IAdaptable[]) fWorkingSetToElement
					.get(ws);
			if (oldElements == null)
				return null;
			IAdaptable[] newElements = ws.getElements();
			List toRemove = new ArrayList(Arrays.asList(oldElements));
			List toAdd = new ArrayList(Arrays.asList(newElements));
			computeDelta(toRemove, toAdd, oldElements, newElements);
			for (Iterator iter = toAdd.iterator(); iter.hasNext();) {
				addElement((IAdaptable) iter.next(), ws);
			}
			for (Iterator iter = toRemove.iterator(); iter.hasNext();) {
				removeElement((IAdaptable) iter.next(), ws);
			}
			if (toRemove.size() > 0 || toAdd.size() > 0)
				fWorkingSetToElement.put(ws, newElements);
			return oldElements;
		}

		private void computeDelta(List toRemove, List toAdd,
				IAdaptable[] oldElements, IAdaptable[] newElements) {
			for (int i = 0; i < oldElements.length; i++) {
				toAdd.remove(oldElements[i]);
			}
			for (int i = 0; i < newElements.length; i++) {
				toRemove.remove(newElements[i]);
			}

		}

		public IWorkingSet getFirstWorkingSet(Object element) {
			return (IWorkingSet) getFirstElement(fElementToWorkingSet, element);
		}

		public List getAllWorkingSets(Object element) {
			return getAllElements(fElementToWorkingSet, element);
		}

		public List getAllWorkingSetsForResource(IResource resource) {
			return getAllElements(fResourceToWorkingSet, resource);
		}

		public List getNonProjectTopLevelElements() {
			return fNonProjectTopLevelElements;
		}

		private void put(IWorkingSet ws) {
			if (fWorkingSetToElement.containsKey(ws))
				return;
			IAdaptable[] elements = ws.getElements();
			fWorkingSetToElement.put(ws, elements);
			for (int i = 0; i < elements.length; i++) {
				IAdaptable element = elements[i];
				addElement(element, ws);
				if (!(element instanceof IProject)
						&& !(element instanceof IScriptProject)) {
					fNonProjectTopLevelElements.add(element);
				}
			}
		}

		private void addElement(IAdaptable element, IWorkingSet ws) {
			addToMap(fElementToWorkingSet, element, ws);
			IResource resource = element.getAdapter(IResource.class);
			if (resource != null) {
				addToMap(fResourceToWorkingSet, resource, ws);
			}
		}

		private void removeElement(IAdaptable element, IWorkingSet ws) {
			removeFromMap(fElementToWorkingSet, element, ws);
			IResource resource = element.getAdapter(IResource.class);
			if (resource != null) {
				removeFromMap(fResourceToWorkingSet, resource, ws);
			}
		}

		private void addToMap(Map map, IAdaptable key, IWorkingSet value) {
			Object obj = map.get(key);
			if (obj == null) {
				map.put(key, value);
			} else if (obj instanceof IWorkingSet) {
				List l = new ArrayList(2);
				l.add(obj);
				l.add(value);
				map.put(key, l);
			} else if (obj instanceof List) {
				((List) obj).add(value);
			}
		}

		private void removeFromMap(Map map, IAdaptable key, IWorkingSet value) {
			Object current = map.get(key);
			if (current == null) {
				return;
			} else if (current instanceof List) {
				List list = (List) current;
				list.remove(value);
				switch (list.size()) {
				case 0:
					map.remove(key);
					break;
				case 1:
					map.put(key, list.get(0));
					break;
				}
			} else if (current == value) {
				map.remove(key);
			}
		}

		private Object getFirstElement(Map map, Object key) {
			Object obj = map.get(key);
			if (obj instanceof List)
				return ((List) obj).get(0);
			return obj;
		}

		private List getAllElements(Map map, Object key) {
			Object obj = map.get(key);
			if (obj instanceof List)
				return (List) obj;
			if (obj == null)
				return Collections.EMPTY_LIST;
			List result = new ArrayList(1);
			result.add(obj);
			return result;
		}
	}

	public WorkingSetModel(IMemento memento) {
		fLocalWorkingSetManager = PlatformUI.getWorkbench()
				.createLocalWorkingSetManager();
		addListenersToWorkingSetManagers();
		fActiveWorkingSets = new ArrayList<IWorkingSet>(2);

		if (memento == null || !restoreState(memento)) {
			IWorkingSet others = fLocalWorkingSetManager.createWorkingSet(
					WorkingSetMessages.WorkingSetModel_others_name,
					new IAdaptable[0]);
			others.setId(WorkingSetIDs.OTHERS);
			fLocalWorkingSetManager.addWorkingSet(others);
			fActiveWorkingSets.add(others);
		}
		Assert.isNotNull(fOthersWorkingSetUpdater);

		fElementMapper.rebuild(getActiveWorkingSets());
		fOthersWorkingSetUpdater.updateElements();
	}

	private void addListenersToWorkingSetManagers() {
		fListeners = new ListenerList<>(ListenerList.IDENTITY);
		fWorkingSetManagerListener = event -> workingSetManagerChanged(event);
		PlatformUI.getWorkbench().getWorkingSetManager()
				.addPropertyChangeListener(fWorkingSetManagerListener);
		fLocalWorkingSetManager
				.addPropertyChangeListener(fWorkingSetManagerListener);
	}

	public void dispose() {
		if (fWorkingSetManagerListener != null) {
			PlatformUI.getWorkbench().getWorkingSetManager()
					.removePropertyChangeListener(fWorkingSetManagerListener);
			fLocalWorkingSetManager
					.removePropertyChangeListener(fWorkingSetManagerListener);
			fLocalWorkingSetManager.dispose();
			fWorkingSetManagerListener = null;
		}
	}

	// ---- model relationships ---------------------------------------

	public IAdaptable[] getChildren(IWorkingSet workingSet) {
		return workingSet.getElements();
	}

	public Object getParent(Object element) {
		if (element instanceof IWorkingSet
				&& fActiveWorkingSets.contains(element))
			return this;
		return fElementMapper.getFirstWorkingSet(element);
	}

	public Object[] getAllParents(Object element) {
		if (element instanceof IWorkingSet
				&& fActiveWorkingSets.contains(element))
			return new Object[] { this };
		return fElementMapper.getAllWorkingSets(element).toArray();
	}

	public Object[] addWorkingSets(Object[] elements) {
		List result = null;
		for (int i = 0; i < elements.length; i++) {
			Object element = elements[i];
			List sets = null;
			if (element instanceof IResource) {
				sets = fElementMapper
						.getAllWorkingSetsForResource((IResource) element);
			} else {
				sets = fElementMapper.getAllWorkingSets(element);
			}
			if (sets != null && sets.size() > 0) {
				if (result == null)
					result = new ArrayList(Arrays.asList(elements));
				result.addAll(sets);
			}
		}
		if (result == null)
			return elements;
		return result.toArray();
	}

	public boolean needsConfiguration() {
		return !fConfigured && fActiveWorkingSets.size() == 1
				&& WorkingSetIDs.OTHERS
						.equals(fActiveWorkingSets.get(0).getId());
	}

	public void configured() {
		fConfigured = true;
	}

	// ---- working set management -----------------------------------

	/**
	 * Adds a property change listener.
	 *
	 * @param listener
	 *            the property change listener to add
	 */
	public void addPropertyChangeListener(IPropertyChangeListener listener) {
		fListeners.add(listener);
	}

	/**
	 * Removes the property change listener.
	 *
	 * @param listener
	 *            the property change listener to remove
	 */
	public void removePropertyChangeListener(IPropertyChangeListener listener) {
		fListeners.remove(listener);
	}

	public IWorkingSet[] getActiveWorkingSets() {
		return fActiveWorkingSets
				.toArray(new IWorkingSet[fActiveWorkingSets.size()]);
	}

	public IWorkingSet[] getAllWorkingSets() {
		List<IWorkingSet> result = new ArrayList<IWorkingSet>();
		result.addAll(fActiveWorkingSets);
		IWorkingSet[] locals = fLocalWorkingSetManager.getWorkingSets();
		for (int i = 0; i < locals.length; i++) {
			if (!result.contains(locals[i]))
				result.add(locals[i]);
		}
		IWorkingSet[] globals = PlatformUI.getWorkbench().getWorkingSetManager()
				.getWorkingSets();
		for (int i = 0; i < globals.length; i++) {
			if (!result.contains(globals[i]))
				result.add(globals[i]);
		}
		return result.toArray(new IWorkingSet[result.size()]);
	}

	public void setActiveWorkingSets(IWorkingSet[] workingSets) {
		fActiveWorkingSets = new ArrayList<IWorkingSet>(
				Arrays.asList(workingSets));
		fElementMapper.rebuild(getActiveWorkingSets());
		fOthersWorkingSetUpdater.updateElements();
		fireEvent(new PropertyChangeEvent(this,
				CHANGE_WORKING_SET_MODEL_CONTENT, null, null));
	}

	public void saveState(IMemento memento) {
		memento.putString(TAG_CONFIGURED, Boolean.toString(fConfigured));
		fLocalWorkingSetManager
				.saveState(memento.createChild(TAG_LOCAL_WORKING_SET_MANAGER));
		for (Iterator<IWorkingSet> iter = fActiveWorkingSets.iterator(); iter
				.hasNext();) {
			IMemento active = memento.createChild(TAG_ACTIVE_WORKING_SET);
			IWorkingSet workingSet = iter.next();
			active.putString(TAG_WORKING_SET_NAME, workingSet.getName());
		}
	}

	public List getNonProjectTopLevelElements() {
		return fElementMapper.getNonProjectTopLevelElements();
	}

	private boolean restoreState(IMemento memento) {
		String configured = memento.getString(TAG_CONFIGURED);
		if (configured == null) {
			return false;
		}
		fConfigured = Boolean.valueOf(configured).booleanValue();

		final IMemento wsManagerMemento = memento
				.getChild(TAG_LOCAL_WORKING_SET_MANAGER);
		if (wsManagerMemento != null) {
			fLocalWorkingSetManager.restoreState(wsManagerMemento);
		}

		IMemento[] actives = memento.getChildren(TAG_ACTIVE_WORKING_SET);
		for (int i = 0; i < actives.length; i++) {
			String name = actives[i].getString(TAG_WORKING_SET_NAME);
			if (name != null) {
				IWorkingSet ws = fLocalWorkingSetManager.getWorkingSet(name);
				if (ws == null) {
					ws = PlatformUI.getWorkbench().getWorkingSetManager()
							.getWorkingSet(name);
				}
				if (ws != null) {
					fActiveWorkingSets.add(ws);
				}
			}
		}
		return true;
	}

	private void workingSetManagerChanged(PropertyChangeEvent event) {
		String property = event.getProperty();
		if (IWorkingSetManager.CHANGE_WORKING_SET_UPDATER_INSTALLED.equals(
				property) && event.getSource() == fLocalWorkingSetManager) {
			IWorkingSetUpdater updater = (IWorkingSetUpdater) event
					.getNewValue();
			if (updater instanceof OthersWorkingSetUpdater) {
				fOthersWorkingSetUpdater = (OthersWorkingSetUpdater) updater;
				fOthersWorkingSetUpdater.init(this);
			}
			return;
		}
		// don't handle working sets not managed by the model
		if (!isAffected(event))
			return;

		if (IWorkingSetManager.CHANGE_WORKING_SET_CONTENT_CHANGE
				.equals(property)) {
			IWorkingSet workingSet = (IWorkingSet) event.getNewValue();
			IAdaptable[] elements = fElementMapper.refresh(workingSet);
			if (elements != null) {
				fireEvent(event);
			}
		} else if (IWorkingSetManager.CHANGE_WORKING_SET_REMOVE
				.equals(property)) {
			IWorkingSet workingSet = (IWorkingSet) event.getOldValue();
			List<IWorkingSet> elements = new ArrayList<IWorkingSet>(
					fActiveWorkingSets);
			elements.remove(workingSet);
			setActiveWorkingSets(
					elements.toArray(new IWorkingSet[elements.size()]));
		} else if (IWorkingSetManager.CHANGE_WORKING_SET_NAME_CHANGE
				.equals(property)) {
			fireEvent(event);
		}
	}

	private void fireEvent(PropertyChangeEvent event) {
		for (IPropertyChangeListener listener : fListeners) {
			listener.propertyChange(event);
		}
	}

	private boolean isAffected(PropertyChangeEvent event) {
		if (fActiveWorkingSets == null)
			return false;
		Object oldValue = event.getOldValue();
		Object newValue = event.getNewValue();
		if ((oldValue != null && fActiveWorkingSets.contains(oldValue))
				|| (newValue != null
						&& fActiveWorkingSets.contains(newValue))) {
			return true;
		}
		return false;
	}

	public boolean isActiveWorkingSet(IWorkingSet changedWorkingSet) {
		return fActiveWorkingSets.contains(changedWorkingSet);
	}
}
