/*=============================================================================#
 # Copyright (c) 2011, 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.jface.text.BadLocationException;


public abstract class CharCodepointIterator implements ICodepointIterator {
	
	
	private static final byte PREPARE_STEPBACK= (PREPARE_BACKWARD | PREPARE_FIX);
	
	
	private static class StringIterator extends CharCodepointIterator {
		
		
		private final String fString;
		
		private final int fStringOffset;
		
		
		public StringIterator(final String string, final int stringIndex,
				final int beginIndex, final int endIndex) throws BadLocationException {
			super(beginIndex, endIndex);
			this.fString= string;
			this.fStringOffset= stringIndex;
		}
		
		
		@Override
		protected char getChar(final int offset, final byte prepare) {
			return this.fString.charAt(offset - this.fStringOffset);
		}
		
		
		@Override
		public String toString() {
			return this.fString.substring(getBeginIndex() - this.fStringOffset, getEndIndex() - this.fStringOffset);
		}
		
	}
	
	private static class CharArrayIterator extends CharCodepointIterator {
		
		
		private final char[] fArray;
		
		private final int fArrayOffset;
		
		
		public CharArrayIterator(final char[] array, final int arrayIndex,
				final int beginIndex, final int endIndex) throws BadLocationException {
			super(beginIndex, endIndex);
			this.fArray= array;
			this.fArrayOffset= arrayIndex;
		}
		
		
		@Override
		protected char getChar(final int offset, final byte prepare) {
			return this.fArray[offset - this.fArrayOffset];
		}
		
		
		@Override
		public String toString() {
			return new String(this.fArray, getBeginIndex() - this.fArrayOffset, getEndIndex() - getBeginIndex());
		}
		
	}
	
	
	/**
	 * Creates a new iterator for a string.
	 * 
	 * @param string the string
	 * @param stringIndex the offset of the string in the document
	 * @param beginIndex the begin index of the iterator in the document
	 * @param endIndex the end index of the iterator in the document
	 * @throws BadLocationException if an index is not valid
	 */
	public static CharCodepointIterator create(final String string, final int stringIndex,
			final int beginIndex, final int endIndex)
			throws BadLocationException {
		if (beginIndex > endIndex
				|| beginIndex < stringIndex || endIndex > stringIndex + string.length()) {
			throw new BadLocationException();
		}
		return new StringIterator(string, stringIndex, beginIndex, endIndex);
	}
	
	/**
	 * Creates a new iterator for a char array.
	 * 
	 * @param array the char array
	 * @param arrayIndex the offset of the array in the document
	 * @param beginIndex the begin index of the iterator in the document
	 * @param endIndex the end index of the iterator in the document
	 * @throws BadLocationException if an index is not valid
	 */
	public static CharCodepointIterator create(final char[] array, final int arrayIndex,
			final int beginIndex, final int endIndex)
			throws BadLocationException {
		if (beginIndex > endIndex
				|| beginIndex < arrayIndex || endIndex > arrayIndex + array.length) {
			throw new BadLocationException();
		}
		return new CharArrayIterator(array, arrayIndex, beginIndex, endIndex);
	}
	
	
	private final int fBeginIndex;
	private final int fEndIndex;
	
	private int fCurrentIndex;
	private int fCurrentCodepoint;
	private int fCurrentCharLength;
	
	
	protected CharCodepointIterator(final int beginIndex, final int endIndex) {
		this.fBeginIndex= beginIndex;
		this.fEndIndex= endIndex;
	}
	
	
	protected abstract char getChar(int index, byte prepare);
	
	
	@Override
	public final int first() {
		internalSet(this.fBeginIndex, PREPARE_FORWARD);
		return this.fCurrentCodepoint;
	}
	
	@Override
	public final int last() {
		internalSet((this.fBeginIndex < this.fEndIndex) ? this.fEndIndex - 1 : this.fEndIndex, PREPARE_STEPBACK);
		return this.fCurrentCodepoint;
	}
	
	@Override
	public final int current() {
		return this.fCurrentCodepoint;
	}
	
	@Override
	public final int next() {
		if (this.fCurrentIndex < this.fEndIndex) {
			internalSet(this.fCurrentIndex + this.fCurrentCharLength, PREPARE_FORWARD);
			return this.fCurrentCodepoint;
		}
		else {
			return EOF;
		}
	}
	
	public final int next(int count) {
		while (count > 0 && this.fCurrentIndex < this.fEndIndex) {
			internalSet(this.fCurrentIndex + this.fCurrentCharLength, PREPARE_FORWARD);
			count--;
		}
		return (count == 0) ? this.fCurrentCodepoint : EOF;
	}
	
	@Override
	public final int previous() {
		if (this.fCurrentIndex > this.fBeginIndex) {
			internalSet(this.fCurrentIndex - 1, PREPARE_STEPBACK);
			return this.fCurrentCodepoint;
		}
		else {
			return EOF;
		}
	}
	
	public final int previous(int count) {
		while (count > 0 && this.fCurrentIndex > this.fBeginIndex) {
			internalSet(this.fCurrentIndex - 1, PREPARE_STEPBACK);
			count--;
		}
		return (count == 0) ? this.fCurrentCodepoint : EOF;
	}
	
	@Override
	public void setIndex(final int index, final byte prepare) throws BadLocationException {
		if (index < this.fBeginIndex || index > this.fEndIndex) {
			throw new BadLocationException();
		}
		internalSet(index, prepare);
	}
	
	private final void internalSet(final int index, final byte prepare) {
		this.fCurrentIndex= index;
		if (this.fCurrentIndex < this.fEndIndex) {
			final char c= getChar(this.fCurrentIndex, prepare);
			char c2;
			if ((prepare & PREPARE_FIX) != 0 && Character.isLowSurrogate(c)
					&& this.fCurrentIndex > this.fBeginIndex
					&& Character.isHighSurrogate(c2= getChar(this.fCurrentIndex-1, prepare)) ) {
				this.fCurrentIndex--;
				this.fCurrentCodepoint= Character.toCodePoint(c2, c);
				this.fCurrentCharLength= 2;
			}
			else if (Character.isHighSurrogate(c)
					&& (this.fCurrentIndex+1 < this.fEndIndex
					&& Character.isLowSurrogate((c2= getChar(this.fCurrentIndex+1, prepare)) ))) {
				this.fCurrentCodepoint= Character.toCodePoint(c, c2);
				this.fCurrentCharLength= 2;
			}
			else {
				this.fCurrentCodepoint= c;
				this.fCurrentCharLength= 1;
			}
		}
		else {
			this.fCurrentCodepoint= EOF;
			this.fCurrentCharLength= 0;
		}
	}
	
	@Override
	public final int getBeginIndex() {
		return this.fBeginIndex;
	}
	
	@Override
	public final int getEndIndex() {
		return this.fEndIndex;
	}
	
	@Override
	public final int getCurrentIndex() {
		return this.fCurrentIndex;
	}
	
	@Override
	public final int getCurrentLength() {
		return this.fCurrentCharLength;
	}
	
}
