/*******************************************************************************
 * 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.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);
				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();
	}

	private 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;
	}

}
