/*******************************************************************************
 * 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.core.internal.text;



import org.eclipse.jface.text.BadLocationException;
import org.eclipse.wst.sse.core.internal.Logger;
import org.eclipse.wst.sse.core.internal.provisional.events.RegionChangedEvent;
import org.eclipse.wst.sse.core.internal.provisional.events.StructuredDocumentEvent;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
import org.eclipse.wst.sse.core.internal.util.Assert;
import org.eclipse.wst.sse.core.internal.util.Debug;
import org.eclipse.wst.sse.core.internal.util.Utilities;


public class BasicStructuredDocumentRegion implements IStructuredDocumentRegion {
	private static final String TEXT_STORE_NOT_ASSIGNED = "text store not assigned yet"; //$NON-NLS-1$
	private static final String UNDEFINED = "org.eclipse.wst.sse.core.structuredDocument.UNDEFINED"; //$NON-NLS-1$

	private ITextRegionList _regions;
	private boolean fIsDeleted = false;
	// private String fType;
	/**
	 * allow a pointer back to this nodes model
	 */
	private IStructuredDocument fParentDocument;
	/**
	 * was this node terminated normally
	 */
	// 0 == false, 1 == true
	private byte hasEnd = 0;
	protected int fLength;
	private IStructuredDocumentRegion next = null;
	private IStructuredDocumentRegion previous = null;
	protected int start;

	public BasicStructuredDocumentRegion() {
		super();
		_regions = new TextRegionListImpl();

	}

	/**
	 * Even inside-this class uses of 'regions' should use this method, as
	 * this is where (soft) memory management/reparsing, etc., will be
	 * centralized.
	 */
	private ITextRegionList _getRegions() {

		return _regions;
	}

	public void addRegion(ITextRegion aRegion) {
		_getRegions().add(aRegion);
	}

	public void adjust(int i) {
		start += i;
	}

	public void adjustLength(int i) {
		fLength += i;
	}

	public void adjustStart(int i) {
		start += i;
	}

	public void adjustTextLength(int i) {
		// not supported

	}

	public boolean containsOffset(int i) {

		return getStartOffset() <= i && i < getEndOffset();
	}

	public boolean containsOffset(ITextRegion containedRegion, int offset) {
		return getStartOffset(containedRegion) <= offset && offset < getEndOffset(containedRegion);
	}

	public void equatePositions(ITextRegion region) {
		start = region.getStart();
		fLength = region.getLength();
	}

	/**
	 * getEnd and getEndOffset are the same only for
	 * IStructuredDocumentRegions
	 */
	public int getEnd() {
		return start + fLength;
	}

	/**
	 * getEnd and getEndOffset are the same only for
	 * IStructuredDocumentRegions
	 */
	public int getEndOffset() {
		return getEnd();
	}

	public int getEndOffset(ITextRegion containedRegion) {
		return getStartOffset(containedRegion) + containedRegion.getLength();
	}

	public ITextRegion getFirstRegion() {
		if (_getRegions() == null)
			return null;
		return _getRegions().get(0);
	}

	public String getFullText() {
		String result = "";
		try {
			result = getParentDocument().get(start, fLength);
		}
		catch (BadLocationException e) {
			// log for now, unless we find reason not to
			Logger.log(Logger.INFO, e.getMessage());
		}
		return result;
	}

	public String getFullText(ITextRegion aRegion) {
		String result = "";
		try {
			int regionStart = aRegion.getStart();
			int regionLength = aRegion.getLength();
			result = fParentDocument.get(start + regionStart, regionLength);
		}
		catch (BadLocationException e) {
			// log for now, unless we find reason not to
			Logger.log(Logger.INFO, e.getMessage());
		}
		return result;
	}

	public String getFullText(String context) {
		// DMW: looping is faster than enumeration,
		// so switched around 2/12/03
		// Enumeration e = getRegions().elements();
		ITextRegion region = null;
		String result = ""; //$NON-NLS-1$
		int length = getRegions().size();
		for (int i = 0; i < length; i++) {
			region = getRegions().get(i);
			if (region.getType() == context)
				result += getFullText(region);
		}
		return result;
	}

	public ITextRegion getLastRegion() {
		if (_getRegions() == null)
			return null;
		return _getRegions().get(_getRegions().size() - 1);
	}

	public int getLength() {
		return fLength;
	}

	public IStructuredDocumentRegion getNext() {
		return next;
	}

	public int getNumberOfRegions() {
		return _getRegions().size();
	}

	public IStructuredDocument getParentDocument() {

		return fParentDocument;
	}

	public IStructuredDocumentRegion getPrevious() {
		return previous;
	}

	/**
	 * The parameter offset refers to the overall offset in the document.
	 */
	public ITextRegion getRegionAtCharacterOffset(int offset) {
		ITextRegion result = null;
		if (_getRegions() != null) {
			// transform the requested offset to the "scale" that
			// regions are stored in, which are all relative to the
			// start point.
			// int transformedOffset = offset - getStartOffset();
			//
			int length = getRegions().size();
			for (int i = 0; i < length; i++) {
				ITextRegion region = getRegions().get(i);
				if (Debug.debugStructuredDocument) {
					System.out.println("region(s) in IStructuredDocumentRegion::getRegionAtCharacterOffset: " + region); //$NON-NLS-1$
					System.out.println("       requested offset: " + offset); //$NON-NLS-1$
					// System.out.println(" transformedOffset: " +
					// transformedOffset); //$NON-NLS-1$
					System.out.println("       region start: " + region.getStart()); //$NON-NLS-1$
					System.out.println("       region end: " + region.getEnd()); //$NON-NLS-1$
					System.out.println("       region type: " + region.getType()); //$NON-NLS-1$
					System.out.println("       region class: " + region.getClass()); //$NON-NLS-1$

				}
				if ((getStartOffset(region) <= offset) && (offset < getEndOffset(region))) {
					result = region;
					break;
				}
			}
		}
		return result;
	}

	public ITextRegionList getRegions() {
		return _getRegions();
	}

	/**
	 * getStart and getStartOffset are the same only for
	 * IStrucutredDocumentRegions
	 */
	public int getStart() {
		return start;
	}

	/**
	 * getStart and getStartOffset are the same only for
	 * IStrucutredDocumentRegions
	 */
	public int getStartOffset() {
		return getStart();
	}

	public int getStartOffset(ITextRegion containedRegion) {
		// assert: containedRegion can not be null
		// (might be performance hit if literally put in assert call,
		// but containedRegion can not be null). Needs to be checked
		// by calling code.
		return getStartOffset() + containedRegion.getStart();
	}

	public String getText() {
		String result = null;
		try {
			if (fParentDocument == null) {
				// likely to happen during inspecting
				result = TEXT_STORE_NOT_ASSIGNED;
			}
			else {
				result = fParentDocument.get(start, fLength);
			}
		}
		catch (BadLocationException e) {
			// log for now, unless we find reason not to
			Logger.log(Logger.INFO, e.getMessage());
		}
		return result;
	}

	public String getText(ITextRegion aRegion) {
		// assert: aRegion can not be null
		// (might be performance hit if literally put in assert call,
		// but aRegion can not be null). Needs to be checked
		// by calling code.
		try {
			return fParentDocument.get(this.getStartOffset(aRegion), aRegion.getTextLength());
		}
		catch (BadLocationException e) {
			Logger.logException(e);
		}
		return ""; //$NON-NLS-1$
	}

	/**
	 * Returns the text of the first region with the matching context type
	 */
	public String getText(String context) {
		// DMW: looping is faster than enumeration,
		// so switched around 2/12/03
		// Enumeration e = getRegions().elements();
		ITextRegion region = null;
		String result = ""; //$NON-NLS-1$
		int length = getRegions().size();
		for (int i = 0; i < length; i++) {
			region = getRegions().get(i);
			if (region.getType() == context) {
				result = getText(region);
				break;
			}
		}
		return result;
	}

	public int getTextEnd() {
		return start + fLength;
	}

	/**
	 * @return int
	 */
	public int getTextEndOffset() {
		ITextRegion region = _getRegions().get(_getRegions().size() - 1);
		return getStartOffset() + region.getTextEnd();
	}

	public int getTextEndOffset(ITextRegion containedRegion) {
		return getStartOffset(containedRegion) + containedRegion.getTextLength();
	}

	public int getTextLength() {
		return fLength;
	}

	/**
	 * Provides the type of IStructuredDocumentRegion ... not to be confused
	 * with type of XML node!
	 */
	// For now return a String.
	public String getType() {
		// for a "named" XML node (e.g. start tag), but type of
		// flatnode is "named xml node" (which is always the second region).
		// Therefore, if there's two or more regions, the type for the
		// flatnode
		// will be the type of the second region. Otherwise it will be the
		// type
		// of the first region.
		// Note: this can be refined as needed.
		String result = UNDEFINED; // "IStructuredDocumentRegion.UNDEFINED";
		// //$NON-NLS-1$
		// we are assume there is always at least one region in a flatnode!
		result = getRegions().get(0).getType();
		// typcially subclassed, if something other than first region is
		// desired
		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.wst.sse.core.text.IStructuredDocumentRegion#isDeleted()
	 */
	public boolean isDeleted() {
		return fIsDeleted;
	}

	/**
	 * 
	 * @return boolean
	 */
	public boolean isEnded() {
		return (hasEnd == 1);
	}

	public boolean sameAs(IStructuredDocumentRegion region, int shift) {
		boolean result = false;
		// if region == null, we return false;
		if (region != null) {
			// if the regions are the same instance, they are equal
			if (this == region) {
				result = true;
			}
			else {
				// this is the non-trivial part
				// note: we change for type first, then start offset and end
				// offset,
				// since that would decide many cases right away and avoid the
				// text comparison
				if (getType() == region.getType()) {
					if (sameOffsetsAs(region, shift) && sameTextAs(region, shift)) {
						result = true;
					}
				}

			}
		}
		return result;
	}

	public boolean sameAs(ITextRegion oldRegion, IStructuredDocumentRegion newDocumentRegion, ITextRegion newRegion, int shift) {
		boolean result = false;
		// if any region is null, we return false (even if both are!)
		if ((oldRegion != null) && (newRegion != null)) {
			// if the regions are the same instance, they are equal
			if (oldRegion == newRegion) {
				result = true;
			}
			else {
				// this is the non-trivial part
				// note: we change for type first, then start offset and end
				// offset,
				// since that would decide many cases right away and avoid the
				// text comparison
				if (oldRegion.getType() == newRegion.getType()) {
					if (sameOffsetsAs(oldRegion, newDocumentRegion, newRegion, shift)) {
						if (sameTextAs(oldRegion, newDocumentRegion, newRegion, shift)) {
							result = true;
						}
					}
				}
			}

		}

		return result;
	}

	private boolean sameOffsetsAs(IStructuredDocumentRegion region, int shift) {
		if (getStartOffset() == region.getStartOffset() - shift) {
			if (getEndOffset() == region.getEndOffset() - shift) {
				return true;
			}
		}
		return false;
	}

	private boolean sameOffsetsAs(ITextRegion oldRegion, IStructuredDocumentRegion documentRegion, ITextRegion newRegion, int shift) {
		if (getStartOffset(oldRegion) == documentRegion.getStartOffset(newRegion) - shift) {
			if (getEndOffset(oldRegion) == documentRegion.getEndOffset(newRegion) - shift) {
				return true;
			}
		}
		return false;
	}

	private boolean sameTextAs(IStructuredDocumentRegion region, int shift) {
		boolean result = false;
		try {
			if (getText().equals(region.getText())) {
				result = true;
			}
		}
		// ISSUE: we should not need this
		catch (StringIndexOutOfBoundsException e) {
			result = false;
		}

		return result;
	}

	private boolean sameTextAs(ITextRegion oldRegion, IStructuredDocumentRegion documentRegion, ITextRegion newRegion, int shift) {
		boolean result = false;

		if (getText(oldRegion).equals(documentRegion.getText(newRegion))) {
			result = true;
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.wst.sse.core.text.IStructuredDocumentRegion#setDelete(boolean)
	 */
	public void setDeleted(boolean isDeleted) {
		fIsDeleted = isDeleted;

	}

	/**
	 * 
	 * @param newHasEnd
	 *            boolean
	 */
	public void setEnded(boolean newHasEnd) {
		if (newHasEnd) {
			hasEnd = 1;
		}
		else {
			hasEnd = 0;
		}
	}

	public void setLength(int newLength) {
		// textLength = newLength;
		fLength = newLength;
	}

	public void setNext(IStructuredDocumentRegion newNext) {
		next = newNext;
	}

	public void setParentDocument(IStructuredDocument document) {
		fParentDocument = document;

	}

	public void setPrevious(IStructuredDocumentRegion newPrevious) {
		previous = newPrevious;
	}

	public void setRegions(ITextRegionList containedRegions) {
		_regions = containedRegions;
	}

	public void setStart(int newStart) {
		start = newStart;
	}

	public String toString() {
		// NOTE: if the document held by any region has been updated and the
		// region offsets have not
		// yet been updated, the output from this method invalid.
		// Also note, this method can not be changed, without "breaking"
		// unit tests, since some of them compare current results to previous
		// results.
		String result = null;
		result = "[" + getStart() + ", " + getEnd() + "] (" + getText() + ")"; //$NON-NLS-4$//$NON-NLS-3$//$NON-NLS-2$//$NON-NLS-1$
		return result;
	}

	private void updateDownStreamRegions(ITextRegion changedRegion, int lengthDifference) {
		int listLength = _getRegions().size();
		int startIndex = 0;
		// first, loop through to find index of where to start
		for (int i = 0; i < listLength; i++) {
			ITextRegion region = _getRegions().get(i);
			if (region == changedRegion) {
				startIndex = i;
				break;
			}
		}
		// now, beginning one past the one that was changed, loop
		// through to end of list, adjusting the start postions.
		startIndex++;
		for (int j = startIndex; j < listLength; j++) {
			ITextRegion region = _getRegions().get(j);
			region.adjustStart(lengthDifference);
		}
	}

	public StructuredDocumentEvent updateRegion(Object requester, IStructuredDocumentRegion structuredDocumentRegion, String changes, int requestStart, int lengthToReplace) {
		StructuredDocumentEvent result = null;
		int lengthDifference = Utilities.calculateLengthDifference(changes, lengthToReplace);
		// Get the region pointed to by the requestStart postion, and give
		// that region a chance to effect
		// the update.
		ITextRegion region = getRegionAtCharacterOffset(requestStart);
		// if there is no region, then the requested changes must come right
		// after the
		// node (and right after the last region). This happens, for example,
		// when someone
		// types something at the end of the document, or more commonly, when
		// they are right
		// at the beginning of one node, and the dirty start is therefore
		// calculated to be the
		// previous node.
		// So, in this case, we'll give the last region a chance to see if it
		// wants to
		// swallow the requested changes -- but only for inserts -- deletes
		// and "replaces"
		// should be reparsed if they are in these border regions, and only if
		// the
		if ((region == null) && (lengthToReplace == 0)) {
			region = _getRegions().get(_getRegions().size() - 1);
			// make sure the region is contiguous
			if (getEndOffset(region) == requestStart) {
				result = region.updateRegion(requester, this, changes, requestStart, lengthToReplace);
			}
		}
		else {
			if (region != null) {
				//
				// If the requested change spans more than one region, then
				// we don't give the region a chance to update.
				if ((containsOffset(region, requestStart)) && (containsOffset(region, requestStart + lengthToReplace))) {
					result = region.updateRegion(requester, this, changes, requestStart, lengthToReplace);
				}
			}
		}
		// if result is not null, then we need to update the start and end
		// postions of the regions that follow this one
		// if result is null, then apply the flatnode specific checks on what
		// it can change
		// (i.e. more than one region, but no change to the node itself)
		if (result != null) {
			// That is, a region decided it could handle the change and
			// created
			// a region changed event.
			Assert.isTrue(result instanceof RegionChangedEvent, "Program Error"); //$NON-NLS-1$
			updateDownStreamRegions(((RegionChangedEvent) result).getRegion(), lengthDifference);
			// PLUS, we need to update our own node end point (length)
			setLength(getLength() + lengthDifference);
		}

		return result;
	}

}
