/*******************************************************************************
 * Copyright (c) 2006, 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
 *     
 *******************************************************************************/
package org.eclipse.wst.sse.ui.internal.spelling;

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

import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.reconciler.DirtyRegion;
import org.eclipse.jface.text.reconciler.IReconcileStep;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.IAnnotationModelExtension;
import org.eclipse.jface.text.source.IAnnotationModelExtension2;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector;
import org.eclipse.ui.texteditor.spelling.SpellingAnnotation;
import org.eclipse.ui.texteditor.spelling.SpellingContext;
import org.eclipse.ui.texteditor.spelling.SpellingProblem;
import org.eclipse.ui.texteditor.spelling.SpellingService;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.parser.ForeignRegion;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionCollection;
import org.eclipse.wst.sse.core.utils.StringUtils;
import org.eclipse.wst.sse.ui.internal.ExtendedConfigurationBuilder;
import org.eclipse.wst.sse.ui.internal.Logger;
import org.eclipse.wst.sse.ui.internal.reconcile.ReconcileAnnotationKey;
import org.eclipse.wst.sse.ui.internal.reconcile.StructuredReconcileStep;
import org.eclipse.wst.sse.ui.internal.reconcile.StructuredTextReconcilingStrategy;
import org.eclipse.wst.sse.ui.internal.reconcile.TemporaryAnnotation;

/**
 * A reconciling strategy that queries the SpellingService using its default
 * engine. Results are show as temporary annotations.
 * 
 * @since 1.1
 */
public class SpellcheckStrategy extends StructuredTextReconcilingStrategy {

	class SpellCheckPreferenceListener implements IPropertyChangeListener {
		private boolean isInterestingProperty(Object property) {
			return SpellingService.PREFERENCE_SPELLING_ENABLED.equals(property) || SpellingService.PREFERENCE_SPELLING_ENGINE.equals(property);
		}

		public void propertyChange(PropertyChangeEvent event) {
			if (isInterestingProperty(event.getProperty())) {
				if (event.getOldValue() == null || event.getNewValue() == null || !event.getNewValue().equals(event.getOldValue())) {
					reconcile();
				}
			}
		}
	}

	private class SpellingProblemCollector implements ISpellingProblemCollector {
		List annotations = new ArrayList();

		public void accept(SpellingProblem problem) {
			if (isInterestingProblem(problem)) {
				TemporaryAnnotation annotation = new TemporaryAnnotation(new Position(problem.getOffset(), problem.getLength()), SpellingAnnotation.TYPE, problem.getMessage(), fReconcileAnnotationKey);

				SpellingQuickAssistProcessor quickAssistProcessor = new SpellingQuickAssistProcessor();
				quickAssistProcessor.setSpellingProblem(problem);
				annotation.setAdditionalFixInfo(quickAssistProcessor);
				annotations.add(annotation);
				if (_DEBUG_SPELLING_PROBLEMS) {
					Logger.log(Logger.INFO, problem.getMessage());
				}
			}
		}

		public void beginCollecting() {
		}

		void clear() {
			annotations.clear();
		}

		public void endCollecting() {
		}

		Annotation[] getAnnotations() {
			return (Annotation[]) annotations.toArray(new Annotation[annotations.size()]);
		}
	}

	private static final boolean _DEBUG_SPELLING = Boolean.valueOf(Platform.getDebugOption("org.eclipse.wst.sse.ui/debug/reconcilerSpelling")).booleanValue(); //$NON-NLS-1$
	private static final boolean _DEBUG_SPELLING_PROBLEMS = Boolean.valueOf(Platform.getDebugOption("org.eclipse.wst.sse.ui/debug/reconcilerSpelling/showProblems")).booleanValue(); //$NON-NLS-1$

	private static final String EXTENDED_BUILDER_TYPE_CONTEXTS = "spellingregions"; //$NON-NLS-1$
	private static final String KEY_CONTENT_TYPE = "org.eclipse.wst.sse.ui.temp.spelling"; //$NON-NLS-1$

	private String fContentTypeId = null;

	private SpellingProblemCollector fProblemCollector = new SpellingProblemCollector();

	/*
	 * Keying our Temporary Annotations based on the partition doesn't help
	 * this strategy to only remove its own TemporaryAnnotations since it's
	 * possibly run on all partitions. Instead, set the key to use an
	 * arbitrary partition type that we can check for using our own
	 * implementation of getAnnotationsToRemove(DirtyRegion).
	 */
	ReconcileAnnotationKey fReconcileAnnotationKey;

	private IPropertyChangeListener fSpellCheckPreferenceListener;

	private SpellingContext fSpellingContext;

	private String[] fSupportedTextRegionContexts;
	private IReconcileStep fSpellingStep = new StructuredReconcileStep() {
	};

	public SpellcheckStrategy(ISourceViewer viewer, String contentTypeId) {
		super(viewer);
		fContentTypeId = contentTypeId;

		fSpellingContext = new SpellingContext();
		IContentType contentType = Platform.getContentTypeManager().getContentType(fContentTypeId);
		fSpellingContext.setContentType(contentType);
		fReconcileAnnotationKey = new ReconcileAnnotationKey(fSpellingStep, KEY_CONTENT_TYPE, ReconcileAnnotationKey.PARTIAL);

		/**
		 * Inherit spelling region rules
		 */
		List contexts = new ArrayList();
		IContentType testType = contentType;
		while (testType != null) {
			String[] textRegionContexts = ExtendedConfigurationBuilder.getInstance().getDefinitions(EXTENDED_BUILDER_TYPE_CONTEXTS, testType.getId());
			for (int j = 0; j < textRegionContexts.length; j++) {
				contexts.addAll(Arrays.asList(StringUtils.unpack(textRegionContexts[j])));
			}
			testType = testType.getBaseType();
		}
		fSupportedTextRegionContexts = (String[]) contexts.toArray(new String[contexts.size()]);

		fSpellCheckPreferenceListener = new SpellCheckPreferenceListener();
	}

	protected boolean containsStep(IReconcileStep step) {
		return fSpellingStep.equals(step);
	}

	public void createReconcileSteps() {

	}

	private TemporaryAnnotation[] getSpellingAnnotationsToRemove(IRegion region) {
		List toRemove = new ArrayList();
		IAnnotationModel annotationModel = getAnnotationModel();
		// can be null when closing the editor
		if (annotationModel != null) {
			Iterator i = null;
			boolean annotationOverlaps = false;
			if (annotationModel instanceof IAnnotationModelExtension2) {
				i = ((IAnnotationModelExtension2) annotationModel).getAnnotationIterator(region.getOffset(), region.getLength(), true, true);
				annotationOverlaps = true;
			}
			else {
				i = annotationModel.getAnnotationIterator();
			}

			while (i.hasNext()) {
				Object obj = i.next();
				if (!(obj instanceof TemporaryAnnotation))
					continue;

				TemporaryAnnotation annotation = (TemporaryAnnotation) obj;
				ReconcileAnnotationKey key = (ReconcileAnnotationKey) annotation.getKey();

				// then if this strategy knows how to add/remove this
				// partition type
				if (key != null && key.equals(fReconcileAnnotationKey)) {
					if (key.getScope() == ReconcileAnnotationKey.PARTIAL && (annotationOverlaps || annotation.getPosition().overlapsWith(region.getOffset(), region.getLength()))) {
						toRemove.add(annotation);
					}
					else if (key.getScope() == ReconcileAnnotationKey.TOTAL) {
						toRemove.add(annotation);
					}
				}
			}
		}

		return (TemporaryAnnotation[]) toRemove.toArray(new TemporaryAnnotation[toRemove.size()]);
	}

	/**
	 * Judge whether a spelling problem is "interesting". Accept any regions
	 * that are explicitly allowed, and since valid prose areas are rarely in
	 * a complicated document region, accept any document region with more
	 * than one text region and reject any document regions containing foreign
	 * text regions.
	 * 
	 * @param problem
	 *            a SpellingProblem
	 * @return whether the collector should accept the given SpellingProblem
	 */
	protected boolean isInterestingProblem(SpellingProblem problem) {
		IDocument document = getDocument();
		if (document instanceof IStructuredDocument) {
			/*
			 * If the error is in a read-only section, ignore it. The user
			 * won't be able to correct it.
			 */
			if (((IStructuredDocument) document).containsReadOnly(problem.getOffset(), problem.getLength()))
				return false;

			IStructuredDocumentRegion documentRegion = ((IStructuredDocument) document).getRegionAtCharacterOffset(problem.getOffset());
			if (documentRegion != null) {
				ITextRegion textRegion = documentRegion.getRegionAtCharacterOffset(problem.getOffset());
				//if the region is not null, and is a supported context and is not a collection of regions,
				//	and it should be spell-checked, then spell check it.
				if (textRegion != null && isSupportedContext(textRegion.getType()) && !(textRegion instanceof ITextRegionCollection) && shouldSpellcheck(problem.getOffset())) {
					return true;
				}
				if (documentRegion.getFirstRegion() instanceof ForeignRegion)
					return false;
//				[192572] Simple regions were being spellchecked just for the sake of them being simple
//				if (documentRegion.getRegions().size() == 1)
//					return true;
				return false;
			}
		}
		return true;
	}


	private boolean isSupportedContext(String type) {
		boolean isSupported = false;
		if (fSupportedTextRegionContexts.length > 0) {
			for (int i = 0; i < fSupportedTextRegionContexts.length; i++) {
				if (type.equals(fSupportedTextRegionContexts[i])) {
					isSupported = true;
					break;
				}
			}
		}
		else {
			isSupported = true;
		}
		return isSupported;
	}

	public void reconcile() {
		IDocument document = getDocument();
		if (document != null) {
			IAnnotationModel annotationModel = getAnnotationModel();
			if (annotationModel != null) {
				IRegion documentRegion = new Region(0, document.getLength());
				spellCheck(documentRegion, documentRegion, annotationModel);
			}
		}
	}

	/**
	 * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.reconciler.DirtyRegion,
	 *      org.eclipse.jface.text.IRegion)
	 */
	public void reconcile(DirtyRegion dirtyRegion, IRegion subRegion) {
		if (isCanceled())
			return;

		IAnnotationModel annotationModel = getAnnotationModel();

		IDocument document = getDocument();
		if (document != null) {
			long time0 = 0;
			if (_DEBUG_SPELLING) {
				time0 = System.currentTimeMillis();
			}
			/**
			 * Apparently the default spelling engine has noticeable overhead
			 * when called multiple times in rapid succession. It's faster to
			 * check the entire dirty region at once since we know that we're
			 * not differentiating by partition.
			 * 
			 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=192530
			 */
			if (_DEBUG_SPELLING) {
				Logger.log(Logger.INFO, "Spell Checking [" + dirtyRegion.getOffset() + ":" + dirtyRegion.getLength() + "] : " + (System.currentTimeMillis() - time0));
			}
			if (annotationModel != null) {
				spellCheck(dirtyRegion, dirtyRegion, annotationModel);
			}
		}
	}

	private void spellCheck(IRegion dirtyRegion, IRegion regionToBeChecked, IAnnotationModel annotationModel) {
		if (annotationModel == null)
			return;

		TemporaryAnnotation[] annotationsToRemove;
		Annotation[] annotationsToAdd;
		annotationsToRemove = getSpellingAnnotationsToRemove(regionToBeChecked);

		if (_DEBUG_SPELLING_PROBLEMS) {
			Logger.log(Logger.INFO, "Spell checking [" + regionToBeChecked.getOffset() + "-" + (regionToBeChecked.getOffset() + regionToBeChecked.getLength()) + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}
		if (getDocument() != null) {
			EditorsUI.getSpellingService().check(getDocument(), new IRegion[]{regionToBeChecked}, fSpellingContext, fProblemCollector, null);
		}
		annotationsToAdd = fProblemCollector.getAnnotations();
		fProblemCollector.clear();


		if (annotationModel instanceof IAnnotationModelExtension) {
			IAnnotationModelExtension modelExtension = (IAnnotationModelExtension) annotationModel;
			Map annotationsToAddMap = new HashMap();
			for (int i = 0; i < annotationsToAdd.length; i++) {
				annotationsToAddMap.put(annotationsToAdd[i], ((TemporaryAnnotation) annotationsToAdd[i]).getPosition());
			}
			modelExtension.replaceAnnotations(annotationsToRemove, annotationsToAddMap);
		}

		else {
			for (int j = 0; j < annotationsToAdd.length; j++) {
				annotationModel.addAnnotation(annotationsToAdd[j], ((TemporaryAnnotation) annotationsToAdd[j]).getPosition());
			}
			for (int j = 0; j < annotationsToRemove.length; j++) {
				annotationModel.removeAnnotation(annotationsToRemove[j]);
			}
		}
	}

	/**
	 * @param partition
	 * @see org.eclipse.jface.text.reconciler.IReconcilingStrategy#reconcile(org.eclipse.jface.text.IRegion)
	 */

	public void reconcile(IRegion partition) {
		IDocument document = getDocument();
		if (document != null) {
			IAnnotationModel annotationModel = getAnnotationModel();
			if (annotationModel != null) {
				spellCheck(partition, partition, annotationModel);
			}
		}
	}

	public void setDocument(IDocument document) {
		if (getDocument() != null) {
			EditorsUI.getPreferenceStore().removePropertyChangeListener(fSpellCheckPreferenceListener);
		}

		super.setDocument(document);

		if (getDocument() != null) {
			EditorsUI.getPreferenceStore().addPropertyChangeListener(fSpellCheckPreferenceListener);
		}
	}
	
	/**
	 * Decides if the given offset should be spell-checked using an <code>IAdapterFactory</code>
	 * 
	 * @param offset Decide if this offset should be spell-checked
	 * @return <code>true</code> if the given <code>offset</code> should be spell-checked,
	 * <code>false</code> otherwise.
	 */
	private boolean shouldSpellcheck(int offset) {
		boolean decision = true;
		
		IStructuredModel model = null;
		try {
			model = StructuredModelManager.getModelManager().getExistingModelForRead(getDocument());
			
			/* use an an adapter factory to get a spell-check decision maker,
			 * and ask it if the  offset should be spell-checked.  It is done
			 * this way so content type specific decisions can be made without this
			 * plugin being aware of any content type specifics.
			 */
			ISpellcheckDelegate delegate = (ISpellcheckDelegate)Platform.getAdapterManager().getAdapter(model, ISpellcheckDelegate.class);
			if(delegate != null) {
				decision = delegate.shouldSpellcheck(offset, model);
			}
		}  finally {
			if(model != null) {
				model.releaseFromRead();
			}
		}
		
		return decision;
	}
}