/*******************************************************************************
 * 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.ui;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;

import org.eclipse.jface.text.Assert;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.BadPositionCategoryException;
import org.eclipse.jface.text.DefaultPositionUpdater;
import org.eclipse.jface.text.DocumentCommand;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Position;
import org.eclipse.swt.events.VerifyEvent;

/**
 * TODO Temporary subclass to workaround BUG44665
 * 
 * Algorithm for intersects() methods changed.
 */
/**
 * Represents a text modification as a document replace command. The text
 * modification is given as a <code>VerifyEvent</code> and translated into a
 * document replace command relative to a given offset. A document command can
 * also be used to initialize a given <code>VerifyEvent</code>.
 * <p>
 * A document command can also represent a list of related changes.
 */
public class StructuredDocumentCommand extends DocumentCommand {

	/**
	 * A command which is added to document commands.
	 * 
	 * @since 2.1
	 */
	private static class Command implements Comparable {
		/** The length of the range to be replaced. */
		final int fLength;
		/** The offset of the range to be replaced */
		final int fOffset;
		/** The listern who owns this command */
		private final IDocumentListener fOwner;
		/** The replacement text */
		private final String fText;

		/**
		 * Creates a new command with the given specification.
		 * 
		 * @param offset
		 *            the offset of the replace command
		 * @param length
		 *            the length of the replace command
		 * @param text
		 *            the text to replace with, may be <code>null</code>
		 * @param owner
		 *            the document command owner, may be <code>null</code>
		 * @since 3.0
		 */
		public Command(int offset, int length, String text, IDocumentListener owner) {
			if (offset < 0 || length < 0)
				throw new IllegalArgumentException();
			fOffset = offset;
			fLength = length;
			fText = text;
			fOwner = owner;
		}

		/*
		 * @see java.util.Comparator#compare(java.lang.Object,
		 *      java.lang.Object)
		 */
		public int compareTo(final Object object) {
			if (equals(object))
				return 0;

			final Command command = (Command) object;

			// diff middle points if not intersecting
			if (fOffset + fLength <= command.fOffset || command.fOffset + command.fLength <= fOffset) {
				int value = (2 * fOffset + fLength) - (2 * command.fOffset + command.fLength);
				if (value != 0)
					return value;
			}
			// the answer
			return 42;
		}

		/*
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		public boolean equals(Object object) {
			if (object == this)
				return true;
			if (!(object instanceof Command))
				return false;
			final Command command = (Command) object;
			return command.fOffset == fOffset && command.fLength == fLength;
		}

		/**
		 * Executes the document command on the specified document.
		 * 
		 * @param document
		 *            the document on which to execute the command.
		 * @throws BadLocationException
		 *             in case this commands cannot be executed
		 */
		public void execute(IDocument document) throws BadLocationException {

			if (fLength == 0 && fText == null)
				return;

			if (fOwner != null)
				document.removeDocumentListener(fOwner);

			document.replace(fOffset, fLength, fText);

			if (fOwner != null)
				document.addDocumentListener(fOwner);
		}

		/**
		 * Returns the length delta for this command.
		 * 
		 * @return the length delta for this command
		 */
		public int getDeltaLength() {
			return (fText == null ? 0 : fText.length()) - fLength;
		}
	}

	/**
	 * A command iterator.
	 */
	private static class CommandIterator implements Iterator {

		/** The original command. */
		private Command fCommand;

		/** A flag indicating the direction of iteration. */
		private boolean fForward;

		/** The command iterator. */
		private final Iterator fIterator;

		/**
		 * Creates a command iterator.
		 * 
		 * @param commands
		 *            an ascending ordered list of commands
		 * @param command
		 *            the original command
		 * @param forward
		 *            the direction
		 */
		public CommandIterator(final List commands, final Command command, final boolean forward) {
			if (commands == null || command == null)
				throw new IllegalArgumentException();
			fIterator = forward ? commands.iterator() : new ReverseListIterator(commands.listIterator(commands.size()));
			fCommand = command;
			fForward = forward;
		}

		/*
		 * @see java.util.Iterator#hasNext()
		 */
		public boolean hasNext() {
			return fCommand != null || fIterator.hasNext();
		}

		/*
		 * @see java.util.Iterator#next()
		 */
		public Object next() {

			if (!hasNext())
				throw new NoSuchElementException();

			if (fCommand == null)
				return fIterator.next();

			if (!fIterator.hasNext()) {
				final Command tempCommand = fCommand;
				fCommand = null;
				return tempCommand;
			}

			final Command command = (Command) fIterator.next();
			final int compareValue = command.compareTo(fCommand);

			if ((compareValue < 0) ^ !fForward) {
				return command;

			} else if ((compareValue > 0) ^ !fForward) {
				final Command tempCommand = fCommand;
				fCommand = command;
				return tempCommand;

			} else {
				throw new IllegalArgumentException();
			}
		}

		/*
		 * @see java.util.Iterator#remove()
		 */
		public void remove() {
			throw new UnsupportedOperationException();
		}
	}

	/**
	 * An iterator, which iterates in reverse over a list.
	 */
	private static class ReverseListIterator implements Iterator {

		/** The list iterator. */
		private final ListIterator fListIterator;

		/**
		 * Creates a reverse list iterator.
		 * 
		 * @param listIterator
		 *            the iterator that this reverse iterator is based upon
		 */
		public ReverseListIterator(ListIterator listIterator) {
			if (listIterator == null)
				throw new IllegalArgumentException();
			fListIterator = listIterator;
		}

		/*
		 * @see java.util.Iterator#hasNext()
		 */
		public boolean hasNext() {
			return fListIterator.hasPrevious();
		}

		/*
		 * @see java.util.Iterator#next()
		 */
		public Object next() {
			return fListIterator.previous();
		}

		/*
		 * @see java.util.Iterator#remove()
		 */
		public void remove() {
			throw new UnsupportedOperationException();
		}
	}

	/**
	 * Additional document commands.
	 * 
	 * @since 2.1
	 */
	private final List fCommands = new ArrayList();

	/**
	 * Adds an additional replace command. The added replace command must not
	 * overlap with existing ones. If the document command owner is not
	 * <code>null</code>, it will not get document change notifications for
	 * the particular command.
	 * 
	 * @param offset
	 *            the offset of the region to replace
	 * @param length
	 *            the length of the region to replace
	 * @param text
	 *            the text to replace with, may be <code>null</code>
	 * @param owner
	 *            the command owner, may be <code>null</code>
	 * @throws BadLocationException
	 *             if the added command intersects with an existing one
	 * @since 2.1
	 */
	public void addCommand(int offsetParameter, int lengthParameter, String textParameter, IDocumentListener ownerParameter) throws BadLocationException {
		final Command command = new Command(offsetParameter, lengthParameter, textParameter, ownerParameter);

		internalAddCommand(command);
	}

	/**
	 * @param command
	 * @throws BadLocationException
	 */
	private void internalAddCommand(final Command command) throws BadLocationException {
		if (intersects(command))
			throw new BadLocationException();

		final int index = Collections.binarySearch(fCommands, command);

		// a command with exactly the same ranges exists already
		if (index >= 0)
			throw new BadLocationException();

		// binary search result is defined as (-(insertionIndex) - 1)
		final int insertionIndex = -(index + 1);

		// overlaps to the right?
		if (insertionIndex != fCommands.size() && intersects((Command) fCommands.get(insertionIndex), command))
			throw new BadLocationException();

		// overlaps to the left?
		if (insertionIndex != 0 && intersects((Command) fCommands.get(insertionIndex - 1), command))
			throw new BadLocationException();

		fCommands.add(insertionIndex, command);
	}

	/**
	 * Executes the document commands on a document.
	 * 
	 * @param document
	 *            the document on which to execute the commands
	 * @since 2.1
	 */
	void executeStructuredDocumentCommand(IDocument document) throws BadLocationException {

		if (length == 0 && text == null && fCommands.size() == 0)
			return;

		DefaultPositionUpdater updater = new DefaultPositionUpdater(getCategory());
		Position caretPosition = null;
		try {
			if (updateCaret()) {
				document.addPositionCategory(getCategory());
				document.addPositionUpdater(updater);
				caretPosition = new Position(caretOffset);
				document.addPosition(getCategory(), caretPosition);
			}

			final Command originalCommand = new Command(offset, length, text, owner);
			for (final Iterator iterator = new CommandIterator(fCommands, originalCommand, false); iterator.hasNext();)
				((Command) iterator.next()).execute(document);

		} catch (BadLocationException e) {
			// ignore
		} catch (BadPositionCategoryException e) {
			// ignore
		} finally {
			if (updateCaret()) {
				document.removePositionUpdater(updater);
				try {
					document.removePositionCategory(getCategory());
				} catch (BadPositionCategoryException e) {
					Assert.isTrue(false);
				}
				caretOffset = caretPosition.getOffset();
			}
		}
	}

	/**
	 * Fills the given verify event with the replace text and the doit flag of
	 * this document command. Returns whether the document command covers the
	 * same range as the verify event considering the given offset.
	 * 
	 * @param event
	 *            the event to be changed
	 * @param modelRange
	 *            to be considered for range comparison
	 * @return <code>true</code> if this command and the event cover the
	 *         same range
	 */
	public boolean fillEventStructuredDocumentCommand(VerifyEvent event, IRegion modelRange) {
		event.text = text;
		event.doit = (offset == modelRange.getOffset() && length == modelRange.getLength() && doit && caretOffset == -1);
		return event.doit;
	}

	/**
	 * Returns the position category for the caret offset position.
	 * 
	 * @return the position category for the caret offset position
	 * @since 3.0
	 */
	private String getCategory() {
		return toString();
	}

	/**
	 * Returns the number of commands including the original document command.
	 * 
	 * @return returns the number of commands
	 * @since 2.1
	 */
	public int getCommandCount() {
		return 1 + fCommands.size();
	}

	/**
	 * Returns an iterator over the commands in ascending position order. The
	 * iterator includes the original document command. Commands cannot be
	 * removed.
	 * 
	 * @return returns the command iterator
	 */
	public Iterator getCommandIterator() {
		Command command = new Command(offset, length, text, owner);
		return new CommandIterator(fCommands, command, true);
	}

	/**
	 * Returns whether the given command intersects with this command.
	 * 
	 * @param command
	 *            the command
	 * @return <code>true</code> if the command intersects with this command
	 * @since 2.1
	 */
	private boolean intersects(Command command) {
		boolean result = false;
		// diff middle points if not intersecting
		if (offset + length <= command.fOffset || command.fOffset + command.fLength <= offset)
			//			return (2 * offset + length) - (2 * command.fOffset +
			// command.fLength) == 0;
			result = false;
		else
			result = true;
		return result;
	}

	/**
	 * Returns whether the two given commands intersect.
	 * 
	 * @param command0
	 *            the first command
	 * @param command1
	 *            the second command
	 * @return <code>true</code> if the commands intersect
	 * @since 2.1
	 */
	private boolean intersects(Command command0, Command command1) {
		boolean result = false;
		// diff middle points if not intersecting
		if (command0.fOffset + command0.fLength <= command1.fOffset || command1.fOffset + command1.fLength <= command0.fOffset)
			//			return (2 * command0.fOffset + command0.fLength) - (2 *
			// command1.fOffset + command1.fLength) == 0;
			result = false;
		else
			result = true;
		return result;
	}

	/**
	 * Translates a verify event into a document replace command using the
	 * given offset.
	 * 
	 * @param event
	 *            the event to be translated
	 * @param modelRange
	 *            the event range as model range
	 */
	public void setEventStructuredDocumentEvent(VerifyEvent event, IRegion modelRange) {

		doit = true;
		text = event.text;

		offset = modelRange.getOffset();
		length = modelRange.getLength();

		owner = null;
		caretOffset = -1;
		shiftsCaret = true;
		fCommands.clear();
	}

	/**
	 * Returns <code>true</code> if the caret offset should be updated,
	 * <code>false</code> otherwise.
	 * 
	 * @return <code>true</code> if the caret offset should be updated,
	 *         <code>false</code> otherwise
	 * @since 3.0
	 */
	private boolean updateCaret() {
		return shiftsCaret && caretOffset != -1;
	}

}
