/*******************************************************************************
 * Copyright (c) 2000, 2006 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
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.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.runtime.Assert;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.ListenerList;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;

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;

import org.eclipse.jdt.core.IJavaProject;

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 fActiveWorkingSets;
	private ListenerList fListeners;
	private IPropertyChangeListener fWorkingSetManagerListener;
	private OthersWorkingSetUpdater fOthersWorkingSetUpdater;

	private ElementMapper fElementMapper= new ElementMapper();

	private boolean fConfigured;

	private static class WorkingSetComparar implements IElementComparer {
		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;
		}
		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[] remove(IWorkingSet ws) {
			IAdaptable[] elements= (IAdaptable[])fWorkingSetToElement.remove(ws);
			if (elements != null) {
				for (int i= 0; i < elements.length; i++) {
					removeElement(elements[i], ws);
				}
			}
			return elements;
		}
		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 IWorkingSet getFirstWorkingSetForResource(IResource resource) {
			return (IWorkingSet)getFirstElement(fResourceToWorkingSet, resource);
		}
		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 IJavaProject)) {
					fNonProjectTopLevelElements.add(element);
				}
			}
		}
		private void addElement(IAdaptable element, IWorkingSet ws) {
			addToMap(fElementToWorkingSet, element, ws);
			IResource resource= (IResource)element.getAdapter(IResource.class);
			if (resource != null) {
				addToMap(fResourceToWorkingSet, resource, ws);
			}
		}
		private void removeElement(IAdaptable element, IWorkingSet ws) {
			removeFromMap(fElementToWorkingSet, element, ws);
			IResource resource= (IResource)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() {
		fLocalWorkingSetManager= PlatformUI.getWorkbench().createLocalWorkingSetManager();
		addListenersToWorkingSetManagers();
		fActiveWorkingSets= new ArrayList(2);

		IWorkingSet others= fLocalWorkingSetManager.createWorkingSet(WorkingSetMessages.WorkingSetModel_others_name, new IAdaptable[0]); 
		others.setId(OthersWorkingSetUpdater.ID);
		fLocalWorkingSetManager.addWorkingSet(others);
		Assert.isNotNull(fOthersWorkingSetUpdater);
		
		fActiveWorkingSets.add(others);

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

	public WorkingSetModel(IMemento memento) {
		fLocalWorkingSetManager= PlatformUI.getWorkbench().createLocalWorkingSetManager();
		addListenersToWorkingSetManagers();
		fActiveWorkingSets= new ArrayList(2);
		
		restoreState(memento); // restore localWorkingSetManager and active working sets
		Assert.isNotNull(fOthersWorkingSetUpdater);
		
		fElementMapper.rebuild(getActiveWorkingSets());
		fOthersWorkingSetUpdater.updateElements();
	}

	private void addListenersToWorkingSetManagers() {
		fListeners= new ListenerList(ListenerList.IDENTITY);
		fWorkingSetManagerListener= new IPropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent 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 &&
		OthersWorkingSetUpdater.ID.equals(((IWorkingSet)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 (IWorkingSet[])fActiveWorkingSets.toArray(new IWorkingSet[fActiveWorkingSets.size()]);
	}

	public IWorkingSet[] getAllWorkingSets() {
		List result= new ArrayList();
		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 (IWorkingSet[])result.toArray(new IWorkingSet[result.size()]);
	}

	public void setActiveWorkingSets(IWorkingSet[] workingSets) {
		fActiveWorkingSets= new ArrayList(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 iter= fActiveWorkingSets.iterator(); iter.hasNext();) {
			IMemento active= memento.createChild(TAG_ACTIVE_WORKING_SET);
			IWorkingSet workingSet= (IWorkingSet)iter.next();
			active.putString(TAG_WORKING_SET_NAME, workingSet.getName());
		}
	}
	
	public List getNonProjectTopLevelElements() {
		return fElementMapper.getNonProjectTopLevelElements();
	}

	private void restoreState(IMemento memento) {
		String configured= memento.getString(TAG_CONFIGURED);
		fConfigured= configured != null && Boolean.valueOf(configured).booleanValue();
		
		fLocalWorkingSetManager.restoreState(memento.getChild(TAG_LOCAL_WORKING_SET_MANAGER));

		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);
				}
			}
		}
	}
	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 elements= new ArrayList(fActiveWorkingSets);
			elements.remove(workingSet);
			setActiveWorkingSets((IWorkingSet[])elements.toArray(new IWorkingSet[elements.size()]));
		} else if (IWorkingSetManager.CHANGE_WORKING_SET_NAME_CHANGE.equals(property)) {
			fireEvent(event);
		}
	}

	private void fireEvent(PropertyChangeEvent event) {
		Object[] listeners= fListeners.getListeners();
		for (int i= 0; i < listeners.length; i++) {
			((IPropertyChangeListener)listeners[i]).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);
	}
}
