/*******************************************************************************
 * Copyright (c) 2003, 2007 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.wst.common.componentcore.internal.impl;

import java.io.IOException;
import java.util.Iterator;
import java.util.Set;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.jem.util.RegistryReader;
import org.eclipse.wst.common.componentcore.ComponentCore;
import org.eclipse.wst.common.componentcore.UnresolveableURIException;
import org.eclipse.wst.common.componentcore.internal.ModulecorePlugin;
import org.eclipse.wst.common.componentcore.internal.StructureEdit;
import org.eclipse.wst.common.componentcore.resources.IVirtualComponent;
import org.eclipse.wst.common.componentcore.resources.IVirtualFile;
import org.eclipse.wst.common.componentcore.resources.IVirtualFolder;
import org.eclipse.wst.common.internal.emf.resource.FileNameResourceFactoryRegistry;
import org.eclipse.wst.common.internal.emf.resource.ResourceFactoryDescriptor;
import org.eclipse.wst.common.internal.emf.utilities.DefaultOverridableResourceFactoryRegistry;
import org.eclipse.wst.common.internal.emfworkbench.WorkbenchResourceHelper;

/**
 * <p>
 * The following class is experimental until fully documented.
 * </p>
 */
public class WTPResourceFactoryRegistry extends FileNameResourceFactoryRegistry {

	public static final WTPResourceFactoryRegistry INSTANCE = new WTPResourceFactoryRegistry();
	 
	private final static boolean LOG_WARNINGS = false;
	
	
	private WTPResourceFactoryRegistry() {
		new ResourceFactoryRegistryReader().readRegistry();
	}
	
	public Resource.Factory delegatedGetFactory(URI uri) {
		if (WTPResourceFactoryRegistry.INSTANCE == this)
			return super.delegatedGetFactory(uri);
		return WTPResourceFactoryRegistry.INSTANCE.getFactory(uri);	
	}   

	public synchronized Resource.Factory getFactory(URI uri, IContentDescription description) {
		Resource.Factory resourceFactory = null;
		if(uri != null && uri.lastSegment() != null) {
			ResourceFactoryDescriptor descriptor = null;
			if(null == description){
				descriptor = getDescriptor(uri);
			} else {
				descriptor = getDescriptor(uri, description);
			}
			
			if(descriptor != null) {
				resourceFactory = getFactory(descriptor);	
			}	
		}
		if(resourceFactory == null)
			resourceFactory = super.getFactory(uri);
		return resourceFactory; 
	}
	
	public synchronized Resource.Factory getFactory(URI uri) {
		return getFactory(uri, (IContentDescription)null);
	}	


	/**
	 * Register a file name representing the last segment of a URI with the corresponding
	 * Resource.Factory.
	 */
	public synchronized void registerLastFileSegment(String aSimpleFileName, Resource.Factory aFactory) { 
		
		if(LOG_WARNINGS) {
			/* the third entry in the array is this stack frame, we walk back from there. */
			StackTraceElement[] stackTrace = (new Exception()).getStackTrace();
			if(stackTrace.length > 4) {
				StringBuffer warningMessage = new StringBuffer("WTPResourceFactoryRegistry.registerLastFileSegment() was called explicitly from " + stackTrace[3]);
				warningMessage.append("\nThis happened around: \n");
				for (int i = 4; (i < stackTrace.length) && i < 8; i++) {
					warningMessage.append("\tnear ").append(stackTrace[i]).append('\n');
				}
				warningMessage.append(".\nClients should use the org.eclipse.wst.common.modulecore.resourceFactories extension point instead.");
				ModulecorePlugin.log(IStatus.INFO, 0, warningMessage.toString(), null);		
			}
		}
		
		super.registerLastFileSegment(aSimpleFileName, aFactory);
		
	}  
	private WTPResourceFactoryRegistryKey getKey(ResourceFactoryDescriptor descriptor) {
		WTPResourceFactoryRegistryKey key = new WTPResourceFactoryRegistryKey();
		key.shortName = descriptor.getShortSegment();
		key.type = descriptor.getContentType();
		key.isDefault = descriptor.isDefault();
		return key;
	}
	
	/**
	 * Declares a subclass to create Resource.Factory(ies) from an extension. 
	 */
	private class ConfigurationResourceFactoryDescriptor extends ResourceFactoryDescriptor  implements IResourceFactoryExtPtConstants {
		
		private String shortSegment;
		private IContentType contentType;
		private boolean isDefault = true;
		private final IConfigurationElement element; 
		
		public ConfigurationResourceFactoryDescriptor(IConfigurationElement ext) throws CoreException {
			Assert.isNotNull(ext);
			element = ext;
			init();
		} 
		
		private void init() throws CoreException {
			shortSegment = element.getAttribute(ATT_SHORT_SEGMENT);
			if(shortSegment == null || shortSegment.trim().length() == 0)
				throw new CoreException(
							ModulecorePlugin.createErrorStatus(0, 
										"The shortSegment attribute of " + TAG_RESOURCE_FACTORY + //$NON-NLS-1$ 
										" must specify a valid, non-null, non-empty value in " +   //$NON-NLS-1$
										element.getNamespaceIdentifier(), null));
			if ("false".equals(element.getAttribute(ATT_ISDEFAULT)))
					isDefault = false;
			
			IConfigurationElement[] bindings = element.getChildren(TAG_CONTENTTYPE);
			if (bindings.length > 0) {
				String contentTypeId = null;
				contentTypeId = bindings[0].getAttribute(ATT_CONTENTTYPEID);			
				if (contentTypeId != null)
					contentType = Platform.getContentTypeManager().getContentType(contentTypeId);
				}
		} 

		public boolean isEnabledFor(URI fileURI) {
			/* shortSegment must be non-null for the descriptor to be created, 
			 * a validation check in init() verifies this requirement */
			if(fileURI != null && fileURI.lastSegment() != null)
				return shortSegment.equals(fileURI.lastSegment());
			return false;
		} 
		
		public Resource.Factory createFactory() {
			
			final Resource.Factory[] factory = new Resource.Factory[1];
			
			SafeRunner.run(new ISafeRunnable() {
				
				public void run() throws Exception {
					factory[0] = (Resource.Factory) element.createExecutableExtension(ATT_CLASS);					
				}
				
				public void handleException(Throwable exception) {
					ModulecorePlugin.log(ModulecorePlugin.createErrorStatus(0, exception.getMessage(), exception));					
				}
			});
			
			return factory[0] != null ? factory[0] : DefaultOverridableResourceFactoryRegistry.GLOBAL_FACTORY;
			
		}

		public String getShortSegment() {
			return shortSegment;
		}

		public IContentType getContentType() {
			
			return contentType;
		}

		public boolean isDefault() {
			return isDefault;
		}  
		public int hashCode() {
			if (getContentType() != null)
				return getShortSegment().hashCode() & getContentType().hashCode();
			else return super.hashCode();
		}
		
		public boolean equals(Object o) {
			if(o instanceof ResourceFactoryDescriptor && getContentType() != null)
				return (getShortSegment().equals(((ResourceFactoryDescriptor)o).getShortSegment()) &&
						getContentType().equals(((ResourceFactoryDescriptor)o).getContentType()));
			else if (((ResourceFactoryDescriptor)o).getContentType() != null) return false;
				
			return super.equals(o);
		}
	}  
	 
	
	private class ResourceFactoryRegistryReader extends RegistryReader implements IResourceFactoryExtPtConstants { 
 		
		public ResourceFactoryRegistryReader() {
			super(Platform.getPluginRegistry(), ModulecorePlugin.PLUGIN_ID, EXTPT_RESOURCE_FACTORIES);
		}

		public boolean readElement(final IConfigurationElement element) {
			
			if(element != null && TAG_RESOURCE_FACTORY.equals(element.getName())) {
				final boolean[] success = new boolean[] { true }; 
				SafeRunner.run(new ISafeRunnable() {
					
					public void run() throws Exception {
						addDescriptor(new ConfigurationResourceFactoryDescriptor(element));
					} 

					public void handleException(Throwable exception) {
						ModulecorePlugin.log(ModulecorePlugin.createErrorStatus(0, exception.getMessage(), exception));
						success[0] = false;
					}
				});				
				return success[0];
			} else {
				return false;
			}	
		}
	}
	private class WTPResourceFactoryRegistryKey { 
 		
		public String shortName;
		public IContentType type;
		public boolean isDefault = true;
		public WTPResourceFactoryRegistryKey() {
			super();
		}
		
		
	}

	protected void addDescriptor(ResourceFactoryDescriptor descriptor) {
		getDescriptors().put(getKey(descriptor), descriptor);
	}

	protected synchronized ResourceFactoryDescriptor getDescriptor(URI uri, IContentDescription description) {
		Set keys = getDescriptors().keySet();
		ResourceFactoryDescriptor defaultDesc = null;
		for (Iterator iterator = keys.iterator(); iterator.hasNext();) {
			WTPResourceFactoryRegistryKey key = (WTPResourceFactoryRegistryKey) iterator.next();
			if (key.shortName.equals(uri.lastSegment())) {
				ResourceFactoryDescriptor desc = (ResourceFactoryDescriptor)getDescriptors().get(key);
				if (description == null) {
					if (key.type == null) 
						return desc;
					else if (desc.isDefault()) 
						return desc;
				}
				//Allow the contentType discrimination to take place
				if ((key.type != null) && 
						(description != null) && 
						(description.getContentType().equals(key.type))) {
					// If the current describer is "default" then specify
					if(desc.isDefault())
						return desc;
					else 	
						defaultDesc = desc;
				}
					
				if ((description != null) && (desc.isDefault()) && (defaultDesc == null))
					defaultDesc = desc;
			}
		}
		return defaultDesc;
	}
private URI newPlatformURI(URI aNewURI, IProject project) {
		
		if (project == null)
			return ModuleURIUtil.trimToDeployPathSegment(aNewURI);
		try {
			IVirtualComponent component = ComponentCore.createComponent(project);

			URI deployPathSegment = ModuleURIUtil.trimToDeployPathSegment(aNewURI);
			
			//IVirtualFile newFile = component.getFile(new Path(deployPathSegment.path()));			
			IVirtualFolder rootFolder = component.getRootFolder();
			IVirtualFile newFile = rootFolder.getFile(new Path(deployPathSegment.path()));
			
			return URI.createPlatformResourceURI(newFile.getWorkspaceRelativePath().toString());
			 
		} catch(Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	private IContentDescription getDescriptionFromURI(URI uri) {
		String contentTypeIdentifier = ModuleURIUtil.getContentTypeName(uri);
		if (contentTypeIdentifier != null)
			return Platform.getContentTypeManager().getContentType(contentTypeIdentifier).getDefaultDescription();
		else
			return null;
		
	}

	protected synchronized ResourceFactoryDescriptor getDescriptor(URI uri) {
		IFile file = WorkbenchResourceHelper.getPlatformFile(uri);
		IContentDescription description = null;
		if (file != null && file.exists()) {
			try {
				description = file.getContentDescription();
			} catch (CoreException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (description == null) {//Check for optional embedded uri segment, then normalize
			description = getDescriptionFromURI(uri);
			try {
				if (description != null) {
					IProject componentProject = null;
					try {
						componentProject = StructureEdit.getContainingProject(uri);
					} catch (UnresolveableURIException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					uri = PlatformURLModuleConnection.resolve(uri);
					uri = newPlatformURI(uri,componentProject);
				} 
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		ResourceFactoryDescriptor defaultDesc = getDescriptor(uri, description);
		// Ok no content type match - go to super
		if (defaultDesc != null){
			return defaultDesc;
		}
		else{
			return super.getDescriptor(uri);
		}
	}
}
