/*******************************************************************************
 * 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.events.RegionChangedEvent;
import org.eclipse.wst.sse.core.events.StructuredDocumentEvent;
import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
import org.eclipse.wst.sse.core.internal.Logger;
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;
import org.eclipse.wst.sse.core.text.IStructuredDocument;
import org.eclipse.wst.sse.core.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.text.ITextRegion;
import org.eclipse.wst.sse.core.text.ITextRegionList;


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 length;
	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);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.sed.structured.text.ITextRegion#adjust(int)
	 */
	public void adjust(int i) {
		start += i;
	}

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

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

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.sed.structured.text.ITextRegion#adjustTextLength(int)
	 */
	public void adjustTextLength(int i) {
		// not supported

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.sed.structured.text.ITextRegionCollection#containsOffset(int)
	 */
	public boolean containsOffset(int i) {

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

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.sed.structured.text.ITextRegionCollection#containsOffset(com.ibm.sed.structured.text.ITextRegion,
	 *      int)
	 */
	public boolean containsOffset(ITextRegion containedRegion, int offset) {
		return getStartOffset(containedRegion) <= offset && offset < getEndOffset(containedRegion);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.sed.structured.text.ITextRegion#equatePositions(com.ibm.sed.structured.text.ITextRegion)
	 */
	public void equatePositions(ITextRegion region) {
		start = region.getStart();
		length = region.getLength();
		//textLength = region.getTextLength();

	}

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

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

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.sed.structured.text.ITextRegionCollection#getEndOffset(com.ibm.sed.structured.text.ITextRegion)
	 */
	public int getEndOffset(ITextRegion containedRegion) {
		return getStartOffset(containedRegion) + containedRegion.getLength();
	}

	//	public IStructuredDocumentRegion getFirstNode() {
	//		IStructuredDocumentRegion aNode = (IStructuredDocumentRegion)
	// fOwningDocument.getFirstStructuredDocumentRegion();
	//		return aNode;
	//	}
	public ITextRegion getFirstRegion() {
		if (_getRegions() == null)
			return null;
		return _getRegions().get(0);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.sed.structured.text.ITextRegionCollection#getFullText()
	 */
	public String getFullText() {
		try {
			return getParentDocument().get(start, length);
		} catch (BadLocationException e) {
			// program error
			throw new SourceEditingRuntimeException(e);
		}
	}

	public String getFullText(ITextRegion aRegion) {
		String result = null;
		try {
			int regionStart = aRegion.getStart();
			int regionLength = aRegion.getLength();
			result = fParentDocument.get(start + regionStart, regionLength);
		} catch (BadLocationException e) {
			throw new SourceEditingRuntimeException(e);
		}
		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 length;
	}

	public IStructuredDocumentRegion getNext() {
		return next;
	}

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

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.sed.structured.text.IStructuredDocumentRegion#getDocument()
	 */
	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();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.sed.structured.text.ITextRegionCollection#getStartOffset(com.ibm.sed.structured.text.ITextRegion)
	 */
	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, length);
			}
		} catch (BadLocationException e) {
			throw new SourceEditingRuntimeException(e);
		}
		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;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.sed.structured.text.ITextRegion#getTextEnd()
	 */
	public int getTextEnd() {

		//return start + textLength;
		return start + length;
	}

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

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.sed.structured.text.ITextRegionCollection#getTextEndOffset(com.ibm.sed.structured.text.ITextRegion)
	 */
	public int getTextEndOffset(ITextRegion containedRegion) {
		return getStartOffset(containedRegion) + containedRegion.getTextLength();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.sed.structured.text.ITextRegion#getTextLength()
	 */
	public int getTextLength() {
		//return textLength;
		return length;
	}

	/**
	 * 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;
			}
		} catch (SourceEditingRuntimeException e) {
			if (e.getOriginalException() instanceof BadLocationException || e.getOriginalException() instanceof StringIndexOutOfBoundsException) {
				// this happens normally if document has been deleted from
				// and therefore regions are not equal
				result = false;
			} else {
				throw e;
			}
		}

		return result;
	}

	private boolean sameTextAs(ITextRegion oldRegion, IStructuredDocumentRegion documentRegion, ITextRegion newRegion, int shift) {
		boolean result = false;
		try {
			if (getText(oldRegion).equals(documentRegion.getText(newRegion))) {
				result = true;
			}
		} catch (SourceEditingRuntimeException e) {
			if (e.getOriginalException() instanceof BadLocationException) {
				// this happens normally if document has been deleted from
				// and therefore regions are not equal
				result = false;
			} else {
				throw e;
			}
		}

		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;
		length = 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);
		}
	}

	// This is a language specific method (e.g. HTML, Java, Prolog, etc.) so
	// could/should be made configurable.
	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ibm.sed.structured.text.ITextRegion#updateModel(java.lang.Object,
	 *      com.ibm.sed.structured.text.IStructuredDocumentRegion,
	 *      java.lang.String, int, int)
	 */
	//	public StructuredDocumentEvent updateModel(Object requester, String
	// changes, int start, int end, IStructuredDocumentRegion flatnode) {
	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;
	}

}
