/*******************************************************************************
 * Copyright (c) 2006, 2012 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Christian Plesner Hansen (plesner@quenta.org) - initial API and implementation
 *******************************************************************************/
package org.eclipse.jface.text.source;
import org.eclipse.core.runtime.Assert;

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.Region;
import org.eclipse.jface.text.TextUtilities;

/**
 * A character pair matcher that matches a specified set of character
 * pairs against each other.  Only characters that occur in the same
 * partitioning are matched.
 *
 * @since 3.3
 */
public class DefaultCharacterPairMatcher implements ICharacterPairMatcher, ICharacterPairMatcherExtension {

	private int fAnchor= -1;
	private final CharPairs fPairs;
	private final String fPartitioning;
	private final boolean fCaretEitherSideOfBracket;

	/**
	 * Creates a new character pair matcher that matches the specified characters within the
	 * specified partitioning. The specified list of characters must have the form <blockquote>{
	 * <i>start</i>, <i>end</i>, <i>start</i>, <i>end</i>, ..., <i>start</i>, <i>end</i>
	 * }</blockquote> For instance:
	 *
	 * <pre>
	 * char[] chars = new char[] {'(', ')', '{', '}', '[', ']'};
	 * new DefaultCharacterPairMatcher(chars, ...);
	 * </pre>
	 *
	 * @param chars a list of characters
	 * @param partitioning the partitioning to match within
	 */
	public DefaultCharacterPairMatcher(char[] chars, String partitioning) {
		this(chars, partitioning, false);
	}

	/**
	 * Creates a new character pair matcher that matches the specified characters within the
	 * specified partitioning. The specified list of characters must have the form <blockquote>{
	 * <i>start</i>, <i>end</i>, <i>start</i>, <i>end</i>, ..., <i>start</i>, <i>end</i>
	 * }</blockquote> For instance:
	 *
	 * <pre>
	 * char[] chars = new char[] {'(', ')', '{', '}', '[', ']'};
	 * new DefaultCharacterPairMatcher(chars, ...);
	 * </pre>
	 *
	 * @param chars a list of characters
	 * @param partitioning the partitioning to match within
	 * @param caretEitherSideOfBracket controls the matching behavior. When <code>true</code>, the
	 *            matching peer will be found when the caret is placed either before or after a
	 *            character. When <code>false</code>, the matching peer will be found only when the
	 *            caret is placed after a character.
	 * @since 3.8
	 */
	public DefaultCharacterPairMatcher(char[] chars, String partitioning, boolean caretEitherSideOfBracket) {
		Assert.isLegal(chars.length % 2 == 0);
		Assert.isNotNull(partitioning);
		fPairs= new CharPairs(chars);
		fPartitioning= partitioning;
		fCaretEitherSideOfBracket= caretEitherSideOfBracket;
	}

	/**
	 * Creates a new character pair matcher that matches characters within the default partitioning.
	 * The specified list of characters must have the form <blockquote>{ <i>start</i>, <i>end</i>,
	 * <i>start</i>, <i>end</i>, ..., <i>start</i>, <i>end</i> }</blockquote> For instance:
	 *
	 * <pre>
	 * char[] chars= new char[] { '(', ')', '{', '}', '[', ']' };
	 * new DefaultCharacterPairMatcher(chars);
	 * </pre>
	 *
	 * @param chars a list of characters
	 */
	public DefaultCharacterPairMatcher(char[] chars) {
		this(chars, IDocumentExtension3.DEFAULT_PARTITIONING);
	}

	@Override
	public IRegion match(IDocument doc, int offset) {
		if (doc == null || offset < 0 || offset > doc.getLength()) return null;
		try {
			return performMatch(doc, offset);
		} catch (BadLocationException ble) {
			return null;
		}
	}

	/**
	 * @see org.eclipse.jface.text.source.ICharacterPairMatcherExtension#match(org.eclipse.jface.text.IDocument,
	 *      int, int)
	 * @since 3.8
	 */
	@Override
	public IRegion match(IDocument document, int offset, int length) {
		if (document == null || offset < 0 || offset > document.getLength() || Math.abs(length) > 1)
			return null;

		try {
			int sourceCaretOffset= offset + length;
			if (Math.abs(length) == 1) {
				char ch= length > 0 ? document.getChar(offset) : document.getChar(sourceCaretOffset);
				if (!fPairs.contains(ch))
					return null;
			}
			int adjustment= getOffsetAdjustment(document, sourceCaretOffset, length);
			sourceCaretOffset+= adjustment;
			return match(document, sourceCaretOffset);
		} catch (BadLocationException e) {
			return null;
		}
	}

	/**
	 * @see org.eclipse.jface.text.source.ICharacterPairMatcherExtension#findEnclosingPeerCharacters(org.eclipse.jface.text.IDocument,
	 *      int, int)
	 * @since 3.8
	 */
	@Override
	public IRegion findEnclosingPeerCharacters(IDocument document, int offset, int length) {
		if (document == null || offset < 0 || offset > document.getLength())
			return null;

		//maybe a bracket is selected
		IRegion region= match(document, offset, length);
		fAnchor= ICharacterPairMatcher.LEFT; //always set the anchor to LEFT
		if (region != null) {
			return region;
		}

		//bracket is not selected
		try {
			final String partition= TextUtilities.getContentType(document, fPartitioning, offset, false);
			DocumentPartitionAccessor partDoc= new DocumentPartitionAccessor(document, fPartitioning, partition);
			IRegion enclosingPeers= findEnclosingPeers(document, partDoc, offset, length, 0, document.getLength());
			if (enclosingPeers != null)
				return enclosingPeers;
			partDoc= new DocumentPartitionAccessor(document, fPartitioning, IDocument.DEFAULT_CONTENT_TYPE);
			return findEnclosingPeers(document, partDoc, offset, length, 0, document.getLength());
		} catch (BadLocationException ble) {
			fAnchor= -1;
			return null;
		}
	}

	/**
	 * @see org.eclipse.jface.text.source.ICharacterPairMatcherExtension#isMatchedChar(char)
	 * @since 3.8
	 */
	@Override
	public boolean isMatchedChar(char ch) {
		return fPairs.contains(ch);
	}

	/**
	 * @see org.eclipse.jface.text.source.ICharacterPairMatcherExtension#isMatchedChar(char,
	 *      org.eclipse.jface.text.IDocument, int)
	 * @since 3.8
	 */
	@Override
	public boolean isMatchedChar(char ch, IDocument document, int offset) {
		return isMatchedChar(ch);
	}

	/**
	 * @see org.eclipse.jface.text.source.ICharacterPairMatcherExtension#isRecomputationOfEnclosingPairRequired(org.eclipse.jface.text.IDocument,
	 *      org.eclipse.jface.text.IRegion, org.eclipse.jface.text.IRegion)
	 * @since 3.8
	 */
	@Override
	public boolean isRecomputationOfEnclosingPairRequired(IDocument document, IRegion currentSelection, IRegion previousSelection) {
		int previousStartOffset= previousSelection.getOffset();
		int currentStartOffset= currentSelection.getOffset();
		int previousEndOffset= previousStartOffset + previousSelection.getLength();
		int currentEndOffset= currentStartOffset + currentSelection.getLength();

		try {
			String prevEndContentType= TextUtilities.getContentType(document, fPartitioning, previousEndOffset, false);
			String currEndContentType= TextUtilities.getContentType(document, fPartitioning, currentEndOffset, false);
			if (!prevEndContentType.equals(currEndContentType))
				return true;

			String prevStartContentType= TextUtilities.getContentType(document, fPartitioning, previousStartOffset, true);
			String currStartContentType= TextUtilities.getContentType(document, fPartitioning, currentStartOffset, true);
			if (!prevStartContentType.equals(currStartContentType))
				return true;

			int start;
			int end;
			if (currentEndOffset > previousEndOffset) {
				start= previousEndOffset;
				end= currentEndOffset;
			} else {
				start= currentEndOffset;
				end= previousEndOffset;
			}
			for (int i= Math.max(start - 1, 0); i <= end; i++) {
				if (isMatchedChar(document.getChar(i))) {
					return true;
				}
			}

			if (currentStartOffset > previousStartOffset) {
				start= previousStartOffset;
				end= currentStartOffset;
			} else {
				start= currentStartOffset;
				end= previousStartOffset;
			}
			for (int i= Math.max(start - 1, 0); i <= end; i++) {
				if (isMatchedChar(document.getChar(i))) {
					return true;
				}
			}
		} catch (BadLocationException e) {
			//do nothing
		}
		return false;
	}

	/**
	 * Computes the adjustment in the start offset for the purpose of finding a matching peer. This
	 * is required as the direction of selection can be right-to-left or left-to-right.
	 *
	 * @param document the document to work on
	 * @param offset the start offset
	 * @param length the selection length
	 * @return the start offset adjustment which can be -1, 0 or +1
	 * @since 3.8
	 */
	private int getOffsetAdjustment(IDocument document, int offset, int length) {
		if (length == 0 || Math.abs(length) > 1 || offset >= document.getLength())
			return 0;
		try {
			if (length < 0) {
				if (fPairs.isStartCharacter(document.getChar(offset))) {
					return 1;
				}
			} else {
				if (fCaretEitherSideOfBracket && fPairs.isEndCharacter(document.getChar(offset - 1))) {
					return -1;
				}
			}
		} catch (BadLocationException e) {
			//do nothing
		}
		return 0;
	}

	/*
	 * Performs the actual work of matching for #match(IDocument, int).
	 */
	private IRegion performMatch(IDocument doc, int caretOffset) throws BadLocationException {
		char prevChar= (caretOffset - 1 >= 0) ? doc.getChar(caretOffset - 1) : Character.MIN_VALUE;
		boolean isForward;
		final char ch;
		if (fCaretEitherSideOfBracket) {
			char currChar= (caretOffset != doc.getLength()) ? doc.getChar(caretOffset) : Character.MIN_VALUE;
			if (fPairs.isEndCharacter(prevChar) && !fPairs.isEndCharacter(currChar)) { //https://bugs.eclipse.org/bugs/show_bug.cgi?id=372516
				caretOffset--;
				currChar= prevChar;
				prevChar= doc.getChar(Math.max(caretOffset - 1, 0));
			} else if (fPairs.isStartCharacter(currChar) && !fPairs.contains(prevChar)) {
				caretOffset++;
				prevChar= currChar;
				currChar= doc.getChar(caretOffset);
			}

			isForward= fPairs.contains(prevChar) && fPairs.isStartCharacter(prevChar);
			boolean isBackward= fPairs.contains(currChar) && !fPairs.isStartCharacter(currChar);
			if (!isForward && !isBackward) {
				return null;
			}
			ch= isForward ? prevChar : currChar;
		} else {
			if (!fPairs.contains(prevChar))
				return null;
			isForward= fPairs.isStartCharacter(prevChar);
			ch= prevChar;
		}

		fAnchor= isForward ? ICharacterPairMatcher.LEFT : ICharacterPairMatcher.RIGHT;
		final int searchStartPosition= isForward ? caretOffset : (fCaretEitherSideOfBracket ? caretOffset - 1 : caretOffset - 2);
		final int adjustedOffset= isForward ? caretOffset - 1 : (fCaretEitherSideOfBracket ? caretOffset + 1 : caretOffset);
		final String partition= TextUtilities.getContentType(doc, fPartitioning, ((!isForward && fCaretEitherSideOfBracket) ? caretOffset : Math.max(caretOffset - 1, 0)), false);
		final DocumentPartitionAccessor partDoc= new DocumentPartitionAccessor(doc, fPartitioning, partition);
		int endOffset= findMatchingPeer(partDoc, ch, fPairs.getMatching(ch),
				isForward, isForward ? doc.getLength() : -1, searchStartPosition);
		if (endOffset == -1)
			return null;
		final int adjustedEndOffset= isForward ? endOffset + 1 : endOffset;
		if (adjustedEndOffset == adjustedOffset)
			return null;
		return new Region(Math.min(adjustedOffset, adjustedEndOffset),
				Math.abs(adjustedEndOffset - adjustedOffset));
	}

	/**
	 * Searches <code>doc</code> for the specified end character, <code>end</code>.
	 *
	 * @param doc the document to search
	 * @param start the opening matching character
	 * @param end the end character to search for
	 * @param searchForward search forwards or backwards?
	 * @param boundary a boundary at which the search should stop
	 * @param startPos the start offset
	 * @return the index of the end character if it was found, otherwise -1
	 * @throws BadLocationException if the document is accessed with invalid offset or line
	 */
	private int findMatchingPeer(DocumentPartitionAccessor doc, char start, char end, boolean searchForward, int boundary, int startPos) throws BadLocationException {
		int pos= startPos;
		int nestingLevel= 0;
		while (pos != boundary) {
			final char c= doc.getChar(pos);
			if (c == end && doc.inPartition(pos)) {
				if (nestingLevel == 0)
					return pos;
				nestingLevel--;
			} else if (c == start && doc.inPartition(pos)) {
				nestingLevel++;
			}
			pos= doc.getNextPosition(pos, searchForward);
		}
		return -1;
	}

	/*
	 * Performs the actual work of finding enclosing peer characters for #findEnclosingPeerCharacters(IDocument, int, int).
	 */
	private IRegion findEnclosingPeers(IDocument document, DocumentPartitionAccessor doc, int offset, int length, int lowerBoundary, int upperBoundary) throws BadLocationException {
		char[] pairs= fPairs.fPairs;

		int start;
		int end;
		if (length >= 0) {
			start= offset;
			end= offset + length;
		} else {
			end= offset;
			start= offset + length;
		}

		boolean lowerFound= false;
		boolean upperFound= false;
		int[][] counts= new int[pairs.length][2];
		char currChar= (start != document.getLength()) ? doc.getChar(start) : Character.MIN_VALUE;
		int pos1;
		int pos2;
		if (fPairs.isEndCharacter(currChar)) {
			pos1= doc.getNextPosition(start, false);
			pos2= start;
		} else {
			pos1= start;
			pos2= doc.getNextPosition(start, true);
		}

		while ((pos1 >= lowerBoundary && !lowerFound) || (pos2 < upperBoundary && !upperFound)) {
			for (int i= 0; i < counts.length; i++) {
				counts[i][0]= counts[i][1]= 0;
			}

			outer1: while (pos1 >= lowerBoundary && !lowerFound) {
				final char c= doc.getChar(pos1);
				int i= getCharacterIndex(c, document, pos1);
				if (i != -1 && doc.inPartition(pos1)) {
					if (i % 2 == 0) {
						counts[i / 2][0]--; //start
					} else {
						counts[i / 2][0]++; //end
					}
					for (int j= 0; j < counts.length; j++) {
						if (counts[j][0] == -1) {
							lowerFound= true;
							break outer1;
						}
					}
				}
				pos1= doc.getNextPosition(pos1, false);
			}

			outer2: while (pos2 < upperBoundary && !upperFound) {
				final char c= doc.getChar(pos2);
				int i= getCharacterIndex(c, document, pos2);
				if (i != -1 && doc.inPartition(pos2)) {
					if (i % 2 == 0) {
						counts[i / 2][1]++; //start
					} else {
						counts[i / 2][1]--; //end
					}
					for (int j= 0; j < counts.length; j++) {
						if (counts[j][1] == -1 && counts[j][0] == -1) {
							upperFound= true;
							break outer2;
						}
					}
				}
				pos2= doc.getNextPosition(pos2, true);
			}

			if (pos1 > start || pos2 < end - 1) {
				//match inside selection => discard
				pos1= doc.getNextPosition(pos1, false);
				pos2= doc.getNextPosition(pos2, true);
				lowerFound= false;
				upperFound= false;
			}
		}
		pos2++;
		if (pos1 < lowerBoundary || pos2 > upperBoundary)
			return null;
		return new Region(pos1, pos2 - pos1);
	}

	/**
	 * Determines the index of the character in the char array passed to the constructor of the pair
	 * matcher.
	 *
	 * @param ch the character
	 * @param document the document
	 * @param offset the offset in document
	 * @return the index of the character in the char array passed to the constructor of the pair
	 *         matcher, and -1 if the character is not one of the matched characters
	 * @since 3.8
	 */
	private int getCharacterIndex(char ch, IDocument document, int offset) {
		char[] pairs= fPairs.fPairs;
		for (int i= 0; i < pairs.length; i++) {
			if (pairs[i] == ch && isMatchedChar(ch, document, offset)) {
				return i;
			}
		}
		return -1;
	}

	@Override
	public int getAnchor() {
		return fAnchor;
	}

	@Override
	public void dispose() { }

	@Override
	public void clear() {
		fAnchor= -1;
	}

	/**
	 * Utility class that wraps a document and gives access to
	 * partitioning information.  A document is tied to a particular
	 * partition and, when considering whether or not a position is a
	 * valid match, only considers position within its partition.
	 */
	private static class DocumentPartitionAccessor {

		private final IDocument fDocument;
		private final String fPartitioning, fPartition;
		private ITypedRegion fCachedPartition;
		private int fLength;

		/**
		 * Creates a new partitioned document for the specified document.
		 *
		 * @param doc the document to wrap
		 * @param partitioning the partitioning used
		 * @param partition the partition managed by this document
		 */
		public DocumentPartitionAccessor(IDocument doc, String partitioning,
				String partition) {
			fDocument= doc;
			fPartitioning= partitioning;
			fPartition= partition;
			fLength= doc.getLength();
		}

		/**
		 * Returns the character at the specified position in this document.
		 *
		 * @param pos an offset within this document
		 * @return the character at the offset
		 * @throws BadLocationException if the offset is invalid in this document
		 */
		public char getChar(int pos) throws BadLocationException {
			return fDocument.getChar(pos);
		}

		/**
		 * Returns true if the specified offset is within the partition
		 * managed by this document.
		 *
		 * @param pos an offset within this document
		 * @return true if the offset is within this document's partition
		 */
		public boolean inPartition(int pos) {
			final ITypedRegion partition= getPartition(pos);
			return partition != null && partition.getType().equals(fPartition);
		}

		/**
		 * Returns the next position to query in the search. The position
		 * is not guaranteed to be in this document's partition.
		 *
		 * @param pos an offset within the document
		 * @param searchForward the direction of the search
		 * @return the next position to query
		 */
		public int getNextPosition(int pos, boolean searchForward) {
			final ITypedRegion partition= getPartition(pos);
			if (partition == null || fPartition.equals(partition.getType()))
				return simpleIncrement(pos, searchForward);
			if (searchForward) {
				int end= partition.getOffset() + partition.getLength();
				if (pos < end)
					return end;
			} else {
				int offset= partition.getOffset();
				if (pos > offset)
					return offset - 1;
			}
			return simpleIncrement(pos, searchForward);
		}

		private int simpleIncrement(int pos, boolean searchForward) {
			return pos + (searchForward ? 1 : -1);
		}

		/**
		 * Returns partition information about the region containing the
		 * specified position.
		 *
		 * @param pos a position within this document.
		 * @return positioning information about the region containing the
		 *   position
		 */
		private ITypedRegion getPartition(int pos) {
			if (fCachedPartition == null || !contains(fCachedPartition, pos)) {
				Assert.isTrue(pos >= 0 && pos <= fLength);
				try {
					fCachedPartition= TextUtilities.getPartition(fDocument, fPartitioning, pos, false);
				} catch (BadLocationException e) {
					fCachedPartition= null;
				}
			}
			return fCachedPartition;
		}

		private static boolean contains(IRegion region, int pos) {
			int offset= region.getOffset();
			return offset <= pos && pos < offset + region.getLength();
		}

	}

	/**
	 * Utility class that encapsulates access to matching character pairs.
	 */
	private static class CharPairs {

		private final char[] fPairs;

		public CharPairs(char[] pairs) {
			fPairs= pairs;
		}

		/**
		 * Returns true if the specified character occurs in one of the character pairs.
		 *
		 * @param c a character
		 * @return true exactly if the character occurs in one of the pairs
		 */
		public boolean contains(char c) {
			char[] pairs= fPairs;
			for (char pair : pairs) {
				if (c == pair)
					return true;
			}
			return false;
		}

		/**
		 * Returns true if the specified character opens a character pair
		 * when scanning in the specified direction.
		 *
		 * @param c a character
		 * @param searchForward the direction of the search
		 * @return whether or not the character opens a character pair
		 */
		public boolean isOpeningCharacter(char c, boolean searchForward) {
			for (int i= 0; i < fPairs.length; i += 2) {
				if (searchForward && getStartChar(i) == c) return true;
				else if (!searchForward && getEndChar(i) == c) return true;
			}
			return false;
		}

		/**
		 * Returns true if the specified character is a start character.
		 *
		 * @param c a character
		 * @return true exactly if the character is a start character
		 */
		public boolean isStartCharacter(char c) {
			return this.isOpeningCharacter(c, true);
		}

		/**
		 * Returns true if the specified character is an end character.
		 *
		 * @param c a character
		 * @return true exactly if the character is an end character
		 * @since 3.8
		 */
		public boolean isEndCharacter(char c) {
			return this.isOpeningCharacter(c, false);
		}

		/**
		 * Returns the matching character for the specified character.
		 *
		 * @param c a character occurring in a character pair
		 * @return the matching character
		 */
		public char getMatching(char c) {
			for (int i= 0; i < fPairs.length; i += 2) {
				if (getStartChar(i) == c) return getEndChar(i);
				else if (getEndChar(i) == c) return getStartChar(i);
			}
			Assert.isTrue(false);
			return '\0';
		}

		private char getStartChar(int i) {
			return fPairs[i];
		}

		private char getEndChar(int i) {
			return fPairs[i + 1];
		}

	}

}
