/*******************************************************************************
 * Copyright (c) 2001, 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
 *     Jens Lukowski/Innoopract - initial renaming/restructuring
 *     
 *******************************************************************************/
package org.eclipse.wst.sse.ui;

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

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.ITextInputListener;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.reconciler.DirtyRegion;
import org.eclipse.jface.text.reconciler.IReconcilingStrategy;
import org.eclipse.jface.text.reconciler.IReconcilingStrategyExtension;
import org.eclipse.jface.text.reconciler.Reconciler;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.wst.sse.core.IModelLifecycleListener;
import org.eclipse.wst.sse.core.IModelManager;
import org.eclipse.wst.sse.core.IStructuredModel;
import org.eclipse.wst.sse.core.ModelLifecycleEvent;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.events.IStructuredDocumentListener;
import org.eclipse.wst.sse.core.events.NewDocumentEvent;
import org.eclipse.wst.sse.core.events.NoChangeEvent;
import org.eclipse.wst.sse.core.events.RegionChangedEvent;
import org.eclipse.wst.sse.core.events.RegionsReplacedEvent;
import org.eclipse.wst.sse.core.events.StructuredDocumentRegionsReplacedEvent;
import org.eclipse.wst.sse.core.text.IStructuredDocument;
import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.text.IStructuredDocumentRegionList;
import org.eclipse.wst.sse.ui.internal.Logger;
import org.eclipse.wst.sse.ui.internal.reconcile.AbstractStructuredTextReconcilingStrategy;
import org.eclipse.wst.sse.ui.internal.reconcile.validator.ValidatorStrategy;
import org.eclipse.wst.sse.ui.util.Assert;


/**
 * Reconciler that maps different partitions to different strategies.
 * Strategies contain one or more Steps Steps contain code that validates
 * dirty regions
 * 
 * Is aware of StructuredDocumentEvents which determine if a reconcile should
 * be done or not. On partition change events in the document, all strategies
 * are called.
 * 
 * @deprecated
 * 
 * @author pavery
 */
public class StructuredTextReconciler extends Reconciler implements IStructuredDocumentListener, IModelLifecycleListener {

	/**
	 * Reconclies the entire document when the document in the viewer is
	 * changed. This happens when the document is initially opened, as well as
	 * after a save-as.
	 * 
	 * Also see processPostModelEvent(...) for similar behavior when document
	 * for the model is changed.
	 */
	private class SourceTextInputListener implements ITextInputListener {

		public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
			// do nothing
		}

		public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {

			// don't bother if reconciler not installed
			if (isInstalled()) {
				setDocument(newInput);
				setDocumentOnAllStrategies(newInput);
				setEntireDocumentDirty(newInput);
			}
		}
	}

	/**
	 * Cancels any running reconcile operations via progress monitor. Ensures
	 * that strategies are released on close of the editor.
	 */
	private class SourceWidgetDisposeListener implements DisposeListener {

		public void widgetDisposed(DisposeEvent e) {

			getLocalProgressMonitor().setCanceled(true);

			// release all strategies
			if (fDefaultStrategy != null && fDefaultStrategy instanceof IReleasable) {
				((IReleasable) fDefaultStrategy).release();
				fDefaultStrategy = null;
			}
			if (!fStrategyTypes.isEmpty()) {
				Iterator it = fStrategyTypes.iterator();
				IReconcilingStrategy strategy = null;
				while (it.hasNext()) {
					strategy = getReconcilingStrategy((String) it.next());
					if (strategy instanceof IReleasable) {
						((IReleasable) strategy).release();
						strategy = null;
					}
				}
			}
		}
	}

	public static final String TRACE_FILTER = "reconciler"; //$NON-NLS-1$

	/** strategy called for unmapped partitions */
	IReconcilingStrategy fDefaultStrategy;

	/** to cancel any long running reconciles if someone closes the editor */
	private SourceWidgetDisposeListener fDisposeListener = null;

	/**
	 * set true after first install to prevent duplicate work done in the
	 * install method (since install gets called multiple times)
	 */
	private boolean fIsInstalled = false;

	/** local queue of dirty regions (created here) to be reconciled */
	private List fLocalDirtyRegionQueue = null;

	/** document that this reconciler works on */
	private IDocument fLocalDocument = null;

	// use our own local for now until we resolve abstract calling it on every
	// document change
	// resulting in some of our strategies getting cut short and not
	// adding/removing annotations correctly
	private IProgressMonitor fLocalProgressMonitor = null;

	/** local copy of model manager */
	private IModelManager fModelManager = null;

	/** the list of partition types for which there are strategies */
	List fStrategyTypes = null;

	/** for initital reconcile when document is opened */
	private SourceTextInputListener fTextInputListener = null;

	/** flag set via structured document events */
	private boolean fValidationNeeded = false;

	/**
	 * the strategy that runs validators contributed via reconcileValidator
	 * ext point
	 */
	private ValidatorStrategy fValidatorStrategy;

	/**
	 * Creates a new StructuredRegionProcessor
	 */
	public StructuredTextReconciler() {
		super();
		configure();
	}

	/**
	 * This method reduces the dirty region queue to the least common dirty
	 * region. (the region that overlaps all dirty regions)
	 * 
	 * @return a condensed DirtyRegion representing all that was in the queue
	 *         at the time this was called, or <code>null</code> if the
	 *         queue is empty
	 */
	private DirtyRegion compactDirtyRegionQueue() {

		DirtyRegion result = null;
		StringBuffer traceInfo = new StringBuffer();
		if (Logger.isTracing(TRACE_FILTER))
			traceInfo.append("[reconciler] COMPACTING STARTING... localDirtyRegionQueue.size():" + fLocalDirtyRegionQueue.size()); //$NON-NLS-1$

		if (fLocalDirtyRegionQueue.size() == 1)
			return (DirtyRegion) fLocalDirtyRegionQueue.remove(0);

		if (!fLocalDirtyRegionQueue.isEmpty()) {
			result = formNewDirtyRegion(traceInfo);
		}

		return result;
	}

	private void configure() {
		fStrategyTypes = new ArrayList();

		// we are always incremental
		setIsIncrementalReconciler(true);
		setDelay(500);
		// setProgressMonitor(new NullProgressMonitor());
		setLocalProgressMonitor(new NullProgressMonitor());
		fDisposeListener = new SourceWidgetDisposeListener();
		fTextInputListener = new SourceTextInputListener();
		fLocalDirtyRegionQueue = new ArrayList();
	}

	private DirtyRegion createDirtyRegion(int offset, int length, String type) {
		DirtyRegion durty = null;
		IDocument doc = getDocument();
		// safety for BLE
		int docLen = doc.getLength();
		if (offset + length > docLen)
			length = docLen - offset;

		if (doc != null) {
			try {
				durty = new DirtyRegion(offset, length, type, doc.get(offset, length));
			}
			catch (BadLocationException e) {
				e.printStackTrace();
			}
		}
		return durty;
	}

	private DirtyRegion createDirtyRegion(ITypedRegion tr, String type) {
		return createDirtyRegion(tr.getOffset(), tr.getLength(), type);
	}

	private DirtyRegion formNewDirtyRegion(StringBuffer traceInfo) {
		DirtyRegion result;
		int min = -1;
		int max = -1;
		DirtyRegion dr = null;
		for (int i = 0; i < fLocalDirtyRegionQueue.size(); i++) {
			dr = (DirtyRegion) fLocalDirtyRegionQueue.get(i);
			if (dr == null)
				continue;

			if (Logger.isTracing(TRACE_FILTER))
				traceInfo.append("\r\n\r\n -> compacting dirty region (" + i + ")" + " start:" + dr.getOffset() + " length:" + dr.getLength()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$

			// possibly expand the dirty region start
			if (min == -1 || min > dr.getOffset())
				min = dr.getOffset();
			// possibly expand the dirty region end
			if (max == -1 || max < dr.getOffset() + dr.getLength())
				max = dr.getOffset() + dr.getLength();
		}
		fLocalDirtyRegionQueue.clear();
		result = (min != -1) ? createDirtyRegion(min, max - min, DirtyRegion.INSERT) : null;

		if (Logger.isTracing(TRACE_FILTER)) {
			traceInfo.append("\r\n\r\nCOMPACTING DONE... dirtyRangeStart:" + min + " dirtyRangeEnd:" + max + "\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			Logger.trace(TRACE_FILTER, traceInfo.toString());
		}
		return result;
	}

	/**
	 * Gets a strategy that is made to handle the given dirtyRegion.
	 * 
	 * @param dirtyRegion
	 * @return a strategy that is made to handle the given dirtyRegion, or the
	 *         default strategy for this reconciler if there isn't one
	 */
	protected IReconcilingStrategy getAppropriateStrategy(DirtyRegion dirtyRegion) {
		String[] partitions = getPartitions(dirtyRegion);
		// for now just grab first partition type in dirty region
		IReconcilingStrategy rs = null;
		if (partitions.length > 0)
			rs = getReconcilingStrategy(partitions[0]);
		return rs != null ? rs : fDefaultStrategy;
	}

	/**
	 * Gets the default strategy for this reconciler.
	 * 
	 * @return the default strategy
	 */
	protected IReconcilingStrategy getDefaultStrategy() {
		return fDefaultStrategy;
	}

	/**
	 * We use our own local progress monitor to cancel long running
	 * strategies/steps. Currently used when widget is disposed (user is
	 * trying to close the editor), and on uninstall.
	 * 
	 * @return the local progress monitor
	 */
	IProgressMonitor getLocalProgressMonitor() {
		return fLocalProgressMonitor;
	}

	/**
	 * Avoid excessive calls to Platform.getPlugin(ModelPlugin.ID)
	 * 
	 * @return sse model manager
	 */
	protected IModelManager getModelManager() {
		if (this.fModelManager == null)
			this.fModelManager = StructuredModelManager.getModelManager();
		return this.fModelManager;
	}

	/**
	 * @deprecated - does not use correct partitioning assumes isInstalled() ==
	 *             true
	 * 
	 * @return the document partitioner for the document this reconciler is
	 *         working on.
	 */
	protected IDocumentPartitioner getPartitioner() {
		return getDocument().getDocumentPartitioner();
	}

	/**
	 * Utility method to get partitions types in a dirty region
	 * 
	 * @param dirtyRegion
	 * @return
	 */
	protected String[] getPartitions(DirtyRegion dirtyRegion) {
		ITypedRegion[] partitions = null;
		try {
			partitions = TextUtilities.computePartitioning(getDocument(), getDocumentPartitioning(), dirtyRegion.getOffset(), dirtyRegion.getLength(), false);
		}
		catch (BadLocationException e) {
			partitions = getPartitioner().computePartitioning(dirtyRegion.getOffset(), dirtyRegion.getLength());
		}
		String[] partitionTypes = new String[partitions.length];
		for (int i = 0; i < partitions.length; i++)
			partitionTypes[i] = partitions[i].getType();
		return partitionTypes;
	}

	/**
	 * @deprecated - promotes model leakage
	 * 
	 * Remember to release model after use!!
	 * 
	 * @return
	 */
	public IStructuredModel getStructuredModelForRead(IDocument doc) {
		IStructuredModel sModel = null;
		if (doc != null)
			sModel = getModelManager().getExistingModelForRead(doc);
		return sModel;
	}

	/**
	 * Get the strategy that runs validators from the reconcileValidator
	 * extension point.
	 * 
	 * @param the
	 *            ValidatorStrategy
	 */
	public ValidatorStrategy getValidatorStrategy() {
		return fValidatorStrategy;
	}



	/**
	 * @param document
	 */
	private void hookUpModelLifecycleListener(IDocument document) {
		IStructuredModel sModel = getModelManager().getExistingModelForRead(document);
		try {
			if (sModel != null) {
				sModel.addModelLifecycleListener(this);
			}
		}
		finally {
			if (sModel != null)
				sModel.releaseFromRead();
		}
	}

	protected void initialProcess() {
		// only happens ONCE on first dirty region in queue (not on doucment
		// open)
		// not useful to us at the moment
	}

	/**
	 * @see org.eclipse.jface.text.reconciler.IReconciler#install(ITextViewer)
	 */
	public void install(ITextViewer textViewer) {
		// we might be called multiple times with the same viewer,
		// maybe after being uninstalled as well, so track separately
		if (!isInstalled()) {

			super.install(textViewer);

			textViewer.getTextWidget().addDisposeListener(fDisposeListener);
			textViewer.addTextInputListener(fTextInputListener);

			getLocalProgressMonitor().setCanceled(false);

			setInstalled(true);
			setValidationNeeded(true);
		}
	}

	/**
	 * @param dirtyRegion
	 * @return
	 */
	private boolean isEntireDocumentChange(DirtyRegion dirtyRegion) {
		return getDocument().getLength() == dirtyRegion.getLength();
	}

	/**
	 * The viewer has been set on this Reconciler.
	 * 
	 * @return true if the viewer has been set on this Reconciler, false
	 *         otherwise.
	 */
	public boolean isInstalled() {
		return fIsInstalled;
	}

	/**
	 * @return Returns the needsValidation.
	 */
	public boolean isValidationNeeded() {
		return fValidationNeeded;
	}

	public void newModel(NewDocumentEvent structuredDocumentEvent) {
		// do nothing
	}

	public void noChange(NoChangeEvent structuredDocumentEvent) {
		// do nothing
	}

	public void nodesReplaced(StructuredDocumentRegionsReplacedEvent structuredDocumentEvent) {
		Logger.trace(StructuredTextReconciler.TRACE_FILTER, "[trace reconciler] >StructuredRegionProcessor: *NODES REPLACED"); //$NON-NLS-1$

		// if partition changed, create a full document dirty region
		// (causes processAll)
		DirtyRegion dr = partitionChanged(structuredDocumentEvent) ? createDirtyRegion(0, getDocument().getLength(), DirtyRegion.INSERT) : createDirtyRegion(structuredDocumentEvent.getOriginalStart(), structuredDocumentEvent.getLength(), DirtyRegion.INSERT);
		fLocalDirtyRegionQueue.add(dr);

		setValidationNeeded(true);
	}

	/**
	 * Checks if the StructuredDocumentEvent involved a partition change. If
	 * there's a partition change, we know we should run all strategies just
	 * to be sure we cover the new regions and remove obsolete annotations.
	 * 
	 * A primitive check for now.
	 * 
	 * @param structuredDocumentEvent
	 * @return
	 */
	private boolean partitionChanged(StructuredDocumentRegionsReplacedEvent structuredDocumentEvent) {
		boolean changed = false;

		IDocumentPartitioner partitioner = structuredDocumentEvent.getStructuredDocument().getDocumentPartitioner();
		if (partitioner != null) {
			IStructuredDocumentRegionList oldNodes = structuredDocumentEvent.getOldStructuredDocumentRegions();
			IStructuredDocumentRegionList newNodes = structuredDocumentEvent.getNewStructuredDocumentRegions();

			IStructuredDocumentRegion oldNode = (oldNodes.getLength() > 0) ? oldNode = oldNodes.item(0) : null;
			IStructuredDocumentRegion newNode = (newNodes.getLength() > 0) ? newNodes.item(0) : null;

			if (oldNode != null && newNode != null)
				changed = partitioner.getContentType(oldNode.getStartOffset()).equals(partitioner.getContentType(newNode.getStartOffset()));
		}
		return changed;
	}

	/**
	 * We keep a local copy of the dirty region queue for compacting.
	 * 
	 * @see org.eclipse.jface.text.reconciler.AbstractReconciler#process(org.eclipse.jface.text.reconciler.DirtyRegion)
	 */
	protected void process(DirtyRegion dirtyRegion) {
		// this is called from the background thread in AbstractReconciler
		// called here so that it only kick off after .5 seconds
		// but fNeedsValidation flag is set in structuredDoucmentsEvents below
		if (isInstalled()) {
			runStrategies();
		}
	}

	/**
	 * Process the entire StructuredDocument. Much more resource intensive
	 * than simply running a strategy on a dirty region.
	 */
	protected void processAll() {
		if (!isInstalled())
			return;
		Logger.trace(StructuredTextReconciler.TRACE_FILTER, "[trace reconciler] >StructuredRegionProcessor: PROCESSING ALL"); //$NON-NLS-1$
		IDocument doc = getDocument();
		DirtyRegion durty = null;

		ITypedRegion tr[] = new ITypedRegion[0];
		try {
			tr = TextUtilities.computePartitioning(doc, getDocumentPartitioning(), 0, doc.getLength(), true);
		}
		catch (BadLocationException e) {
			Logger.logException(e);
		}

		IReconcilingStrategy s = null;
		for (int i = 0; i < tr.length; i++) {
			durty = createDirtyRegion(tr[i], DirtyRegion.INSERT);
			s = getReconcilingStrategy(tr[i].getType());
			if (s != null) {
				if (s instanceof AbstractStructuredTextReconcilingStrategy)
					((AbstractStructuredTextReconcilingStrategy) s).reconcile(durty, durty);
				else
					s.reconcile(durty, durty);
			}
			// run validator strategy every time, it figures out if it has
			// a
			// validator for this partition
			// pass in true for "refreshAll" flag = true indicating that
			// the
			// entire document is being reconciled, only do it once
			if (fValidatorStrategy != null)
				fValidatorStrategy.reconcile(tr[i], durty);

		}
		// we ran the whole doc already now we can reset the strategies
		resetStrategies();
	}

	/**
	 * Process a subsection of the document.
	 */
	protected void processPartial(DirtyRegion durty) {
		if (!isInstalled())
			return;
		IDocument doc = getDocument();
		HashSet alreadyRan = new HashSet();

		ITypedRegion tr[] = new ITypedRegion[0];
		try {
			tr = TextUtilities.computePartitioning(doc, getDocumentPartitioning(), 0, doc.getLength(), true);
		}
		catch (BadLocationException e) {
			Logger.logException(e);
		}

		IReconcilingStrategy s = null;
		for (int i = 0; i < tr.length; i++) {
			durty = createDirtyRegion(tr[i], DirtyRegion.INSERT);
			// keeping track of already ran might not be the way to do
			// it...
			if (!alreadyRan.contains(tr[i].getType())) {
				alreadyRan.add(tr[i].getType());
				s = getReconcilingStrategy(tr[i].getType());
				if (s != null)
					s.reconcile(durty, durty);
			}
			// run validator strategy every time, it figures out if it has
			// a
			// validator for this parition
			if (fValidatorStrategy != null)
				fValidatorStrategy.reconcile(tr[i], durty);
		}

		resetStrategies();
	}

	/**
	 * @see org.eclipse.wst.sse.core.IModelLifecycleListener#processPostModelEvent(org.eclipse.wst.sse.core.ModelLifecycleEvent)
	 */
	public void processPostModelEvent(ModelLifecycleEvent event) {

		// if underlying StructuredDocument changed, need to reconnect it
		// here...
		// ex. file is modified outside the workbench
		if (event.getType() == ModelLifecycleEvent.MODEL_DOCUMENT_CHANGED) {

			// check that it's this model that changed
			IStructuredModel thisModel = getModelManager().getExistingModelForRead(getDocument());
			try {
				if (thisModel != null && event.getModel().equals(thisModel)) {

					IStructuredDocument sDoc = event.getModel().getStructuredDocument();

					if (Logger.isTracing(TRACE_FILTER)) {
						System.out.println("======================================================"); //$NON-NLS-1$
						System.out.println("StructuredRegionProcessor: DOCUMENT MODEL CHANGED TO: "); //$NON-NLS-1$
						System.out.println(sDoc.get());
						System.out.println("======================================================"); //$NON-NLS-1$
					}
					setDocument(sDoc);

					// propagate document change
					setDocumentOnAllStrategies(sDoc);

					// ensure that the document is re-reconciled
					setEntireDocumentDirty(sDoc);
				}
			}
			finally {
				if (thisModel != null)
					thisModel.releaseFromRead();
			}
		}
	}

	/**
	 * @see org.eclipse.wst.sse.core.IModelLifecycleListener#processPreModelEvent(org.eclipse.wst.sse.core.ModelLifecycleEvent)
	 */
	public void processPreModelEvent(ModelLifecycleEvent event) {

		if (event.getType() == ModelLifecycleEvent.MODEL_DOCUMENT_CHANGED) {

			// clear the dirty region queue
			fLocalDirtyRegionQueue.clear();

			// note: old annotations are removed via the strategies on
			// AbstractStructuredTextReconcilingStrategy#setDocument(...)
		}
	}

	/**
	 * Reinitializes listeners and sets new document onall strategies.
	 * 
	 * @see org.eclipse.jface.text.reconciler.AbstractReconciler#reconcilerDocumentChanged(IDocument)
	 */
	protected void reconcilerDocumentChanged(IDocument document) {

		// unhook old lifecycle listner
		unhookModelLifecycleListener(fLocalDocument);

		// add new lifecycle listener
		hookUpModelLifecycleListener(document);

		if (fLocalDocument != null && fLocalDocument instanceof IStructuredDocument)
			((IStructuredDocument) fLocalDocument).removeDocumentChangedListener(this);

		setDocument(document);

		if (document != null && document instanceof IStructuredDocument)
			((IStructuredDocument) fLocalDocument).addDocumentChangedListener(this);

		setDocumentOnAllStrategies(document);
	}

	public void regionChanged(RegionChangedEvent structuredDocumentEvent) {
		Logger.trace(StructuredTextReconciler.TRACE_FILTER, "[trace reconciler] >StructuredRegionProcessor: *REGION CHANGED: \r\n\r\n created dirty region from flat model event >> :" + structuredDocumentEvent.getOriginalStart() + ":" + structuredDocumentEvent.getLength() + "\r\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

		String dirtyRegionType = structuredDocumentEvent.getDeletedText().equals("") ? DirtyRegion.INSERT : DirtyRegion.REMOVE; //$NON-NLS-1$
		DirtyRegion dr = createDirtyRegion(structuredDocumentEvent.getOriginalStart(), structuredDocumentEvent.getLength(), dirtyRegionType);

		fLocalDirtyRegionQueue.add(dr);

		setValidationNeeded(true);
	}

	public void regionsReplaced(RegionsReplacedEvent structuredDocumentEvent) {
		Logger.trace(StructuredTextReconciler.TRACE_FILTER, "[trace reconciler] >StructuredRegionProcessor: *REGIONS REPLACED: \r\n\r\n created dirty region from flat model event >> :" + structuredDocumentEvent.getOriginalStart() + ":" + structuredDocumentEvent.getLength() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

		DirtyRegion dr = createDirtyRegion(structuredDocumentEvent.getOriginalStart(), structuredDocumentEvent.getLength(), DirtyRegion.INSERT);
		fLocalDirtyRegionQueue.add(dr);

		setValidationNeeded(true);
	}

	/**
	 * Resets any flags that were set (eg. flags set during processAll())
	 */
	protected void resetStrategies() {
//		Iterator it = fStrategyTypes.iterator();
//		String type = null;
//		while (it.hasNext()) {
//			type = (String) it.next();
//			if (getReconcilingStrategy(type) instanceof AbstractStructuredTextReconcilingStrategy)
//				((AbstractStructuredTextReconcilingStrategy) getReconcilingStrategy(type)).reset();
//		}
	}

	/**
	 * Runs the appropriate strategies on the dirty region queue. The
	 * reconciler currently handles these reconciling scenarios:
	 * 
	 * <ul>
	 * <li>partition change</li>
	 * <li>routine text edits</li>
	 * <li>entire document change</li>
	 * <li>the default strategy</li>
	 * </ul>
	 * 
	 */
	private void runStrategies() {
		DirtyRegion dirtyRegion = null;
		while (fDefaultStrategy != null && isInstalled() && isValidationNeeded()) {
			// this flag may be set to true if more dirty regions come in
			// while this method is running
			setValidationNeeded(false);
			Logger.trace(TRACE_FILTER, "start RUNNING STRATEGIES IN RECONCILER"); //$NON-NLS-1$
			dirtyRegion = compactDirtyRegionQueue();
			// will be null if there is nothing in the queue
			if (dirtyRegion != null) {
				Logger.trace(TRACE_FILTER, "RUNNING with dirty region:" + dirtyRegion.getOffset() + ":" + dirtyRegion.getLength()); //$NON-NLS-1$ //$NON-NLS-2$
				try {
					if (isEntireDocumentChange(dirtyRegion))
						processAll();
					else
						processPartial(dirtyRegion);
				}
				catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	/**
	 * Sets the default reconciling strategy.
	 * 
	 * @param strategy
	 */
	public void setDefaultStrategy(IReconcilingStrategy strategy) {
		Assert.isNotNull(strategy, "Can't set default strategy to null"); //$NON-NLS-1$

		fDefaultStrategy = strategy;
		fDefaultStrategy.setDocument(getDocument());
		if (fDefaultStrategy instanceof IReconcilingStrategyExtension)
			((IReconcilingStrategyExtension) fDefaultStrategy).setProgressMonitor(getLocalProgressMonitor());
	}


	public void setDocument(IDocument doc) {
		// making sure local document is always up to date
		// https://w3.opensource.ibm.com/bugzilla/show_bug.cgi?id=3858
		fLocalDocument = doc;
		setDocumentOnAllStrategies(doc);
	}

	/**
	 * Propagates a new document to all strategies and steps.
	 * 
	 * @param document
	 */
	protected void setDocumentOnAllStrategies(IDocument document) {
		if (isInstalled()) {
			// default strategies
			if (fDefaultStrategy != null)
				fDefaultStrategy.setDocument(document);

			// external validator strategy
			if (fValidatorStrategy != null)
				fValidatorStrategy.setDocument(document);

			// set document on all regular strategies
			super.reconcilerDocumentChanged(document);
		}
	}

	protected void setEntireDocumentDirty(IDocument document) {

		// make the entire document dirty
		// this also happens on a "save as"
		if (document != null && isInstalled() && fLocalDirtyRegionQueue.size() == 0) {

			// since we're marking the entire doc dirty
			fLocalDirtyRegionQueue.clear();

			DirtyRegion entireDocument = createDirtyRegion(0, document.getLength(), DirtyRegion.INSERT);
			fLocalDirtyRegionQueue.add(entireDocument);

			// set this so reconcile won't be "short circuited"
			setValidationNeeded(true);
		}
	}

	/**
	 * @param isInstalled
	 *            The isInstalled to set.
	 */
	public void setInstalled(boolean isInstalled) {
		fIsInstalled = isInstalled;
	}

	private void setLocalProgressMonitor(IProgressMonitor pm) {
		fLocalProgressMonitor = pm;
		// set on default strategy
		if (fDefaultStrategy != null && fDefaultStrategy instanceof IReconcilingStrategyExtension)
			((IReconcilingStrategyExtension) fDefaultStrategy).setProgressMonitor(pm);
		// set on all other strategies
		if (!fStrategyTypes.isEmpty()) {
			Iterator it = fStrategyTypes.iterator();
			String type = null;
			while (it.hasNext()) {
				type = (String) it.next();
				if (getReconcilingStrategy(type) instanceof IReconcilingStrategyExtension)
					((IReconcilingStrategyExtension) getReconcilingStrategy(type)).setProgressMonitor(pm);
			}
		}
	}

	/**
	 * Sets the strategy for a given contentType (partitionType)
	 * 
	 * @see org.eclipse.jface.text.reconciler.Reconciler#setReconcilingStrategy(org.eclipse.jface.text.reconciler.IReconcilingStrategy,
	 *      java.lang.String)
	 */
	public void setReconcilingStrategy(IReconcilingStrategy strategy, String contentType) {
		super.setReconcilingStrategy(strategy, contentType);
		if (strategy != null) {
			strategy.setDocument(fLocalDocument);
			if (strategy instanceof IReconcilingStrategyExtension) {
				((IReconcilingStrategyExtension) strategy).setProgressMonitor(getLocalProgressMonitor());
			}
		}
		fStrategyTypes.add(contentType);
	}

	/**
	 * @param needsValidation
	 *            The needsValidation to set.
	 */
	public void setValidationNeeded(boolean needsValidation) {
		fValidationNeeded = needsValidation;
	}

	/**
	 * Set the strategy that runs validators from the reconcileValidator
	 * extension point.
	 * 
	 * @param the
	 *            ValidatorStrategy
	 */
	public void setValidatorStrategy(ValidatorStrategy strategy) {
		fValidatorStrategy = strategy;
		if (fValidatorStrategy != null)
			fValidatorStrategy.setDocument(getDocument());
	}

	/**
	 * 
	 * @param document
	 */
	private void unhookModelLifecycleListener(IDocument document) {
		IStructuredModel sModel = getModelManager().getExistingModelForRead(document);
		try {
			if (sModel != null) {
				sModel.removeModelLifecycleListener(this);
			}
		}
		finally {
			if (sModel != null)
				sModel.releaseFromRead();
		}
	}

	/**
	 * Cleanup listeners.
	 * 
	 * @see org.eclipse.jface.text.reconciler.IReconciler#uninstall()
	 */
	public void uninstall() {
		setValidationNeeded(false);
		if (isInstalled()) {
			setInstalled(false);
			// getProgressMonitor().setCanceled(true);
			getLocalProgressMonitor().setCanceled(true);

			getTextViewer().removeTextInputListener(fTextInputListener);

			super.uninstall();
		}
		if (fLocalDocument != null && fLocalDocument instanceof IStructuredDocument) {
			// remove structured document listener
			((IStructuredDocument) fLocalDocument).removeDocumentChangedListener(this);
			// remove lifecycle listener on the model
			unhookModelLifecycleListener(fLocalDocument);
		}
		setDocument(null);
	}
}
