/*=============================================================================#
 # Copyright (c) 2005, 2020 Stephan Wahlbrink and others.
 # 
 # This program and the accompanying materials are made available under the
 # terms of the Eclipse Public License 2.0 which is available at
 # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 # which is available at https://www.apache.org/licenses/LICENSE-2.0.
 # 
 # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 # 
 # Contributors:
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.ecommons.text;

import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.TypedRegion;

import org.eclipse.statet.jcommons.collections.IntArrayList;
import org.eclipse.statet.jcommons.collections.IntList;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;

import org.eclipse.statet.ecommons.text.core.PartitionConstraint;
import org.eclipse.statet.ecommons.text.core.sections.DocContentSections;


/**
 * Utility methods for heuristic based R manipulations in an incomplete source file.
 * <p>
 * An instance holds some internal position in the document and is therefore not threadsafe.</p>
 * 
 * @since 0.2
 */
@NonNullByDefault
public class BasicHeuristicTokenScanner implements ITokenScanner {
	
	
	protected static final PartitionConstraint ALL_PARTITIONS_CONSTRAINT= new PartitionConstraint() {
		
		@Override
		public boolean matches(final String partitionType) {
			return true;
		}
		
	};
	
	
	/**
	 * Specifies the stop condition, upon which the <code>scan...</code> methods will decide whether
	 * to keep scanning or not. This interface may implemented by clients.
	 */
	protected abstract class StopCondition {
		
		/**
		 * Instructs the scanner to return the current position.
		 * 
		 * @return <code>true</code> if the stop condition is met.
		 */
		public abstract boolean stop();
		
		/**
		 * Asks the condition to return the next position to query. The default
		 * is to return the next/previous position.
		 * 
		 * @return the next position to scan
		 */
		public int nextPositionForward() {
			return BasicHeuristicTokenScanner.this.pos + 1;
		}
		
		public int nextPositionBackward() {
			return BasicHeuristicTokenScanner.this.pos - 1;
		}
		
	}
	
	/**
	 * Stops upon a character in the default partition that matches the given character list.
	 */
	protected abstract class PartitionBasedCondition extends StopCondition {
		
		private @Nullable ITypedRegion currentPartition;
		private boolean currentPartitionMatched;
		private int currentPartitionStart;
		private int currentPartitionEnd;
		
		public PartitionBasedCondition() {
			this.currentPartitionMatched= false;
		}
		
		@Override
		public boolean stop() {
			if (this.currentPartitionMatched && this.currentPartitionStart <= BasicHeuristicTokenScanner.this.pos && BasicHeuristicTokenScanner.this.pos < this.currentPartitionEnd) {
				return matchesChar();
			}
			final ITypedRegion partition= getPartition();
			this.currentPartition= partition;
			this.currentPartitionStart= partition.getOffset();
			this.currentPartitionEnd= this.currentPartitionStart + partition.getLength();
			if (BasicHeuristicTokenScanner.this.partitionConstraint.matches(partition.getType())) {
				this.currentPartitionMatched= true;
				return matchesChar();
			}
			else {
				this.currentPartitionMatched= false;
				return false;
			}
			
		}
		
		protected abstract boolean matchesChar();
		
		@Override
		public int nextPositionForward() {
			if (this.currentPartitionMatched) {
				return BasicHeuristicTokenScanner.this.pos + 1;
			}
			if (BasicHeuristicTokenScanner.this.pos < this.currentPartitionEnd) {
				return this.currentPartitionEnd;
			}
			return BasicHeuristicTokenScanner.this.pos + 1;
		}
		
		@Override
		public int nextPositionBackward() {
			if (this.currentPartitionMatched) {
				return BasicHeuristicTokenScanner.this.pos - 1;
			}
			if (BasicHeuristicTokenScanner.this.pos >= this.currentPartitionStart) {
				return this.currentPartitionStart - 1;
			}
			return BasicHeuristicTokenScanner.this.pos - 1;
		}
		
	}
	
	
	protected class SingleCharacterMatchCondition extends PartitionBasedCondition {
		
		protected final int singleChar;
		
		/**
		 * Creates a new instance.
		 * @param ch the single character to match
		 */
		public SingleCharacterMatchCondition(final char ch) {
			this.singleChar= ch;
		}
		
		@Override
		protected boolean matchesChar() {
			return (this.singleChar == BasicHeuristicTokenScanner.this.ch);
		}
		
	}
	
	protected class CharacterMatchCondition extends PartitionBasedCondition {
		
		protected final char[] fChars;
		
		/**
		 * Creates a new instance.
		 * @param chars the chars to match.
		 */
		public CharacterMatchCondition(final char[] chars) {
			assert (chars != null);
			this.fChars= chars;
		}
		
		@Override
		protected boolean matchesChar() {
			for (int i= 0; i < this.fChars.length; i++) {
				if (this.fChars[i] == BasicHeuristicTokenScanner.this.ch) {
					return true;
				}
			}
			return false;
		}
		
	}
	
	protected class ExtCharacterMatchCondition extends CharacterMatchCondition {
		
		private final char fEscapeChar;
		private int fLastEscapeOffset= -100;
		
		ExtCharacterMatchCondition(final char[] chars, final char escapeChar) {
			super(chars);
			this.fEscapeChar= escapeChar;
		}
		
		@Override
		protected boolean matchesChar() {
			if (BasicHeuristicTokenScanner.this.pos == this.fLastEscapeOffset+1) {
				return false;
			}
			if (BasicHeuristicTokenScanner.this.ch == this.fEscapeChar) {
				this.fLastEscapeOffset= BasicHeuristicTokenScanner.this.pos;
				return false;
			}
			return super.matchesChar();
		}
		
	}
	
	protected class StringMatchCondition extends PartitionBasedCondition {
		
		protected final String[] strings;
		private final int escapeChar;
		private int lastEscapeOffset= Integer.MIN_VALUE;
		
		/**
		 * Creates a new instance.
		 * @param ch the string to match
		 */
		public StringMatchCondition(final String s, final int escapeChar) {
			this.strings= new String[] { s };
			this.escapeChar= escapeChar;
		}
		
		/**
		 * Creates a new instance.
		 * @param ch the string to match
		 */
		public StringMatchCondition(final String[] s, final int escapeChar) {
			this.strings= s;
			this.escapeChar= escapeChar;
		}
		
		@Override
		protected boolean matchesChar() {
			if (BasicHeuristicTokenScanner.this.pos == this.lastEscapeOffset + 1) {
				return false;
			}
			if (this.escapeChar == BasicHeuristicTokenScanner.this.ch) {
				this.lastEscapeOffset= BasicHeuristicTokenScanner.this.pos;
				return false;
			}
			try {
				for (final String string : this.strings) {
					if (string.charAt(0) == BasicHeuristicTokenScanner.this.ch) {
						if (string.regionMatches(1, BasicHeuristicTokenScanner.this.document.get(
								BasicHeuristicTokenScanner.this.pos + 1, string.length() - 1),
								0, string.length() - 1 )) {
							return true;
						}
					}
				}
			} catch (final BadLocationException e) {}
			return false;
		}
		
	}
	
	
	/** The partitioning being used for scanning. */
	private final String partitioning;
	
	private final PartitionConstraint defaultPartitionConstraint;
	
	/** The document being scanned. */
	private IDocument document;
	/** The partition to scan in. */
	private PartitionConstraint partitionConstraint;
	
	/* internal scan state */
	
	/** the most recently read character. */
	protected char ch;
	/** the most recently read position. */
	protected int pos;
	/** the most recently read line of position (only if used). */
	private int line;
	
	private @Nullable StopCondition nonWSCondition;
	private @Nullable StopCondition nonWSorLRCondition;
	
	
	@SuppressWarnings("null")
	public BasicHeuristicTokenScanner(final DocContentSections documentContentInfo,
			final PartitionConstraint defaultContentConstraint) {
		this.partitioning= documentContentInfo.getPartitioning();
		this.defaultPartitionConstraint= defaultContentConstraint;
	}
	
	
	public final IDocument getDocument() {
		return this.document;
	}
	
	public final String getDocumentPartitioning() {
		return this.partitioning;
	}
	
	protected final PartitionConstraint getDefaultPartitionConstraint() {
		return this.defaultPartitionConstraint;
	}
	
	protected final PartitionConstraint getPartitionConstraint() {
		return this.partitionConstraint;
	}
	
	public final char getChar() {
		return this.ch;
	}
	
	protected boolean isWhitespace() {
		return (Character.getType(this.ch) == Character.SPACE_SEPARATOR || this.ch == '\t');
	}
	
	protected final StopCondition getAnyNonWSCondition() {
		StopCondition nonWSCondition= this.nonWSCondition;
		if (nonWSCondition == null) {
			nonWSCondition= new StopCondition() {
				@Override
				public boolean stop() {
					return (!isWhitespace());
				}
			};
			this.nonWSCondition= nonWSCondition;
		}
		return nonWSCondition;
	}
	
	protected final StopCondition getAnyNonWSorLRCondition() {
		StopCondition nonWSorLRCondition= this.nonWSorLRCondition;
		if (nonWSorLRCondition == null) {
			nonWSorLRCondition= new StopCondition() {
				@Override
				public boolean stop() {
					return (!isWhitespace() && BasicHeuristicTokenScanner.this.ch != '\r' && BasicHeuristicTokenScanner.this.ch != '\n');
				}
			};
			this.nonWSorLRCondition= nonWSorLRCondition;
		}
		return nonWSorLRCondition;
	}
	
	protected final StopCondition getNonWSCondition() {
		StopCondition nonWSCondition= this.nonWSCondition;
		if (nonWSCondition == null) {
			nonWSCondition= new PartitionBasedCondition() {
				@Override
				protected boolean matchesChar() {
					return (!isWhitespace());
				}
			};
			this.nonWSCondition= nonWSCondition;
		}
		return nonWSCondition;
	}
	
	protected final StopCondition getNonWSorLRCondition() {
		StopCondition nonWSorLRCondition= this.nonWSorLRCondition;
		if (nonWSorLRCondition == null) {
			nonWSorLRCondition= new PartitionBasedCondition() {
				@Override
				protected boolean matchesChar() {
					return (!isWhitespace() && BasicHeuristicTokenScanner.this.ch != '\r' && BasicHeuristicTokenScanner.this.ch != '\n');
				}
			};
			this.nonWSorLRCondition= nonWSorLRCondition;
		}
		return nonWSorLRCondition;
	}
	
	/**
	 * Configures the scanner for the given document
	 * and the given partition type as partition constraint
	 * 
	 * @param document the document to scan
	 * @param partition the partition to scan in
	 */
	@Override
	public void configure(final IDocument document, final String partitionType) {
		assert (document != null && partitionType != null);
		this.document= document;
		this.partitionConstraint= new PartitionConstraint() {
			@Override
			public boolean matches(final String partitionTypeToTest) {
				return partitionType == partitionTypeToTest;
			}
		};
	}
	
	/**
	 * Configures the scanner for the given document
	 * and no partition constraint
	 * 
	 * @param document the document to scan
	 */
	public void configure(final IDocument document) {
		assert (document != null);
		this.document= document;
		this.partitionConstraint= ALL_PARTITIONS_CONSTRAINT;
	}
	
	/**
	 * Configures the scanner for the given document
	 * and the partition constraint for default partitions
	 * 
	 * @param document the document to scan
	 */
	public void configureDefaultPartitions(final IDocument document) {
		assert (document != null);
		this.document= document;
		this.partitionConstraint= getDefaultPartitionConstraint();
	}
	
	/**
	 * Configures the scanner for the given document
	 * and the given partition constraint
	 * 
	 * @param document the document to scan
	 * @param partition the partition to scan in
	 */
	public void configure(final IDocument document, final PartitionConstraint partitionConstraint) {
		assert (document != null && partitionConstraint != null);
		this.document= document;
		this.partitionConstraint= partitionConstraint;
	}
	
//	public void configure(IDocument document, int offset) throws BadLocationException {
//		configure(document, TextUtilities.getContentType(
//				document, partitioning, offset, false));
//	}
	
	
	/**
	 * Returns the most recent internal scan position.
	 * 
	 * @return the most recent internal scan position.
	 */
	public int getPosition() {
		return this.pos;
	}
	
	
	protected StopCondition createFindPeerStopCondition(final int start, final char[] pair, final char escapeChar) {
		return (escapeChar == (char)0) ?
				new CharacterMatchCondition(pair) : new ExtCharacterMatchCondition(pair, escapeChar);
	}
	
	protected int createForwardBound(final int start) throws BadLocationException {
		return this.document.getLength();
	}
	
	protected int createBackwardBound(final int start) throws BadLocationException {
		return -1;
	}
	
	@Override
	public int findClosingPeer(final int start, final char[] pair) {
		return findClosingPeer(start, pair, (char)0);
	}
	
	@Override
	public int findClosingPeer(int start, final char[] pair, final char escapeChar) {
		Assert.isNotNull(this.document);
		Assert.isTrue(start >= 0);
		
		try {
			final StopCondition cond= createFindPeerStopCondition(start, pair, escapeChar);
			final int bound= createForwardBound(start);
			
			int depth= 1;
			start-= 1;
			while (true) {
				start= scanForward(start + 1, bound, cond);
				if (start == NOT_FOUND) {
					return NOT_FOUND;
				}
				
				if (this.ch == pair[OPENING_PEER]) {
					depth++;
				} else {
					depth--;
				}
				
				if (depth == 0) {
					return start;
				}
			}
			
		}
		catch (final BadLocationException e) {
			return NOT_FOUND;
		}
	}
	
	@Override
	public int findOpeningPeer(int start, final char[] pair) {
		if (start >= this.document.getLength()) {
			start= this.document.getLength()-1;
		}
		try {
			final StopCondition cond= createFindPeerStopCondition(start, pair, (char)0);
			final int bound= createBackwardBound(start);
			
			int depth= 1;
			start+= 1;
			while (true) {
				start= scanBackward(start - 1, bound, cond);
				if (start == NOT_FOUND) {
					return NOT_FOUND;
				}
				
				if (this.ch == pair[CLOSING_PEER]) {
					depth++;
				} else {
					depth--;
				}
				
				if (depth == 0) {
					return start;
				}
			}
			
		}
		catch (final BadLocationException e) {
			return NOT_FOUND;
		}
	}
	
	@Override
	public int findOpeningPeer(int start, final char[] pair, final char escapeChar) {
		Assert.isTrue(start < this.document.getLength());
		if (escapeChar == (char)0) {
			return findOpeningPeer(start, pair);
		}
		
		try {
			final StopCondition cond= createFindPeerStopCondition(start, pair, escapeChar);
			final int bound= createBackwardBound(start);
			
			int depth= 1;
			start+= 1;
			this.line= this.document.getLineOfOffset(start);
			while (true) {
				final int[] list= preScanBackward(start - 1, bound, cond);
				if (list == null) {
					return NOT_FOUND;
				}
				
				for (int i= list.length-1; i >= 0; i--) {
					start= list[i];
					if (this.document.getChar(start) == pair[CLOSING_PEER]) {
						depth++;
					} else {
						depth--;
					}
					
					if (depth == 0) {
						return start;
					}
				}
				start= this.document.getLineOffset(this.line+1);
			}
			
		}
		catch (final BadLocationException e) {
			return NOT_FOUND;
		}
	}
	
	public int computePairBalance(int backwardOffset, final int backwardBound,
			int forwardOffset, final int forwardBound, final int initial,
			final char[] pair, final char escapeChar) {
		int balance= 0;
		final StopCondition condition= createFindPeerStopCondition(forwardBound, pair, escapeChar);
		
		ITER_BACKWARD : while (--backwardOffset >= 0) {
			backwardOffset= scanBackward(backwardOffset, backwardBound, condition);
			if (backwardOffset != NOT_FOUND) {
				if (this.ch == pair[OPENING_PEER]) {
					balance++;
				}
				else {
					balance--;
				}
			}
			else {
				break ITER_BACKWARD;
			}
		}
		if (balance < 0) {
			balance= 0;
		}
		balance+= initial;
		
		ITER_FORWARD : while (forwardOffset < forwardBound) {
			forwardOffset= scanForward(forwardOffset, forwardBound, condition);
			if (forwardOffset != NOT_FOUND) {
				if (this.ch == pair[OPENING_PEER]) {
					balance++;
				}
				else {
					balance--;
				}
				if (balance == 0) {
					break ITER_FORWARD;
				}
				forwardOffset++;
			}
			else {
				break ITER_FORWARD;
			}
		}
		return balance;
	}
	
	
	/**
	 * Finds the smallest position in <code>document</code> such that the position is &gt;= <code>position</code>
	 * and &lt; <code>bound</code> and <code>Character.isWhitespace(document.getChar(pos))</code> evaluates to <code>false</code>.
	 * 
	 * @param position the first character position in <code>document</code> to be considered
	 * @param bound the first position in <code>document</code> to not consider any more, with <code>bound</code> &gt; <code>position</code>, or <code>UNBOUND</code>
	 * @return the smallest position of a non-whitespace character in [<code>position</code>, <code>bound</code>), or <code>NOT_FOUND</code> if none can be found
	 */
	public final int findAnyNonBlankForward(final int position, final int bound, final boolean linebreakIsBlank) {
		return scanForward(position, bound, linebreakIsBlank ?
				getAnyNonWSorLRCondition() : getAnyNonWSCondition());
	}
	
	public final int findAnyNonBlankBackward(final int position, final int bound, final boolean linebreakIsBlank) {
		return scanBackward(position-1, bound, linebreakIsBlank ?
				getAnyNonWSorLRCondition() : getAnyNonWSCondition());
	}
	
	public final int findNonBlankForward(final int position, final int bound, final boolean linebreakIsBlank) {
		return scanForward(position, bound, linebreakIsBlank ?
				getNonWSorLRCondition() : getNonWSCondition());
	}
	
	public final int findNonBlankBackward(final int position, final int bound, final boolean linebreakIsBlank) {
		return scanBackward(position-1, bound, linebreakIsBlank ?
				getNonWSorLRCondition() : getNonWSCondition());
	}
	
	public @Nullable IRegion findBlankRegion(final int position, final boolean linebreakIsBlank) {
		return findRegion(position, linebreakIsBlank ?
				getAnyNonWSorLRCondition() : getAnyNonWSCondition());
	}
	
	public boolean isBlankLine(final int position) throws BadLocationException {
		final IRegion line= this.document.getLineInformationOfOffset(position);
		if (line.getLength() > 0) {
			final int nonWhitespace= findAnyNonBlankForward(line.getOffset(), line.getOffset()+line.getLength(), false);
			return (nonWhitespace == NOT_FOUND);
		}
		return true;
	}
	
	public final @Nullable IRegion findCommonWord(final int position) {
		return findRegion(position, new StopCondition() {
			@Override
			public boolean stop() {
				return (!Character.isLetterOrDigit(BasicHeuristicTokenScanner.this.ch));
			}
		});
	}
	
	
	public final int getFirstLineOfRegion(final IRegion region) throws BadLocationException {
		return this.document.getLineOfOffset(region.getOffset());
	}
	
	public final int getLastLineOfRegion(final IRegion region) throws BadLocationException {
		if (region.getLength() == 0) {
			return this.document.getLineOfOffset(region.getOffset());
		}
		return this.document.getLineOfOffset(region.getOffset()+region.getLength()-1);
	}
	
	
	private final int @Nullable [] preScanBackward(final int start, final int bound, final StopCondition condition) throws BadLocationException {
		final IntList list= new IntArrayList();
		int scanEnd= start+1;
		
		NEXT_LINE: while (list.isEmpty() && this.line >= 0) {
			final int lineOffset= this.document.getLineOffset(this.line);
			int next= lineOffset - 1;
			while ((next= scanForward(next + 1, scanEnd, condition)) != NOT_FOUND) {
				if (bound < next) {
					list.add(next);
				}
			}
			
			this.line--;
			if (lineOffset <= bound) {
				break NEXT_LINE;
			}
			
			scanEnd= lineOffset;
		}
		
		if (!list.isEmpty()) {
			return list.toArray();
		}
		return null;
	}
	
	
	/**
	 * Finds the lowest position <code>p</code> in <code>document</code> such that <code>start</code> &lt;= p &lt;
	 * <code>bound</code> and <code>condition.stop(document.getChar(p), p)</code> evaluates to <code>true</code>.
	 * 
	 * @param start the first character position in <code>document</code> to be considered
	 * @param bound the first position in <code>document</code> to not consider any more, with <code>bound</code> &gt; <code>start</code>, or <code>UNBOUND</code>
	 * @param condition the <code>StopCondition</code> to check
	 * @return the lowest position in [<code>start</code>, <code>bound</code>) for which <code>condition</code> holds, or <code>NOT_FOUND</code> if none can be found
	 */
	protected final int scanForward(final int start, int bound, final StopCondition condition) {
		if (bound == UNBOUND) {
			bound= this.document.getLength();
		}
		assert(bound <= this.document.getLength());
		assert(start >= 0);
		
		try {
			this.pos= start;
			while (this.pos < bound) {
				this.ch= this.document.getChar(this.pos);
				if (condition.stop()) {
					return this.pos;
				}
				this.pos= condition.nextPositionForward();
			}
			this.pos= bound;
			this.ch= (this.pos >= 0 && this.pos < this.document.getLength()) ? this.document.getChar(this.pos) : (char) -1;
		}
		catch (final BadLocationException e) {
		}
		return NOT_FOUND;
	}
	
	
	/**
	 * Finds the lowest position in <code>document</code> such that the position is &gt;= <code>position</code>
	 * and &lt; <code>bound</code> and <code>document.getChar(position) == ch</code> evaluates to <code>true</code>
	 * and the position is in the default partition.
	 * 
	 * @param position the first character position in <code>document</code> to be considered
	 * @param bound the first position in <code>document</code> to not consider any more, with <code>bound</code> &gt; <code>position</code>, or <code>UNBOUND</code>
	 * @param ch the <code>char</code> to search for
	 * @return the lowest position of <code>ch</code> in (<code>bound</code>, <code>position</code>] that resides in a Java partition, or <code>NOT_FOUND</code> if none can be found
	 */
	public final int scanForward(final int position, final int bound, final char ch) {
		return scanForward(position, bound, new SingleCharacterMatchCondition(ch));
	}
	
	/**
	 * Finds the lowest position in <code>document</code> such that the position is &gt;= <code>position</code>
	 * and &lt; <code>bound</code> and <code>document.getChar(position) == ch</code> evaluates to <code>true</code> for at least one
	 * ch in <code>chars</code> and the position is in the default partition.
	 * 
	 * @param position the first character position in <code>document</code> to be considered
	 * @param bound the first position in <code>document</code> to not consider any more, with <code>bound</code> &gt; <code>position</code>, or <code>UNBOUND</code>
	 * @param chars an array of <code>char</code> to search for
	 * @return the lowest position of a non-whitespace character in [<code>position</code>, <code>bound</code>) that resides in a Java partition, or <code>NOT_FOUND</code> if none can be found
	 */
	public final int scanForward(final int position, final int bound, final char[] chars) {
		return scanForward(position, bound, new CharacterMatchCondition(chars));
	}
	
	public final int scanForward(final int position, int bound, final String s, final int escapeChar) {
		if (bound == UNBOUND) {
			bound= this.document.getLength();
		}
		bound-= s.length();
		return scanForward(position, bound, new StringMatchCondition(s, escapeChar));
	}
	public final int scanForward(final int position, int bound, final String[] s, final int escapeChar) {
		if (bound == UNBOUND) {
			bound= this.document.getLength();
		}
		bound-= s[0].length();
		return scanForward(position, bound, new StringMatchCondition(s, escapeChar));
	}
	
	/**
	 * Finds the highest position <code>p</code> in <code>document</code> such that <code>bound</code> &lt; <code>p</code> &lt;= <code>start</code>
	 * and <code>condition.stop(document.getChar(p), p)</code> evaluates to <code>true</code>.
	 * 
	 * @param start the first character position in <code>document</code> to be considered
	 * @param bound the first position in <code>document</code> to not consider any more, with <code>bound</code> &lt; <code>start</code>, or <code>UNBOUND</code>
	 * @param condition the <code>StopCondition</code> to check
	 * @return the highest position in (<code>bound</code>, <code>start</code> for which <code>condition</code> holds, or <code>NOT_FOUND</code> if none can be found
	 */
	protected final int scanBackward(final int start, int bound, final StopCondition condition) {
		if (bound == UNBOUND) {
			bound= -1;
		}
		assert(bound >= -1);
//		assert(start == 0 || start < document.getLength() );
		
		try {
			if (this.document.getLength() > 0) {
				this.pos= start;
				while (this.pos > bound) {
					this.ch= this.document.getChar(this.pos);
					if (condition.stop()) {
						return this.pos;
					}
					this.pos= condition.nextPositionBackward();
				}
			}
			this.pos= bound;
			this.ch= (this.pos >= 0 && this.pos < this.document.getLength()) ? this.document.getChar(this.pos) : (char) -1;
		}
		catch (final BadLocationException e) {
		}
		return NOT_FOUND;
	}
	
	/**
	 * Finds the highest position in <code>document</code> such that the position is &lt;= <code>position</code>
	 * and &gt; <code>bound</code> and <code>document.getChar(position) == ch</code> evaluates to <code>true</code> for at least one
	 * ch in <code>chars</code> and the position is in the default partition.
	 * 
	 * @param position the first character position in <code>document</code> to be considered
	 * @param bound the first position in <code>document</code> to not consider any more, with <code>bound</code> &lt; <code>position</code>, or <code>UNBOUND</code>
	 * @param ch the <code>char</code> to search for
	 * @return the highest position of one element in <code>chars</code> in (<code>bound</code>, <code>position</code>] that resides in a Java partition, or <code>NOT_FOUND</code> if none can be found
	 */
	public final int scanBackward(final int position, final int bound, final char ch) {
		return scanBackward(position, bound, new SingleCharacterMatchCondition(ch));
	}
	
	/**
	 * Finds the highest position in <code>document</code> such that the position is &lt;= <code>position</code>
	 * and &gt; <code>bound</code> and <code>document.getChar(position) == ch</code> evaluates to <code>true</code> for at least one
	 * ch in <code>chars</code> and the position is in the default partition.
	 * 
	 * @param position the first character position in <code>document</code> to be considered
	 * @param bound the first position in <code>document</code> to not consider any more, with <code>bound</code> &lt; <code>position</code>, or <code>UNBOUND</code>
	 * @param chars an array of <code>char</code> to search for
	 * @return the highest position of one element in <code>chars</code> in (<code>bound</code>, <code>position</code>] that resides in a Java partition, or <code>NOT_FOUND</code> if none can be found
	 */
	public final int scanBackward(final int position, final int bound, final char[] chars) {
		return scanBackward(position, bound, new CharacterMatchCondition(chars));
	}
	
	
	public final int count(int start, final int stop, final char c) {
		int count= 0;
		final SingleCharacterMatchCondition condition= new SingleCharacterMatchCondition(c);
		while (start < stop && (start= scanForward(start, stop, condition)) != NOT_FOUND) {
			count++;
			start++;
		}
		return count;
	}
	
	
	protected final @Nullable IRegion findRegion(final int position, final StopCondition condition) {
		return findRegion(position, condition, false);
	}
	
	protected final @Nullable IRegion findRegion(final int position, final StopCondition condition, final boolean allowClosing) {
		int start= position;
		int end= scanForward(position, UNBOUND, condition);
		if (end == NOT_FOUND) {
			end= this.pos;
		}
		if (allowClosing || end > position) {
			start= scanBackward(--start, UNBOUND, condition);
			if (start == NOT_FOUND) {
				start= this.pos;
			}
			start++;
		}
		if (start < end) {
			return new Region(start, end-start);
		}
		return null;
	}
	
	/**
	 * Returns the partition at <code>position</code>.
	 * 
	 * @param position the position to get the partition for
	 * @return the content type at <code>position</code> or a dummy zero-length
	 *     partition if accessing the document fails
	 */
	protected final @Nullable String getContentType() {
		try {
			return TextUtilities.getContentType(this.document, this.partitioning, this.pos, false);
		}
		catch (final BadLocationException e) {
			return null; // ?
		}
	}
	
	/**
	 * Returns the partition at current position of the scanner (#fPos).
	 * 
	 * @param position the position to get the partition for
	 * @return the partition at <code>position</code> or a dummy zero-length
	 *     partition if accessing the document fails
	 */
	protected final ITypedRegion getPartition() {
		try {
			return TextUtilities.getPartition(this.document, this.partitioning, this.pos, false);
		}
		catch (final BadLocationException e) {
			return new TypedRegion(this.pos, 0, "__no_partition_at_all"); //$NON-NLS-1$
		}
	}
	
	/**
	 * Returns the partition at <code>position</code>.
	 * 
	 * @param position the position to get the partition for
	 * @return the partition at <code>position</code> or a dummy zero-length
	 *     partition if accessing the document fails
	 */
	public final ITypedRegion getPartition(final int position) {
		try {
			return TextUtilities.getPartition(this.document, this.partitioning, position, false);
		}
		catch (final BadLocationException e) {
			return new TypedRegion(this.pos, 0, "__no_partition_at_all"); //$NON-NLS-1$
		}
	}
	
}
