/*******************************************************************************
 * Copyright (c) 2006 Sybase, Inc. 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:
 *     Sybase, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.pagedesigner.editors.palette.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.ReentrantLock;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.content.IContentTypeManager;
import org.eclipse.gef.palette.PaletteDrawer;
import org.eclipse.gef.palette.PaletteEntry;
import org.eclipse.jst.jsf.common.internal.JSPUtil;
import org.eclipse.jst.jsf.common.runtime.internal.view.model.common.Namespace;
import org.eclipse.jst.jsf.core.internal.CompositeTagRegistryFactory;
import org.eclipse.jst.jsf.core.internal.CompositeTagRegistryFactory.TagRegistryIdentifier;
import org.eclipse.jst.jsf.designtime.internal.view.model.ITagRegistry;
import org.eclipse.jst.jsf.designtime.internal.view.model.ITagRegistry.ITagRegistryListener;
import org.eclipse.jst.jsf.designtime.internal.view.model.ITagRegistry.TagRegistryChangeEvent;
import org.eclipse.jst.jsf.designtime.internal.view.model.ITagRegistry.TagRegistryChangeEvent.EventType;
import org.eclipse.jst.pagedesigner.PDPlugin;
import org.eclipse.jst.pagedesigner.editors.palette.DesignerPaletteCustomizationsHelper;
import org.eclipse.jst.pagedesigner.editors.palette.IEntryChangeListener;
import org.eclipse.jst.pagedesigner.editors.palette.IPaletteConstants;
import org.eclipse.jst.pagedesigner.editors.palette.IPaletteContext;
import org.eclipse.jst.pagedesigner.editors.palette.IPaletteItemManager;
import org.eclipse.wst.html.core.internal.contentmodel.HTMLCMDocumentFactory;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
import org.eclipse.wst.xml.core.internal.provisional.contentmodel.CMDocType;

/**
 *  Manages tag library palette by palette context.   Capable of handling JSP and XHTML content types.
 *  
 *  Callers must use getInstance(IPaletteContext), and when done, call release(IFile).   
 *  
 * @author mengbo and others
 */
public class PaletteItemManager implements IPaletteItemManager,
		IPaletteConstants, ITagRegistryListener {
	
	private static final boolean DEBUG = false;

	
	private static Map<TagRegistryIdentifier, PaletteItemManager> _managers = new HashMap<TagRegistryIdentifier, PaletteItemManager>();
	private static ReentrantLock MANAGER_LOCK = new ReentrantLock();
	private static long MANAGER_LOCK_TIMEOUT = 120;
	
	private Set<IFile> _files = new HashSet<IFile>();
	private TagRegistryIdentifier _tagRegId;
	private List<PaletteDrawer> _paletteCategories = new ArrayList<PaletteDrawer>();
	private CopyOnWriteArrayList<IEntryChangeListener> _listeners = new CopyOnWriteArrayList<IEntryChangeListener>();
	private AtomicBoolean IS_DISPOSED = new AtomicBoolean();

	private PaletteHelper _paletteHelper;

	private ITagRegistry _tagRegistry;


	/**
	 * Return singleton paletteItemManager for a given project.  Will only work for JSPs.
	 * @param project
	 * @return PaletteItemManager
	 * @deprecated - use getInstance(paletteContext)
	 */
	public static PaletteItemManager getInstance(final IProject project) {
		if (project == null) {
			// sometimes when the editor is editing a file in jar file, may not
			// be able to
			// get the project.
			return getInstance(createPaletteContext(null));
		}		
		//relies on JSP file extension for content type
		return getInstance(createPaletteContext(project.getFile("dummy.jsp")));  //$NON-NLS-1$
	}
	
	/**
	 * @param paletteContext
	 * @return PaletteItemManager instance shared with all files with same palette context in a project
	 * 				May return null if locking issue 
	 */
	public static PaletteItemManager getInstance(final IPaletteContext paletteContext) {	
		boolean hasLock = false;
		try {
			if (MANAGER_LOCK.tryLock(MANAGER_LOCK_TIMEOUT, TimeUnit.SECONDS)){
				hasLock = true;
				final TagRegistryIdentifier regId = getTagRegistryIdentifier(paletteContext);
				if (regId == null) {
					PDPlugin.log(new Status(IStatus.ERROR, PDPlugin.getPluginId(), "Unable to display palette for "+paletteContext.getFile().getName()+".  Unknown content type for file."));  //$NON-NLS-1$//$NON-NLS-2$
					return null;
				}
				PaletteItemManager manager = _managers.get(regId);
				if (manager == null) {
					 manager = new PaletteItemManager(regId);
					_managers.put(regId, manager);
					manager.init();
				} 
				manager.addFile(paletteContext.getFile());
				return manager;
				
			}
			//if we get here then the lock has timed out
			PDPlugin.log(new Status(Status.ERROR, PDPlugin.getPluginId(), "(getInstance()) Failed to get managers lock for" + paletteContext.getFile().toString())); //$NON-NLS-1$
			
		} catch (InterruptedException e) {
			PDPlugin.log("Failed in PaletteItemManager.getInstance(PaletteContext", e); //$NON-NLS-1$
		} finally {
			if (hasLock)
				MANAGER_LOCK.unlock();
		}
		return null;
	}
	
	private static TagRegistryIdentifier getTagRegistryIdentifier(
			final IPaletteContext paletteContext) {

		final IFile file = paletteContext.getFile();
		if (file != null) {
	        final IContentTypeManager typeManager = Platform.getContentTypeManager();
	        final IContentType contentType = 
	            typeManager.findContentTypeFor(file.getName());
	        
	        if (contentType != null)
	        {
	            return new TagRegistryIdentifier(file.getProject(), contentType);
	        }
	        return null;
		}
		//to support legacy null projects.   Allows HTML and JSP tag libs to be displayed.
	    return new TagRegistryIdentifier(null, org.eclipse.jst.pagedesigner.utils.JSPUtil.JSP_CONTENTTYPE);

	}

	/**
	 * @param file
	 * @return IPaletteContext
	 */
	public static IPaletteContext createPaletteContext(final IFile file) {
		return new IPaletteContext() {
			public IFile getFile() {
				return file;
			}

			public Object getAdapter(Class adapter) {				
				return null;
			}
		};
	}
	private void addFile(final IFile file) {
		synchronized (_files) {
			_files.add(file);
		}
		
	}
	
	/**
	 * Indicates that the file no longer needs the paletteItemManager, freeing the manager to be released after last reference
	 * @param paletteContext
	 */
	public void release(final IPaletteContext paletteContext) { 
		final IFile file = paletteContext.getFile();
		boolean isEmpty = false;
		synchronized (_files) {
			if (_files.contains(file)) {
				_files.remove(file);
				if (_files.isEmpty())
					isEmpty = true;
			}
		}

		if (isEmpty && IS_DISPOSED.compareAndSet(false, true)) {
			removeTagRegistryListeners(this);
			boolean hasLock = false;
			try {
				if (MANAGER_LOCK.tryLock(MANAGER_LOCK_TIMEOUT, TimeUnit.SECONDS)) {
					hasLock = true;
					_managers.remove(_tagRegId);
				}
				else {
					PDPlugin.log(new Status(Status.ERROR, PDPlugin.getPluginId(), "(Release) Failed to get managers lock for" + paletteContext.getFile().toString())); //$NON-NLS-1$
				}
			} catch (InterruptedException e) {
				PDPlugin.log("Failed to release paletteItemManager for" + paletteContext.getFile().toString(), e); //$NON-NLS-1$
			} finally {
				if (hasLock)
					MANAGER_LOCK.unlock();
			}
		}
	}

	private static void removeTagRegistryListeners(final PaletteItemManager manager) {
		if (manager.getTagRegistry() != null)
			manager.getTagRegistry().removeListener(manager);
	}

	private ITagRegistry getTagRegistry() {		
		return _tagRegistry;
	}

	/**
	 * For JUnit testing purposes only
	 */
	public static void clearPaletteItemManager() {
		
		boolean hasLock = false;
		try {
			if (MANAGER_LOCK.tryLock(MANAGER_LOCK_TIMEOUT, TimeUnit.SECONDS)){
				hasLock = true;
				if (_managers == null)
					return;

				for (final PaletteItemManager manager : _managers.values()) {
					PaletteItemManager.removeTagRegistryListeners(manager);		
					manager._files.clear();
				}							
				_managers.clear();
			} else {
				//if we get here then the lock has timed out
				PDPlugin.log(new Status(Status.ERROR, PDPlugin.getPluginId(), "(clear) Failed to get managers lock")); //$NON-NLS-1$
			}
			
		} catch (InterruptedException e) {
			PDPlugin.log("Failed in clearPaletteItemManager", e); //$NON-NLS-1$
		} finally {
			if (hasLock)
				MANAGER_LOCK.unlock();
		}

	}
	
	private PaletteItemManager(final TagRegistryIdentifier regId) {
		_paletteHelper = new PaletteHelper(this);
		if (regId != null) {
			_tagRegId = regId;
//			init();
		}		
	}
	

	public List getAllCategories() {	
		synchronized (_paletteCategories) {
			final List<PaletteDrawer> readOnlyCategories = new ArrayList<PaletteDrawer>(_paletteCategories);			
			return Collections.unmodifiableList(readOnlyCategories);
		}		
	}

	/**
	 * Initializes the palette items for the current project
	 */
	protected synchronized void init() {
		synchronized (_paletteCategories) {
			_paletteCategories.clear();
		}
		
		initTagRegistry();

		DesignerPaletteCustomizationsHelper.loadUserCustomizations(this);
		
		sortCategories();
	}

	/**
	 * Sort palette categories
	 */
	protected void sortCategories() {
		//note that once we store ordering customizations, we will need to do something different
		synchronized(_paletteCategories) {
			Collections.sort(_paletteCategories, new Comparator(){
	
				public int compare(Object o1, Object o2) {
					String label1 = ((PaletteEntry)o1).getLabel();
					String label2 = ((PaletteEntry)o2).getLabel();
					
					return label1.compareTo(label2);
				}
				
			});
		}
	}

	/**
	 * Reinitializes the palatteItemManager and informs all palette roots that use the manager to refresh
	 */
	public void reset() {
		init();
		fireModelChanged(null, null);
	}
	
	private void initTagRegistry() {
		registerHTMLCategory();
		if (isJSP(_tagRegId))
			registerJSPCategory();			
		
		registerTagsFromTagRegistry();	
	}

	private boolean isJSP(final TagRegistryIdentifier tagRegistryId) {
		final IContentType ct = tagRegistryId.getContentType();
		if (JSPUtil.isJSPContentType(ct.getId()))
			return true;
		return false;
	}

	private void registerTagsFromTagRegistry() {
		_tagRegistry = getTagRegistry(_tagRegId);
		if (_tagRegistry != null) {
			for (final Namespace ns : _tagRegistry.getAllTagLibraries()) {							
				_paletteHelper.configPaletteItemsByNamespace(this, ns);			
			}
		}
	}

	private ITagRegistry getTagRegistry(final TagRegistryIdentifier regId) {
		ITagRegistry reg = null;
		if (regId.getProject() != null) {
			reg = CompositeTagRegistryFactory.getInstance().getRegistry(regId);
			if (reg != null) {
				reg.addListener(this);
			}
		}
		return reg;
	}

	private void registerHTMLCategory() {
		final CMDocument doc = HTMLCMDocumentFactory.getCMDocument(CMDocType.HTML_DOC_TYPE);
		_paletteHelper.getOrCreateTaglibPaletteDrawer(this, doc, CMDocType.HTML_DOC_TYPE);
	}

	private void registerJSPCategory() {
		final CMDocument doc = HTMLCMDocumentFactory.getCMDocument(CMDocType.JSP11_DOC_TYPE);
		_paletteHelper.getOrCreateTaglibPaletteDrawer(this, doc, CMDocType.JSP11_DOC_TYPE);
	}

//	/**
//	 * Search Classpath entry list to find if the entry is jar library and the
//	 * library have the tld descriptor, if have ,build a palette category mapping
//	 * the tld descriptor.
//	 * 
//	 * @param project
//	 */
//	private void registerTldFromClasspath(final IProject project) {
//		if (project != null) {
//			ITaglibRecord[] tldrecs = TaglibIndex.getAvailableTaglibRecords(project.getFullPath());
//			for (int i=0;i<tldrecs.length;i++){				
//				_paletteHelper.configPaletteItemsByTLD(this, getCurProject(), tldrecs[i]);			
//			}
//		}			
//	}

	/**
	 * @param id (most likely the uri)
	 * @param label 
	 * @return TaglibPaletteDrawer
	 */
	public TaglibPaletteDrawer findOrCreateCategory(final String id, final String label) {
		TaglibPaletteDrawer category = getTaglibPalletteDrawer(id);
		if (category == null)
			category = createTaglibPaletteDrawer(id, label);
		return category;
	}

	/**
	 * @param uri
	 * @return TaglibPaletteDrawer
	 */
	public TaglibPaletteDrawer findCategoryByURI(final String uri) {
		TaglibPaletteDrawer category;
		for (final Iterator iter = getAllCategories().iterator(); iter.hasNext();) {
			category = (TaglibPaletteDrawer) iter.next();
			if (uri.equals(category.getURI())) {
				return category;
			}
		}
		return null;
	}

	public TaglibPaletteDrawer createTaglibPaletteDrawer(final String uri, final String label) {
		final TaglibPaletteDrawer r = new TaglibPaletteDrawer(uri, label);
		synchronized(_paletteCategories) {
			_paletteCategories.add(r);
		}
		return r;
	}

	public TaglibPaletteDrawer getTaglibPalletteDrawer(final String uri) {
		for (final Iterator iter = getAllCategories().iterator(); iter.hasNext();) {
			final TaglibPaletteDrawer cat = (TaglibPaletteDrawer) iter.next();
			if (uri.equalsIgnoreCase(cat.getId())) {
				return cat;
			}
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.sybase.stf.jmt.pagedesigner.editors.palette.IPaletteItemManager#addEntryChangeListener(com.sybase.stf.jmt.pagedesigner.editors.palette.IEntryChangeListener)
	 */
	public void addEntryChangeListener(final IEntryChangeListener listener) {
		_listeners.addIfAbsent(listener);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.sybase.stf.jmt.pagedesigner.editors.palette.IPaletteItemManager#removeEntryChangeListener(com.sybase.stf.jmt.pagedesigner.editors.palette.IEntryChangeListener)
	 */
	public void removeEntryChangeListener(final IEntryChangeListener listener) {		
		_listeners.remove(listener);
	}

	/**
	 * Notify model change event
	 * 
	 * @param oldDefinitions
	 * @param newDefinitions
	 */
	private void fireModelChanged(final List oldDefinitions, final List newDefinitions) {
		if (_listeners == null) {
			return;
		}
		for (final Iterator<IEntryChangeListener> it= _listeners.iterator();it.hasNext();){
			final IEntryChangeListener listener = it.next();
			listener.modelChanged(oldDefinitions, newDefinitions);
		}	
	}
	
	/**
	 * Informs all paletteItemManagers, except the notifying paletteManager, of updates to the customizations
	 * All palette viewer roots will be notifed of possible updates
	 * @param notifyingManager 
	 */
	public static void notifyPaletteItemManagersOfCustomizationsUpdate(final IPaletteItemManager notifyingManager){
		boolean hasLock = false;
		try {
			if (MANAGER_LOCK.tryLock(MANAGER_LOCK_TIMEOUT, TimeUnit.SECONDS)){
				hasLock = true;
				for (Iterator it=_managers.values().iterator();it.hasNext();){
					final PaletteItemManager mgr = (PaletteItemManager)it.next();
					if (mgr != null && notifyingManager != mgr)
						mgr.reset();
				}
			} 
			else {
				//if we get here then the lock has timed out
				PDPlugin.log(new Status(Status.ERROR, PDPlugin.getPluginId(), "Failed to get managers lock in notifyPaletteItemManagersOfCustomizationsUpdate")); //$NON-NLS-1$
			}
			
		} catch (InterruptedException e) {
			PDPlugin.log("Failed in notifyPaletteItemManagersOfCustomizationsUpdate", e); //$NON-NLS-1$
		} finally {
			if (hasLock)
				MANAGER_LOCK.unlock();
		}

	}

	public void registryChanged(final TagRegistryChangeEvent event) {
		final EventType eventType = event.getType();
		switch (eventType) {
			case ADDED_NAMESPACE:
				addNamespaces(event.getAffectedObjects());
				break;
			case REMOVED_NAMESPACE:
				removeNamespaces(event.getAffectedObjects());
				break;
			case CHANGED_NAMESPACE:
				changeNamespaces(event.getAffectedObjects());
				break;
			case REGISTRY_DISPOSED:
				break;
	
			default:
				break;
		}
		
		DesignerPaletteCustomizationsHelper.loadUserCustomizations(this);
		sortCategories();
		
		fireModelChanged(null, null);
	}


	private void addNamespaces(final List<? extends Namespace> affectedObjects) {
		synchronized (_paletteCategories) {
			for (final Namespace ns : affectedObjects) {
				if (DEBUG)
					System.out.println("Add NS: "+ns.getNSUri()+"["+System.currentTimeMillis()+"]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				_paletteHelper.configPaletteItemsByNamespace(this, ns);
			}
		}
	}
	
	private void removeNamespaces(final List<? extends Namespace> affectedObjects) {
		final List<Integer> drawersToRemove = new ArrayList<Integer>();
		synchronized (_paletteCategories) {
			for (final Namespace ns : affectedObjects) {
				for (int i=_paletteCategories.size() - 1; i >= 0; i--) {//gather in reverse order
					final PaletteDrawer drawer = _paletteCategories.get(i);
					if (drawer.getId().equals(ns.getNSUri())) {
						if (DEBUG)
							System.out.println("Remove NS: "+drawer.getId() +"["+System.currentTimeMillis()+"]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
						drawersToRemove.add(new Integer(i));	
					}
				}
			}	
			if (! drawersToRemove.isEmpty()) {
				Collections.sort(drawersToRemove, new Comparator<Integer>() {//reverse order sort

					public int compare(Integer o1, Integer o2) {
						if (o1.intValue() > o2.intValue())
							return -1;
						else if (o1.intValue() < o2.intValue())
							return 1;
							
						return 0;
					}
				});
				for (Integer index : drawersToRemove) {
					_paletteCategories.remove(index.intValue());				
				}
			}
		}
	}

	private void changeNamespaces(final List<? extends Namespace> affectedObjects) {
		//for now, remove then add
		removeNamespaces(affectedObjects);
		addNamespaces(affectedObjects);		
	}

	public TagRegistryIdentifier getTagRegistryIdentifier() {		
		return _tagRegId;
	}

	/**
	 * @return helper
	 */
	public PaletteHelper getPaletteHelper() {
		return _paletteHelper;
	}

}
