/*******************************************************************************
 * Copyright (c) 2004 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.jst.jsp.core.internal.document;

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

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.text.IDocumentExtension3;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jst.jsp.core.PageDirectiveAdapter;
import org.eclipse.jst.jsp.core.internal.text.rules.StructuredTextPartitionerForJSP;
import org.eclipse.jst.jsp.core.modelhandler.EmbeddedTypeStateData;
import org.eclipse.wst.sse.core.AdapterFactory;
import org.eclipse.wst.sse.core.INodeAdapter;
import org.eclipse.wst.sse.core.INodeNotifier;
import org.eclipse.wst.sse.core.IStructuredModel;
import org.eclipse.wst.sse.core.internal.modelhandler.EmbeddedTypeRegistry;
import org.eclipse.wst.sse.core.internal.modelhandler.EmbeddedTypeRegistryImpl;
import org.eclipse.wst.sse.core.modelhandler.EmbeddedTypeHandler;
import org.eclipse.wst.sse.core.text.IStructuredDocument;
import org.eclipse.wst.sse.core.util.Debug;
import org.eclipse.wst.sse.core.util.StringUtils;
import org.eclipse.wst.xml.core.document.XMLNode;

/**
 * This class has the responsibility to provide 
 * an embedded factory registry for JSP Aware INodeAdapter Factories
 * to use. 
 * 
 * Typically, the embedded type is to be considered a feature of 
 * the document, so JSP Aware AdpaterFactories should call
 * getAdapter(PageDirectiveAdapter.class) directoy on the document
 * (or owning document) node.
 */
public class PageDirectiveAdapterImpl implements PageDirectiveAdapter {

	protected static final String STR_CHARSET = "charset"; //$NON-NLS-1$
	private final static Object adapterType = PageDirectiveAdapter.class;
	private IStructuredModel model;
	protected final String[] JAVASCRIPT_LANGUAGE_KEYS = new String[]{"javascript", "javascript1.0", "javascript1.1_3", "javascript1.2", "javascript1.3", "javascript1.4", "javascript1.5", "javascript1.6", "jscript", "sashscript"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ //$NON-NLS-9$ //$NON-NLS-10$
	protected final String[] JAVA_LANGUAGE_KEYS = new String[]{"java"}; //$NON-NLS-1$

	/**
	 * Constructor for PageDirectiveAdapterImpl.
	 */
	public PageDirectiveAdapterImpl(INodeNotifier target) {
		super();
		notifierAtCreation = target;
		// we need to remember our instance of model, 
		// in case we need to "signal" a re-init needed.
		if (target instanceof XMLNode) {
			XMLNode node = (XMLNode) target;
			model = node.getModel();
		}

	}

	/**
	 * parses the full contentType value into its two parts
	 * the contentType, and the charset, if present. Note: this 
	 * method is a lightly modified version of a method in AbstractHeadParser.
	 * There, we're mostly interested in the charset part of contentTypeValue. 
	 * Here, we're mostly interested in the mimeType part.
	 */
	private String getMimeTypeFromContentTypeValue(String contentTypeValue) {
		if (contentTypeValue == null)
			return null;
		String cleanContentTypeValue = StringUtils.stripNonLetterDigits(contentTypeValue);
		StringTokenizer tokenizer = new StringTokenizer(cleanContentTypeValue, ";= \t\n\r\f"); //$NON-NLS-1$
		int tLen = tokenizer.countTokens();
		// if contains encoding should have three tokens, the mimetype, the word 'charset', and the encoding value
		String[] tokens = new String[tLen];
		int j = 0;
		while (tokenizer.hasMoreTokens()) {
			tokens[j] = tokenizer.nextToken();
			j++;
		}
		// 
		// Following is the common form for target expression		
		// <META http-equiv="Content-Type" content="text/html; charset=UTF-8">
		// But apparrently is also valid without the content type there, 
		// just the charset, as follows:
		// <META http-equiv="Content-Type" content="charset=UTF-8">
		// So we'll loop through tokens and key off of 'charset'

		int charsetPos = -1;
		for (int i = 0; i < tokens.length; i++) {
			if (tokens[i].equalsIgnoreCase(STR_CHARSET)) {
				charsetPos = i;
				break;
			}
		}
		//String charset = null;
		String contentType = null;
		if (charsetPos > -1) {
			// case where charset was present
			//			int charsetValuePos = charsetPos + 1;
			//			if (charsetValuePos < tokens.length) {
			//				charset = tokens[charsetValuePos];
			//			}
			int contentTypeValuePos = charsetPos - 1;
			if (contentTypeValuePos > -1) {
				contentType = tokens[contentTypeValuePos];
			}
		}
		else {
			// charset was not present, so if there's 
			// a value, we assume its the contentType value
			if (tokens.length > 0) {
				contentType = tokens[0];
			}
		}
		return contentType;
	}

	private EmbeddedTypeHandler embeddedTypeHandler;
	private List embeddedFactoryRegistry = new ArrayList();
	private String cachedLanguage;
	private String cachedContentType;
	private INodeNotifier notifierAtCreation;

	private int firstLanguagePosition = -1;
	private int firstContentTypePosition = -1;

	private boolean reinitializing;

	/*
	 * @see INodeAdapter#isAdapterForType(Object)
	 */
	public boolean isAdapterForType(Object type) {
		return (type == adapterType);
	}

	/*
	 * @see INodeAdapter#notifyChanged(INodeNotifier, int, Object, Object, Object, int)
	 */
	public void notifyChanged(INodeNotifier notifier, int eventType, Object changedFeature, Object oldValue, Object newValue, int pos) {
	}

	public void setEmbeddedType(EmbeddedTypeHandler handler) {
		// if really the same handler, no need for further processing
		if (embeddedTypeHandler == handler) {
			return;
		}
		// then one exists, and the new one is truely different, so we need to 
		// release and remove current factories
		if (embeddedTypeHandler != null) {
			Iterator list = embeddedFactoryRegistry.iterator();
			while (list.hasNext()) {
				AdapterFactory factory = (AdapterFactory) list.next();
				factory.release();
			}

			embeddedFactoryRegistry.clear();
		}

		embeddedTypeHandler = handler;
		// when the handler is set, "transfer" its factories to our own list.
		// note: our own list may also be added to else where, such as on
		// "editor side".
		if (embeddedTypeHandler != null) {
			Iterator iterator = embeddedTypeHandler.getAdapterFactories().iterator();
			while (iterator.hasNext()) {
				AdapterFactory factory = (AdapterFactory) iterator.next();
				embeddedFactoryRegistry.add(factory);
			}
		}
	}

	/**
	 * @see PageDirectiveAdapter#adapt(INodeNotifier, Object)
	 */
	public INodeAdapter adapt(INodeNotifier notifier, Object type) {
		INodeAdapter result = null;
		// if embeddedContentType hasn't been set, 
		// then we can not adapt it.
		if (embeddedTypeHandler != null) {
			if (embeddedFactoryRegistry != null) {
				Iterator iterator = embeddedFactoryRegistry.iterator();
				AdapterFactory factory = null;
				while (iterator.hasNext()) {
					factory = (AdapterFactory) iterator.next();
					if (factory.isFactoryForType(type)) {
						result = factory.adapt(notifier);
						break;
					}
				}
			}
		}
		return result;

	}

	/**
	 * @see PageDirectiveAdapter#getEmbeddedType()
	 */
	public EmbeddedTypeHandler getEmbeddedType() {
		if (embeddedTypeHandler == null) {
			embeddedTypeHandler = getDefaultEmbeddedType();
		}
		return embeddedTypeHandler;
	}

	public void addEmbeddedFactory(AdapterFactory factory) {
		// should we check if already exists in list?
		embeddedFactoryRegistry.add(factory);
	}

	//	/**
	//	 * Used by PageDirectiveWatchers to signal that some important attribute has changed, and 
	//	 * any cached values should be re-calcuated
	//	 */
	//	void changed() {
	//		// we won't actually check if change is needed, if the model state is already changing.
	//		if (!model.isReinitializationNeeded()) {
	//			// go through our list of page watcher adapters, and updates the attributes 
	//			// we're interested in, if and only if they are the earliest occurance in the resource
	//			String potentialContentType = null;
	//			String potentialLanguage = null;
	//			int contentTypePosition = -1;
	//			int languagePosition = -1;
	//			Iterator iterator = pageDirectiveWatchers.iterator();
	//			while (iterator.hasNext()) {
	//				PageDirectiveWatcher pdWatcher = (PageDirectiveWatcher) iterator.next();
	//				String contentType = pdWatcher.getContentType();
	//				String language = pdWatcher.getLanguage();
	//				int offset = pdWatcher.getOffset();
	//				if (potentialContentType == null || (hasValue(contentType) && (offset < contentTypePosition))) {
	//					potentialContentType = contentType;
	//					contentTypePosition = offset;
	//				}
	//			}
	//			// now we have the best candiates for cached values, let's see if they've really changed from 
	//			// what we had. If so, note we go through the setters so side effects can take place there.
	//			potentialContentType = getMimeTypeFromContentTypeValue(potentialContentType);
	//			if (potentialContentType == null || potentialContentType.length() == 0) {
	//				//potentialContentType = getDefaultContentType();
	//			} else {
	//				setCachedContentType(potentialContentType);
	//			}
	//
	//			if (potentialLanguage != null && hasValue(potentialLanguage)) {
	//				setCachedLanguage(potentialLanguage);
	//			}
	//		}
	//	}
	void changedContentType(int elementOffset, String newValue) {
		// only need to process if this new value is 
		// earlier in the file than our current value
		if (firstContentTypePosition == -1 || elementOffset <= firstContentTypePosition) {
			// dw_TODO: update embedded partitioner in JSP document partitioner
			// nsd_TODO: update embedded partitioner in JSP document partitioner

			// no need to change current value, if we're told some 
			// earlier value is null or blank (sounds like an error, anyway)
			if (hasValue(newValue)) {
				firstContentTypePosition = elementOffset;
				String potentialContentType = getMimeTypeFromContentTypeValue(newValue);
				// only do the set processing if different
				// from what it already is
				//	if (!potentialContentType.equalsIgnoreCase(cachedLanguage)) {
				setCachedContentType(potentialContentType);
				//	}
			}
		}
	}

	/**
	 * Used by PageDirectiveWatchers to signal that some important attribute has changed, and 
	 * any cached values should be re-calcuated
	 */
	void changedLanguage(int elementOffset, String newValue) {
		// only need to process if this new value is 
		// earlier in the file than our current value
		// has to be less than or equal to, in case our previous earliest one, 
		// is itself changing!
		if (firstLanguagePosition == -1 || elementOffset <= firstLanguagePosition) {

			// no need to change current value, if we're told some 
			// earlier value is null or blank (sounds like an error, anyway)
			if (hasValue(newValue)) {
				firstLanguagePosition = elementOffset;
				// only do the set processing if different
				// from what it already is
				if (!newValue.equalsIgnoreCase(cachedLanguage)) {
					setCachedLanguage(newValue);
				}
			}

			// dw_TODO: set language in document partitioner
			// nsd_TODO: set language in document partitioner
		}
	}

	/**
	 * Used by PageDirectiveWatchers to signal that some important attribute has changed, and 
	 * any cached values should be re-calcuated
	 */
	void changedPageEncoding(int elementOffset, String newValue) {

		// we don't currently track active value, since
		// just need during read and write (where its 
		// calculated. We will need in future, to 
		// acurately clone a model and to display 
		// "current encoding" to user in status bar.
	}

	/**
	 * Method hasValue.
	 * @param contentType
	 * @return boolean
	 */
	private boolean hasValue(String value) {
		if (value != null && value.length() > 0)
			return true;
		else
			return false;
	}

	/**
	 * Returns the cachedContentType.
	 * @return String
	 */
	public String getContentType() {
		if (cachedContentType == null) {
			cachedContentType = getDefaultContentType();
		}
		return cachedContentType;
	}

	/**
	 * Method getDefaultContentType.
	 * @return String
	 */
	private String getDefaultContentType() {
		return "text/html"; //$NON-NLS-1$
	}

	/**
	 * Returns the cachedLanguage.
	 * @return String
	 */
	public String getLanguage() {
		if (cachedLanguage == null)
			cachedLanguage = getDefaultLanguage();
		return cachedLanguage;
	}

	/**
	 * Method getDefaultLanguage.
	 * @return String
	 */
	private String getDefaultLanguage() {
		return "java"; //$NON-NLS-1$
	}

	/**
	 * Sets the cachedContentType.
	 * @param cachedContentType The cachedContentType to set
	 */
	public void setCachedContentType(String newContentType) {
		// if the passed in value is the same as existing, there's nothing to do.
		// if its different, then we need to change the contentHandler as well
		// and, more to the point, signal a re-initializtation is needed.
		// Note: if the value we're getting set to does not have a handler in the registry, 
		// we'll actually not set it to null or anything, we'll just continue on with the one
		// we have. This is pretty important to avoid re-initializing on every key stroke if someone 
		// is typing in a new content type, but haven't yet finished the whole "word".
		// However, if an contentType is not recognized, the registry returns the one 
		// for XML.
		//		if (this.cachedContentType != null && this.cachedContentType.equalsIgnoreCase(newContentType)) { // then do nothing
		//		} else {
		this.cachedContentType = newContentType;
		// see if we can update embedded handler
		//		if (this.cachedContentType == null || this.cachedContentType.length() == 0) { // do nothing, don't can't get a new handler, so we'll keep what we have
		//		} else {

		// getHandler should always return something (never null), based 
		// on the rules in the factory. 
		EmbeddedTypeHandler handler = getHandlerFor(this.cachedContentType);
		// we do this check for re-init here, instead of in setEmbeddedType, 
		// since setEmbeddedType is called during the normal initializtion 
		// process, when re-init is not needed (since there is no content)
		if (embeddedTypeHandler != null && handler != null && embeddedTypeHandler != handler) {
			// changing this embedded handler here may 
			// be in the middle of anotify loop, not sure
			// if that'll cause problems.
			setEmbeddedType(handler);
			modelReinitNeeded(embeddedTypeHandler, handler);
		}
		//		}

		//		}

	}

	/**
	 * This method is used to re-init based on embeddedTypeHandler
	 * changing. It is given priority over the language change, since
	 * there its more important to have old and new handlers's in the 
	 * stateData field.
	 */
	private void modelReinitNeeded(EmbeddedTypeHandler oldHandler, EmbeddedTypeHandler newHandler) {
		if (model.isReinitializationNeeded()) {
			System.out.println("already being initialized"); //$NON-NLS-1$
		}

		try {
			model.aboutToChangeModel();
			model.setReinitializeStateData(new EmbeddedTypeStateData(oldHandler, newHandler));
			model.setReinitializeNeeded(true);
		}
		finally {
			model.changedModel();
		}
	}

	/**
	 * Method modelReinitNeeded.
	 */
	private void modelReinitNeeded(String oldlanguage, String newLanguage) {
		// bit of a short cut for now .... we dont' need language at the moment, 
		// but should set the state data
		if (model.isReinitializationNeeded()) {
			if (Debug.displayWarnings) {
				System.out.println("already being initialized"); //$NON-NLS-1$
			}
		}
		else {
			try {
				// if already being re-initialized, we don't want to 
				// reset the data in the stateData field.
				model.aboutToChangeModel();
				model.setReinitializeStateData(newLanguage);
				model.setReinitializeNeeded(true);
			}
			finally {
				model.changedModel();
			}
		}
	}

	public void setCachedLanguage(String newLanguage) {
		if (cachedLanguage != null && languageStateChanged(cachedLanguage, newLanguage)) { // a complete re-init overkill in current system, since really just need for 
			// the line style providers, 
			// BUT, a change in language could effect other things, 
			// and we don't expect to happen often so a little overkill isn't too bad.
			// The deep problem is that there is no way to get at the "edit side" adpapters
			// specifically here in model class.
			// we have to do the model changed sequence to get the 
			// screen to update.
			// do not signal again, if signaled once (the reinit state data will be wrong.
			// (this needs to be improved in future)
			if (!model.isReinitializationNeeded()) {
				modelReinitNeeded(cachedLanguage, newLanguage);
			}
		}
		setLanguage(newLanguage);
	}

	/**
	 * This is public access method, used especially
	 * from loader, for JSP Fragment support. 
	 */
	public void setLanguage(String newLanguage) {
		this.cachedLanguage = newLanguage;
		IDocumentPartitioner partitioner = ((IDocumentExtension3) model.getStructuredDocument()).getDocumentPartitioner(IStructuredDocument.DEFAULT_STRUCTURED_PARTITIONING);
		if (partitioner instanceof StructuredTextPartitionerForJSP) {
			((StructuredTextPartitionerForJSP) partitioner).setLanguage(newLanguage);
		}
	}

	/**
	 * Method languageStateChange.
	 * @param cachedLanguage
	 * @param newLanguage
	 * @return boolean
	 */
	private boolean languageStateChanged(String cachedLanguage, String newLanguage) {
		boolean result = false; // languages are equal, then no change in state
		if (!cachedLanguage.equalsIgnoreCase(newLanguage)) {
			boolean oldLanguageKnown = languageKnown(cachedLanguage);
			boolean newLanguageKnown = languageKnown(newLanguage);
			result = newLanguageKnown || (!newLanguageKnown && oldLanguageKnown);
		}
		return result;
	}

	/**
	 * Method languageKnown.
	 * @param cachedLanguage
	 * @return boolean
	 */
	private boolean languageKnown(String language) {
		return (StringUtils.contains(JAVA_LANGUAGE_KEYS, language, false) || StringUtils.contains(JAVASCRIPT_LANGUAGE_KEYS, language, false));
	}

	private IFile getFile(IStructuredModel model) {
		String location = model.getBaseLocation();
		IPath path = new Path(location);
		if (!path.toFile().exists() && path.segmentCount() > 1) {
			return ResourcesPlugin.getWorkspace().getRoot().getFile(path);
		}
		return null;
	}

	private EmbeddedTypeHandler getHandlerFor(String contentType) {
		EmbeddedTypeRegistry reg = getEmbeddedContentTypeRegistry();
		EmbeddedTypeHandler handler = null;
		if (reg != null)
			handler = reg.getTypeFor(contentType);
		return handler;
	}

	/**
	 * Gets the embeddedContentTypeRegistry.
	 * @return Returns a EmbeddedContentTypeRegistry
	 */
	private EmbeddedTypeRegistry getEmbeddedContentTypeRegistry() {
		return EmbeddedTypeRegistryImpl.getInstance();
	}

	/**
	 * For JSP files, text/html is the default 
	 * content type. This may want this different 
	 * for types like jsv (jsp for voice xml)
	 * For now, hard code to new instance.
	 * In future, should get instance from registry.
	 * 
	 * Specification cites HTML as the default contentType.
	 */
	protected EmbeddedTypeHandler getDefaultEmbeddedType() {
		return getHandlerFor(getDefaultContentType());
	}

	public void contentSettingsChanged(IResource resource) {
		// Note: we currently get notified multiple times, 
		// I assume since there's mulitple fields in the properties.
		// For now, I'll assume that once we get notified, all the 
		// fields are accurate, so if we're reinitializing, don't 
		// check any further. To NOT do this causes concurrent modification
		// exceptions. To do it, may cause us to miss when user changes
		// two fields at once. Will need to test. 
		if (reinitializing)
			return;
		if (resource == null)
			return;
		IFile file = getFile(model);
		if (file == null)
			return;
		//        String filename = null;
		//        if (resource.FILE == resource.getType()) {
		//        	filename = resource.getLocation().toString();
		//        }
		IProject project = file.getProject();
		if (project == null)
			return;
		if (!project.equals(resource.getProject()))
			return;
		// Note: these change notifications appear to be coming 
		// in based on any change in project. I'm not sure how
		// to tell if they are for my particular file, or 
		// if there's some other error I'm making in listeners.
		// the setters below should be smart enough 
		// to know if a meaningful change occurred, or 
		// not. Note: we seem to get called a lot (for resources other than our own?)
		// with lots of 'null' values. The logic below may prevent the correct unsetting
		// of a property (such as changing from a language setting back to 'none'). 
		// We may need a 'none' id, or something, to help detect that case, since we can't 
		// always assume the 'null' is accurate.
	}

	public INodeNotifier getTarget() {
		return notifierAtCreation;
	}

	public void release(Object type) {
		if (embeddedTypeHandler != null) {
			if (embeddedFactoryRegistry != null) {
				Iterator iterator = embeddedFactoryRegistry.iterator();
				AdapterFactory factory = null;
				while (iterator.hasNext()) {
					factory = (AdapterFactory) iterator.next();
					if (factory.isFactoryForType(type)) {
						factory.release();
					}
				}
			}
		}

	}
}