/*******************************************************************************
 * Copyright (c) 2006 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.preferences.InstanceScope;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension3;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.reconciler.DirtyRegion;
import org.eclipse.jface.text.reconciler.IReconcileResult;
import org.eclipse.jface.text.reconciler.IReconcileStep;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.IAnnotationModelExtension;
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.preferences.ScopedPreferenceStore;
import org.eclipse.ui.texteditor.spelling.ISpellingProblemCollector;
import org.eclipse.ui.texteditor.spelling.SpellingContext;
import org.eclipse.ui.texteditor.spelling.SpellingEngineDescriptor;
import org.eclipse.ui.texteditor.spelling.SpellingProblem;
import org.eclipse.ui.texteditor.spelling.SpellingService;
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.SSEUIPlugin;
import org.eclipse.wst.sse.ui.internal.reconcile.DocumentAdapter;
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.5
 */
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) {
			TemporaryAnnotation annotation = new TemporaryAnnotation(new Position(problem.getOffset(), problem.getLength()), TemporaryAnnotation.ANNOT_WARNING, problem.getMessage(), fReconcileAnnotationKey);
			/*
			 * TODO: create and use an IQuickFixProcessor that uses
			 * problem.getProposals() for fixes [note, the default engine
			 * doesn't propose fixes, at least without a dictionary].
			 */
			annotation.setAdditionalFixInfo(problem);
			annotations.add(annotation);
			if (_DEBUG_SPELLING) {
				Logger.log(Logger.INFO_DEBUG, problem.getMessage());
			}
		}

		public void beginCollecting() {
		}

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

		public void endCollecting() {
		}

		IReconcileResult[] getResults() {
			return (IReconcileResult[]) annotations.toArray(new IReconcileResult[annotations.size()]);
		}
	}

	private class SpellingStep extends StructuredReconcileStep {
		protected IReconcileResult[] reconcileModel(final DirtyRegion dirtyRegion, IRegion subRegion) {
			SpellingService service = getSpellingService(fContentTypeId + "." + SpellingService.PREFERENCE_SPELLING_ENGINE); //$NON-NLS-1$
			if (_DEBUG_SPELLING) {
				Logger.log(Logger.INFO_DEBUG, "Spell checking [" + subRegion.getOffset() + "-" + (subRegion.getOffset() + subRegion.getLength()) + "]"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			}
			if (getDocument() != null) {
				service.check(getDocument(), new IRegion[]{subRegion}, fSpellingContext, fProblemCollector, getProgressMonitor());
			}
			IReconcileResult[] results = fProblemCollector.getResults();
			fProblemCollector.clear();
			return results;
		}
	}

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

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

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

	private String fContentTypeId = null;

	private String fDocumentPartitioning;

	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).
	 * 
	 * Value initialized through
	 * 
	 * super(ISourceViewer)->super.init()->createReconcileSteps()
	 */
	ReconcileAnnotationKey fReconcileAnnotationKey;
	private IPropertyChangeListener fSpellCheckPreferenceListener;

	SpellingContext fSpellingContext;

	/*
	 * Value initialized through
	 * 
	 * super(ISourceViewer)->super.init()->createReconcileSteps()
	 */
	IReconcileStep fSpellingStep;

	String[] fSupportedPartitionTypes;

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

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

		String[] definitions = ExtendedConfigurationBuilder.getInstance().getDefinitions(EXTENDED_BUILDER_TYPE, fContentTypeId);
		List defs = new ArrayList();
		for (int i = 0; i < definitions.length; i++) {
			defs.addAll(Arrays.asList(StringUtils.unpack(definitions[i])));
		}
		fSupportedPartitionTypes = (String[]) defs.toArray(new String[defs.size()]);

		fSpellCheckPreferenceListener = new SpellCheckPreferenceListener();
	}

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

	public void createReconcileSteps() {
		fSpellingStep = new SpellingStep();
	}

	String getDocumentPartitioning() {
		return fDocumentPartitioning == null ? IDocumentExtension3.DEFAULT_PARTITIONING : fDocumentPartitioning;
	}

	private TemporaryAnnotation[] getSpellingAnnotationsToRemove(IRegion region) {
		List toRemove = new ArrayList();
		IAnnotationModel annotationModel = getAnnotationModel();
		// can be null when closing the editor
		if (getAnnotationModel() != null) {
			Iterator 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)) {
					Position position = annotation.getPosition();
					if (key.getScope() == ReconcileAnnotationKey.PARTIAL && position.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()]);
	}

	/**
	 * @param engineID
	 * @return the SpellingService with the preferred engine
	 */
	SpellingService getSpellingService(String engineID) {
		SpellingService defaultService = EditorsUI.getSpellingService();

		SpellingService preferredService = defaultService;

		if (engineID != null) {
			/*
			 * Set up a preference store indicating that the given engine
			 * should be used instead of the default preference store's
			 * default
			 */
			SpellingEngineDescriptor[] descriptors = defaultService.getSpellingEngineDescriptors();
			for (int i = 0; i < descriptors.length; i++) {
				if (engineID.equals(descriptors[i].getId())) {
					IPreferenceStore store = new ScopedPreferenceStore(new InstanceScope(), SSEUIPlugin.getDefault().getBundle().getSymbolicName());
					store.setValue(SpellingService.PREFERENCE_SPELLING_ENGINE, engineID);
					preferredService = new SpellingService(store);
					break;
				}
			}
		}
		return preferredService;
	}

	private boolean isSupportedPartitionType(String type) {
		boolean supported = false;
		if (fSupportedPartitionTypes == null || fSupportedPartitionTypes.length == 0) {
			supported = true;
		}
		else {
			for (int i = 0; i < fSupportedPartitionTypes.length; i++) {
				if (type.equals(fSupportedPartitionTypes[i])) {
					supported = true;
					break;
				}
			}
		}
		return supported;
	}

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

	/**
	 * @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;

		TemporaryAnnotation[] annotationsToRemove = null;
		IReconcileResult[] annotationsToAdd = null;
		StructuredReconcileStep structuredStep = (StructuredReconcileStep) fSpellingStep;
		IAnnotationModel annotationModel = getAnnotationModel();

		IDocument document = getDocument();
		if (document != null) {
			try {
				ITypedRegion[] partitions = TextUtilities.computePartitioning(document, getDocumentPartitioning(), dirtyRegion.getOffset(), dirtyRegion.getLength(), true);
				for (int i = 0; i < partitions.length; i++) {
					if (isSupportedPartitionType(partitions[i].getType())) {
						annotationsToRemove = getSpellingAnnotationsToRemove(partitions[i]);
						annotationsToAdd = structuredStep.reconcile(dirtyRegion, partitions[i]);

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

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

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

	public void reconcile(IRegion partition) {
		DirtyRegion region = null;
		IDocument document = getDocument();
		if (document != null) {
			try {
				region = new DirtyRegion(partition.getOffset(), partition.getLength(), DirtyRegion.INSERT, document.get(partition.getOffset(), partition.getLength()));
				reconcile(region, region);
			}
			catch (BadLocationException e) {
				Logger.logException(e);
			}
		}
	}

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

		super.setDocument(document);
		if (document != null) {
			if (fSpellingStep == null) {
				createReconcileSteps();
			}
			fSpellingStep.setInputModel(new DocumentAdapter(document));
		}

		if (getDocument() != null) {
			EditorsUI.getPreferenceStore().addPropertyChangeListener(fSpellCheckPreferenceListener);
		}
	}

	public void setDocumentPartitioning(String partitioning) {
		fDocumentPartitioning = partitioning;
	}
}