/*******************************************************************************
 * Copyright (c) 2004, 2005 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 * 
 * Contributors:
 *     IBM Corporation - Initial API and implementation
 *     Jens Lukowski/Innoopract - initial renaming/restructuring
 *******************************************************************************/
package org.eclipse.wst.common.uriresolver.internal;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;

/**
 * The URI resolver extension registry contains information about
 * all of the extension URI resolvers.
 */
public class URIResolverExtensionRegistry
{
	protected HashMap map = new HashMap();
	
	protected List resolverList = new ArrayList();

	public static final int STAGE_PRENORMALIZATION = 1;

	public static final int STAGE_POSTNORMALIZATION = 2;

	public static final int STAGE_PHYSICAL = 3;

	public static final String PRIORITY_LOW = "low";

	public static final String PRIORITY_MEDIUM = "medium";

	public static final String PRIORITY_HIGH = "high";

	protected final static String NULL_PROJECT_NATURE_ID = "";

	protected static URIResolverExtensionRegistry instance;

	private URIResolverExtensionRegistry()
	{
	}

	/**
	 * Get the one and only instance of the registry.
	 * 
	 * @return The one and only instance of the registry.
	 */
	public synchronized static URIResolverExtensionRegistry getIntance()
	{
		if (instance == null)
		{
			instance = new URIResolverExtensionRegistry();
			new URIResolverExtensionRegistryReader(instance).readRegistry();
		}
		return instance;
	}

	/**
	 * Add an extension resolver to the registry.
	 * 
	 * @param className The name of the extension URI resolver class.
	 * @param pluginId The ID of the plugin that contains the extension URI resolver class.
	 * @param projectNatureIds A list of project natures IDs for which the resolver should run.
	 * @param resourceType The type of resoure for which an extension resource should run.
	 * @param stage The stage to run. Either prenormalization or postnormalization.
	 * @param priority The priority of the resolver. Valid values are high, medium, and low.
	 */
	public void put(String className, String pluginId, List projectNatureIds,
			String resourceType, int stage, String priority)
	{
		if (projectNatureIds == null)
			projectNatureIds = new ArrayList();
		if (projectNatureIds.isEmpty())
		{
			projectNatureIds.add(NULL_PROJECT_NATURE_ID);
		}
		URIResolverExtensionDescriptor info = new URIResolverExtensionDescriptor(
				className, pluginId, projectNatureIds, resourceType, stage, priority);

		resolverList.add(info);
		
		Iterator idsIter = projectNatureIds.iterator();
		while (idsIter.hasNext())
		{
			String key = (String) idsIter.next();

			HashMap priorityMap = (HashMap) map.get(key);
			if (priorityMap == null)
			{
				priorityMap = new HashMap();
				map.put(key, priorityMap);
				priorityMap.put(PRIORITY_HIGH, new ArrayList());
				priorityMap.put(PRIORITY_MEDIUM, new ArrayList());
				priorityMap.put(PRIORITY_LOW, new ArrayList());
			}
			List list = (List) priorityMap.get(priority);
			list.add(info);
		}
	}

	/**
	 * Return a list of URIResolverExtensionDescriptor objects that apply to this
	 * project. The list is in the priority order high, medium, low.
	 * 
	 * @param project The project for which you are requesting resolvers.
	 * @return A list of URIResolverExtensionDescriptor objects.
	 */
	public List getExtensionDescriptors(IProject project)
	{
	  if(project != null) {
		  List result = new ArrayList();
		  List lowPriorityList = new ArrayList();
		  List mediumPriorityList = new ArrayList();
		  List highPriorityList = new ArrayList();          
		  for (Iterator i = map.keySet().iterator(); i.hasNext();)
		  {
		    String key = (String) i.next();
		    try
		    {
		      if (key == NULL_PROJECT_NATURE_ID || project.hasNature(key))
		      {
		        highPriorityList.addAll((List) ((HashMap) map.get(key)).get(PRIORITY_HIGH));
		        mediumPriorityList.addAll((List) ((HashMap) map.get(key)).get(PRIORITY_MEDIUM));
		        lowPriorityList.addAll((List) ((HashMap) map.get(key)).get(PRIORITY_LOW));
		      }
		    } catch (CoreException e)
		    {
		    }
		  }
		  result.addAll(highPriorityList);
		  result.addAll(mediumPriorityList);
		  result.addAll(lowPriorityList);
		  return result;
	  } else {
		  return resolverList;
	  }
	}

	/**
	 * Return a list of URIResolver objects that match the stage.
	 * TODO: This seems like an odd method to house here. It may need to be moved
	 *       or removed if the stage attribute dissapears.
	 * 
	 * @param resolverInfoList A list of resolvers to prune.
	 * @param stage The stage requested.
	 * @return A list of URIResolver objects that match the stage.
	 */
	public List getMatchingURIResolvers(List resolverInfoList, int stage)
	{
		List result = new ArrayList();
		for (Iterator i = resolverInfoList.iterator(); i.hasNext();)
		{
			URIResolverExtensionDescriptor info = (URIResolverExtensionDescriptor) i
					.next();
			if (info.stage == stage)
			{
				Object resolver = info.getResolver();
				if (resolver != null)
				{
					result.add(resolver);
				}
			}
		}
		return result;
	}
}
