/*******************************************************************************
 * 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.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.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.util.Debug;
import org.eclipse.wst.sse.core.util.ResourceUtil;
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 String firstLanguageValue;
	private int firstContentTypePosition = -1;
	private String firstContentTypeValue;

	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)) {
				firstContentTypeValue = 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)) {
				firstLanguageValue = 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 = model.getStructuredDocument().getDocumentPartitioner();
		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 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 = ResourceUtil.getFileFor(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();
					}
				}
			}
		}

	}
}