/*******************************************************************************
 * Copyright (c) 2002, 2009 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
 *     Jens Lukowski/Innoopract - initial renaming/restructuring
 *     Jesper Steen Moeller - Added XML Catalogs 1.1 support
 *     
 *******************************************************************************/
package org.eclipse.wst.xml.core.internal.catalog;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.Platform;
import org.eclipse.wst.xml.core.internal.Logger;
import org.eclipse.wst.xml.core.internal.XMLCorePlugin;
import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalog;
import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogElement;
import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEntry;
import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogEvent;
import org.eclipse.wst.xml.core.internal.catalog.provisional.ICatalogListener;
import org.eclipse.wst.xml.core.internal.catalog.provisional.IDelegateCatalog;
import org.eclipse.wst.xml.core.internal.catalog.provisional.INextCatalog;
import org.eclipse.wst.xml.core.internal.catalog.provisional.IRewriteEntry;
import org.eclipse.wst.xml.core.internal.catalog.provisional.ISuffixEntry;
public class Catalog implements ICatalog
{

	class CatalogLS
	{
		public void load()
		{
		}

		public synchronized void save()
		{
			try
			{
				new CatalogWriter().write(Catalog.this, location);
			} catch (Exception e)
			{
				Logger.logException(e);
			}
		}
	}

	class DefaultCatalogLS extends CatalogLS
	{
		public void load()
		{
			NextCatalog userCatalogReference = new NextCatalog();
			userCatalogReference.setId(XMLCorePlugin.USER_CATALOG_ID);
			userCatalogReference.setCatalogLocation(USER_CATALOG_FILE);
			addCatalogElement(userCatalogReference);

			NextCatalog systemCatalogReference = new NextCatalog();
			systemCatalogReference.setId(XMLCorePlugin.SYSTEM_CATALOG_ID);
			systemCatalogReference.setCatalogLocation(SYSTEM_CATALOG_FILE);
			addCatalogElement(systemCatalogReference);

			/*
			 * Here we save the file in order to 'reflect' the catalog that
			 * we've created from plug-in extensions to disk. The 'default'
			 * catalog is only ever written to disk and never read from disk.
			 */
			save();
		}
	}

	private static Comparator LONGEST_REWRITE_FIRST = new Comparator() 
	{
		public int compare(Object entry1, Object entry2) 
		{
			String start1 = ((IRewriteEntry)entry1).getStartString();
			String start2 = ((IRewriteEntry)entry2).getStartString();
			
			// Bigger is earlier
			return start2.length() - start1.length();
		}
	};

	private static Comparator LONGEST_SUFFIX_FIRST = new Comparator() 
	{
		public int compare(Object entry1, Object entry2) 
		{
			String suffix1 = ((ISuffixEntry)entry1).getSuffix();
			String suffix2 = ((ISuffixEntry)entry2).getSuffix();
			
			// Bigger is earlier
			return suffix2.length() - suffix1.length();
		}
	};

	private static Comparator LONGEST_DELEGATE_PREFIX_FIRST = new Comparator() 
	{
		public int compare(Object entry1, Object entry2) 
		{
			String prefix1 = ((IDelegateCatalog)entry1).getStartString();
			String prefix2 = ((IDelegateCatalog)entry2).getStartString();
			
			// Bigger is earlier
			return prefix2.length() - prefix1.length();
		}
	};

	class InternalResolver
	{
		protected Map publicMap = new HashMap();

		protected Map systemMap = new HashMap();

		protected Map uriMap = new HashMap();

		// These are sorted by longest "key" first.
		protected List rewriteSystemList = new LinkedList();
		protected List rewriteUriList = new LinkedList();
		protected List suffixSystemList = new LinkedList();
		protected List suffixUriList = new LinkedList();
		protected List delegatePublicList = new LinkedList();
		protected List delegateSystemList = new LinkedList();
		protected List delegateUriList = new LinkedList();
		
		InternalResolver()
		{
			for (Iterator i = catalogElements.iterator(); i.hasNext();)
			{
				ICatalogElement catalogElement = (ICatalogElement) i.next();
				if (catalogElement.getType() == ICatalogElement.TYPE_ENTRY)
				{
					ICatalogEntry entry = (ICatalogEntry) catalogElement;
					Map map = getEntryMap(entry.getEntryType());
					map.put(entry.getKey(), entry);
				} 
				else if (catalogElement.getType() == ICatalogElement.TYPE_REWRITE) 
				{
					IRewriteEntry entry = (IRewriteEntry) catalogElement;
					if (entry.getEntryType() == IRewriteEntry.REWRITE_TYPE_SYSTEM) 
					{
						rewriteSystemList.add(entry);
					} 
					else 
					{
						rewriteUriList.add(entry);
					}
				} 
				else if (catalogElement.getType() == ICatalogElement.TYPE_SUFFIX) 
				{
					ISuffixEntry entry = (ISuffixEntry) catalogElement;
					if (entry.getEntryType() == ISuffixEntry.SUFFIX_TYPE_SYSTEM) 
					{
						suffixSystemList.add(entry);
					} 
					else 
					{
						suffixUriList.add(entry);
					}
				} 
				else if (catalogElement.getType() == ICatalogElement.TYPE_DELEGATE) 
				{
					IDelegateCatalog delegate = (IDelegateCatalog) catalogElement;
					if (delegate.getEntryType() == IDelegateCatalog.DELEGATE_TYPE_PUBLIC) 
					{
						delegatePublicList.add(delegate);
					}
					else if (delegate.getEntryType() == IDelegateCatalog.DELEGATE_TYPE_SYSTEM) 
					{
						delegateSystemList.add(delegate);
					}
					else 
					{
						delegateUriList.add(delegate);
					}
				}
			}
			
			Collections.sort(rewriteSystemList, LONGEST_REWRITE_FIRST);
			Collections.sort(rewriteUriList, LONGEST_REWRITE_FIRST);

			Collections.sort(suffixSystemList, LONGEST_SUFFIX_FIRST);
			Collections.sort(suffixUriList, LONGEST_SUFFIX_FIRST);
		
			Collections.sort(delegatePublicList, LONGEST_DELEGATE_PREFIX_FIRST);
			Collections.sort(delegateSystemList, LONGEST_DELEGATE_PREFIX_FIRST);
			Collections.sort(delegateUriList, LONGEST_DELEGATE_PREFIX_FIRST);
		}

		private Map getEntryMap(int entryType)
		{
			Map map = systemMap;
			switch (entryType)
			{
			case ICatalogEntry.ENTRY_TYPE_PUBLIC:
				map = publicMap;
				break;
			case ICatalogEntry.ENTRY_TYPE_URI:
				map = uriMap;
				break;
			default:
				break;
			}
			return map;
		}

		protected String getMappedURI(Map map, String key)
		{
			CatalogEntry entry = (CatalogEntry) map.get(key);
			if(entry == null) return null;
			String uri = entry.getURI();
			try
			{
                // TODO CS : do we really want to resolve these here?
                // I'm guessing we should return the 'platform:' form of the URI
                // to the caller.
                if (uri.startsWith("platform:")) //$NON-NLS-1$
                {  
				  URL entryURL = new URL(entry.getAbsolutePath(uri));                
				  uri = Platform.resolve(entryURL).toString();
                  
                  // we need to ensure URI's are of form "file:///D:/XXX" and NOT  
                  // "file:D:/XXX".  Otherwise the EMF URI class gets confused
                  // (see bug 103607) 
                  String FILE_SCHEME = "file:"; //$NON-NLS-1$
                  if (uri.startsWith(FILE_SCHEME) && !uri.startsWith(FILE_SCHEME + "/")) //$NON-NLS-1$
                  {
                    uri = FILE_SCHEME + "///" + uri.substring(FILE_SCHEME.length()); //$NON-NLS-1$
                  }  
                }  
                return uri; 
			} catch (IOException e)
			{
				return null;
			}
		}

		public String resolvePublic(String publicId, String systemId)
				throws MalformedURLException, IOException
		{
			String result = getMappedURI(publicMap, publicId);
			if (result == null)
			{
				result = getMappedURI(systemMap, systemId);
			}
			// our clients used to pass namespace in place of public id, so we need to check uri map for those
			if (result == null)
			{
				result = getMappedURI(uriMap, publicId);
			}
			if (result == null)
			{
				result = resolveDelegateCatalogs(delegatePublicList, publicId, systemId);
			}
			if (result == null)
			{
				result = resolveSubordinateCatalogs(
						ICatalogEntry.ENTRY_TYPE_PUBLIC, publicId, systemId);
			}
			return result;
		}

		public String resolveSystem(String systemId)
				throws MalformedURLException, IOException
		{
			String result = getMappedURI(systemMap, systemId);
			if (result == null)
			{
				result = resolveRewrite(rewriteSystemList, systemId);
			}
			if (result == null)
			{
				result = resolveSuffix(suffixSystemList, systemId);
			}
			if (result == null)
			{
				result = resolveDelegateCatalogs(delegateSystemList, systemId, systemId); // systemId is the key for "startString"
			}
			if (result == null)
			{
				result = resolveSubordinateCatalogs(
						ICatalogEntry.ENTRY_TYPE_SYSTEM, null, systemId);
			}
			return result;
		}

		private String resolveRewrite(List rewriteList, String searchString) 
		{
			for (Iterator it = rewriteList.iterator(); it.hasNext();) 
			{
				IRewriteEntry entry = (IRewriteEntry) it.next();
				String startString = entry.getStartString();
				if (searchString.startsWith(startString)) 
				{
					return entry.getRewritePrefix() + searchString.substring(startString.length());
				}
			}
			return null;
		}

		private String resolveSuffix(List suffixList, String searchString) {
			for (Iterator it = suffixList.iterator(); it.hasNext();) {
				ISuffixEntry entry = (ISuffixEntry) it.next();
				if (searchString.endsWith(entry.getSuffix())) {
					return entry.getURI();
				}
			}
			return null;
		}

		protected String resolveDelegateCatalogs(List delegateCatalogs, String key,
				String systemId) throws MalformedURLException, IOException
		{
			String result = null;
			for (Iterator iterator = delegateCatalogs.iterator(); iterator
					.hasNext();) {
				IDelegateCatalog delegate = (IDelegateCatalog) iterator.next();
				
				if (key.startsWith(delegate.getStartString())) {
	
					ICatalog catalog = delegate.getReferencedCatalog();
					if (catalog != null)
					{
						switch (delegate.getEntryType())
						{
						case IDelegateCatalog.DELEGATE_TYPE_PUBLIC:
							result = catalog.resolvePublic(key, systemId);
							break;
						case IDelegateCatalog.DELEGATE_TYPE_SYSTEM:
							result = catalog.resolveSystem(systemId);
							break;
						case IDelegateCatalog.DELEGATE_TYPE_URI:
							result = catalog.resolveURI(systemId);
							break;
						default:
							break;
						}
						if (result != null)
						{
							return result;
						}
					}
				}
			}
			return null;
		}
		
		public String resolveURI(String uri) throws MalformedURLException,
				IOException
		{
			String result = getMappedURI(uriMap, uri);
			if (result == null)
			{
				result = resolveRewrite(rewriteUriList, uri);
			}
			if (result == null)
			{
				result = resolveSuffix(suffixUriList, uri);
			}
			if (result == null)
			{
				result = resolveDelegateCatalogs(delegateUriList, uri, uri); // uri is treated as the systemId
			}
			if (result == null)
			{
				result = resolveSubordinateCatalogs(
						ICatalogEntry.ENTRY_TYPE_URI, null, uri);
			}
			return result;
		}
	}

	class SystemCatalogLS extends CatalogLS
	{
		public void load()
		{
			new CatalogContributorRegistryReader(Catalog.this).readRegistry();

			/*
			 * Here we save the file in order to 'reflect' the catalog that
			 * we've created from plugin extensions to disk. 
			 * The 'system' catalog is only ever written to disk and never read from disk.
			 */
			save();
		}
	}

	class UserCatalogLS extends CatalogLS
	{
		public void load()
		{
			InputStream inputStream = null;
			try
			{
				if (location != null && location.length() > 0) 
				{
					URL url = new URL(location);
					inputStream = url.openStream();
					boolean oldNotificationEnabled = isNotificationEnabled();
					setNotificationEnabled(false);
					clear();
					try
					{
						CatalogReader.read(Catalog.this, inputStream);
					} finally
					{
						setNotificationEnabled(oldNotificationEnabled);
					}
				}
				else
				{
					clear();
				}
				notifyChanged();
			} catch (Exception e)
			{
				// This is OK since the catalog may not exist before we create it
			} finally
			{
				if (inputStream != null)
				{
					try
					{
						inputStream.close();
					} catch (Exception e)
					{
					}
				}
			}
		}
	}

	public static final String DEFAULT_CATALOG_FILE = "default_catalog.xml"; //$NON-NLS-1$

	public static final String SYSTEM_CATALOG_FILE = "system_catalog.xml"; //$NON-NLS-1$

	public static final String USER_CATALOG_FILE = "user_catalog.xml"; //$NON-NLS-1$

	protected String base;

	protected List catalogElements = new ArrayList();

	protected CatalogLS catalogLS;

	protected String id;

	protected InternalResolver internalResolver;

	protected boolean isNotificationEnabled;

	protected List listenerList = new ArrayList();

	protected String location;

	protected CatalogSet resourceSet;

	public Catalog(CatalogSet catalogResourceSet, String id, String location)
	{
		this.resourceSet = catalogResourceSet;
		this.id = id;
		this.location = location;

		if (XMLCorePlugin.DEFAULT_CATALOG_ID.equals(id))
		{
			catalogLS = new DefaultCatalogLS();
		} else if (XMLCorePlugin.SYSTEM_CATALOG_ID.equals(id))
		{
			catalogLS = new SystemCatalogLS();
		} else
		{
			catalogLS = new UserCatalogLS();
		}
	}

	public void addCatalogElement(ICatalogElement element)
	{
		catalogElements.add(element);
		element.setOwnerCatalog(this);
		internalResolver = null;
		notifyAddElement(element);
	}

	public void addEntriesFromCatalog(ICatalog catalog)
	{
		try
		{
			setNotificationEnabled(false);
			if (catalog != null)
			{
				ICatalogElement[] entries = ((Catalog)catalog).getCatalogElements();
				for (int i = 0; i < entries.length; i++)
				{
					CatalogElement clone = (CatalogElement)((CatalogElement)entries[i]).clone();
					addCatalogElement(clone);
				}
			} else
			{
				Logger.log(Logger.ERROR, "argument was null in Catalog.addEntriesFromCatalog"); //$NON-NLS-1$
			}
		} finally
		{
			setNotificationEnabled(true);
		}
		internalResolver = null;
		notifyChanged();
	}

	public void addListener(ICatalogListener listener)
	{
		listenerList.add(listener);
	}

	public void clear()
	{
		catalogElements.clear();
		internalResolver = null;
		notifyChanged();
	}

	public ICatalogElement createCatalogElement(int type)
	{
		switch (type)
		{
		case ICatalogElement.TYPE_ENTRY:
			return new CatalogEntry(); // TODO: Should be kind of deprecated
		case ICatalogElement.TYPE_NEXT_CATALOG:
			return new NextCatalog();
		case ICatalogEntry.ENTRY_TYPE_PUBLIC:
		case ICatalogEntry.ENTRY_TYPE_SYSTEM:
		case ICatalogEntry.ENTRY_TYPE_URI:
			return new CatalogEntry(type);
		case ICatalogElement.TYPE_REWRITE:	
		case IRewriteEntry.REWRITE_TYPE_SYSTEM:
		case IRewriteEntry.REWRITE_TYPE_URI:
			return new RewriteEntry(type);
		case ICatalogElement.TYPE_SUFFIX:	
		case ISuffixEntry.SUFFIX_TYPE_SYSTEM:
		case ISuffixEntry.SUFFIX_TYPE_URI:
			return new SuffixEntry(type);
		case ICatalogElement.TYPE_DELEGATE:	
		case IDelegateCatalog.DELEGATE_TYPE_PUBLIC:
		case IDelegateCatalog.DELEGATE_TYPE_SYSTEM:
		case IDelegateCatalog.DELEGATE_TYPE_URI:
			return new DelegateCatalog(type);
		default:
			throw new IllegalArgumentException("Unknown element type " + type);//$NON-NLS-1 // Makes no sense at all!
		}
	}

	public String getBase()
	{
		return base;
	}

	private List getCatalogElements(int type)
	{
		List result = new ArrayList();
		ICatalogElement[] elements = (ICatalogElement[]) catalogElements
				.toArray(new ICatalogElement[catalogElements.size()]);
		for (int i = 0; i < elements.length; i++)
		{
			ICatalogElement element = elements[i];
			if (element.getType() == type)
			{
				result.add(element);
			}
		}
		return result;
	}

	public ICatalogEntry[] getCatalogEntries()
	{
		List result = getCatalogElements(ICatalogElement.TYPE_ENTRY);
		return (ICatalogEntry[]) result
				.toArray(new ICatalogEntry[result.size()]);
	}

	public IDelegateCatalog[] getDelegateCatalogs() 
	{
		List result = getCatalogElements(ICatalogElement.TYPE_DELEGATE);
		return (IDelegateCatalog[]) result
				.toArray(new IDelegateCatalog[result.size()]);
	}
	
	public IRewriteEntry[] getRewriteEntries() 
	{
		List result = getCatalogElements(ICatalogElement.TYPE_REWRITE);
		return (IRewriteEntry[]) result
				.toArray(new IRewriteEntry[result.size()]);
	}
	
	public ISuffixEntry[] getSuffixEntries() 
	{
		List result = getCatalogElements(ICatalogElement.TYPE_SUFFIX);
		return (ISuffixEntry[]) result
				.toArray(new ISuffixEntry[result.size()]);
	}
	
	protected CatalogSet getCatalogSet()
	{
		return resourceSet;
	}

	public String getId()
	{
		return id;
	}

	public String getLocation()
	{
		return location;
	}

	public INextCatalog[] getNextCatalogs()
	{
		List result = getCatalogElements(ICatalogElement.TYPE_NEXT_CATALOG);
		return (INextCatalog[]) result.toArray(new INextCatalog[result.size()]);
	}

	protected InternalResolver getOrCreateInternalResolver()
	{
		if (internalResolver == null)
		{
			internalResolver = new InternalResolver();
		}
		return internalResolver;
	}

	protected boolean isNotificationEnabled()
	{
		return isNotificationEnabled;
	}

	public void load() throws IOException
	{
		catalogLS.load();
	}

	protected void notifyAddElement(ICatalogElement entry)
	{
		if (isNotificationEnabled)
		{
			ICatalogEvent event = new CatalogEvent(this, entry,
					ICatalogEvent.ELEMENT_ADDED);
			notifyListeners(event);
		}
	}

	protected void notifyChanged()
	{
		ICatalogEvent event = new CatalogEvent(this, null,
				ICatalogEvent.CHANGED);
		notifyListeners(event);
	}

	protected void notifyListeners(ICatalogEvent event)
	{
		List list = new ArrayList();
		list.addAll(listenerList);
		for (Iterator i = list.iterator(); i.hasNext();)
		{
			ICatalogListener listener = (ICatalogListener) i.next();
			listener.catalogChanged(event);
		}
	}

	protected void notifyRemoveElement(ICatalogElement element)
	{
		if (isNotificationEnabled)
		{
			ICatalogEvent event = new CatalogEvent(this, element,
					ICatalogEvent.ELEMENT_REMOVED);
			notifyListeners(event);
		}
	}

	public void removeCatalogElement(ICatalogElement element)
	{
		catalogElements.remove(element);
		internalResolver = null;
		notifyRemoveElement(element);
		
	}

	public void removeListener(ICatalogListener listener)
	{
		listenerList.remove(listener);
	}

	public String resolvePublic(String publicId, String systemId)
			throws MalformedURLException, IOException
	{
		return getOrCreateInternalResolver().resolvePublic(publicId, systemId);
	}

	protected String resolveSubordinateCatalogs(int entryType, String publicId,
			String systemId) throws MalformedURLException, IOException
	{
		String result = null;
		INextCatalog[] nextCatalogs = getNextCatalogs();
		for (int i = 0; i < nextCatalogs.length; i++)
		{
			INextCatalog nextCatalog = nextCatalogs[i];
			ICatalog catalog = nextCatalog.getReferencedCatalog();
			if (catalog != null)
			{
				switch (entryType)
				{
				case ICatalogEntry.ENTRY_TYPE_PUBLIC:
					result = catalog.resolvePublic(publicId, systemId);
					break;
				case ICatalogEntry.ENTRY_TYPE_SYSTEM:
					result = catalog.resolveSystem(systemId);
					break;
				case ICatalogEntry.ENTRY_TYPE_URI:
					result = catalog.resolveURI(systemId);
					break;
				default:
					break;
				}
				if (result != null)
				{
					return result;
				}
			}
		}
		return null;
	}

	public String resolveSystem(String systemId) throws MalformedURLException,
			IOException
	{
		return getOrCreateInternalResolver().resolveSystem(systemId);
	}

	public String resolveURI(String uri) throws MalformedURLException,
			IOException
	{
		return getOrCreateInternalResolver().resolveURI(uri);
	}

	public void save() throws IOException
	{
		catalogLS.save();
	}

	public void setBase(String base)
	{
		this.base = base;
	}

	public void setId(String id)
	{
		this.id = id;
	}

	public void setLocation(String location)
	{
		this.location = location;
	}

	protected void setNotificationEnabled(boolean b)
	{
		isNotificationEnabled = b;
	}

	public ICatalogElement[] getCatalogElements()
	{
		return (ICatalogElement[]) catalogElements.toArray(new ICatalogElement[catalogElements.size()]);
	}
	

	

}
