/*******************************************************************************
 * Copyright (c) 2000, 2015 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
 *******************************************************************************/
package org.eclipse.jface.text;

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.swt.events.VerifyEvent;

import org.eclipse.core.runtime.Assert;


/**
 * Represents a text modification as a document replace command. The text
 * modification is given as a {@link org.eclipse.swt.events.VerifyEvent} 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.</p>
 */
public class DocumentCommand {

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

		/**
		 * 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;
		}

		/**
		 * 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);
		}

		@Override
		public int compareTo(Command object) {
			if (isEqual(object))
				return 0;

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

		private boolean isEqual(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;
		}
	}

	/**
	 * An iterator, which iterates in reverse over a list.
	 * 
	 * @param <E> the type of elements returned by this iterator
	 */
	private static class ReverseListIterator<E> implements Iterator<E> {

		/** The list iterator. */
		private final ListIterator<E> fListIterator;

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

		@Override
		public boolean hasNext() {
			return fListIterator.hasPrevious();
		}

		@Override
		public E next() {
			return fListIterator.previous();
		}

		@Override
		public void remove() {
			throw new UnsupportedOperationException();
		}
	}

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

		/** The command iterator. */
		private final Iterator<Command> fIterator;

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

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

		/**
		 * 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<Command> 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;
		}

		@Override
		public boolean hasNext() {
			return fCommand != null || fIterator.hasNext();
		}

		@Override
		public Command 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= 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();
			}
		}

		@Override
		public void remove() {
			throw new UnsupportedOperationException();
		}
	}

	/** Must the command be updated */
	public boolean doit= false;
	/** The offset of the command. */
	public int offset;
	/** The length of the command */
	public int length;
	/** The text to be inserted */
	public String text;
	/**
	 * The owner of the document command which will not be notified.
	 * @since 2.1
	 */
	public IDocumentListener owner;
	/**
	 * The caret offset with respect to the document before the document command is executed.
	 * @since 2.1
	 */
	public int caretOffset;
	/**
	 * Additional document commands.
	 * @since 2.1
	 */
	private final List<Command> fCommands= new ArrayList<>();
	/**
	 * Indicates whether the caret should be shifted by this command.
	 * @since 3.0
	 */
	public boolean shiftsCaret;


	/**
	 * Creates a new document command.
	 */
	protected DocumentCommand() {
	}

	/**
	 * 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
	 */
	void setEvent(VerifyEvent event, IRegion modelRange) {

		doit= true;
		text= event.text;

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

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

	/**
	 * Fills the given verify event with the replace text and the <code>doit</code>
	 * 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
	 */
	boolean fillEvent(VerifyEvent event, IRegion modelRange) {
		event.text= text;
		event.doit= (offset == modelRange.getOffset() && length == modelRange.getLength() && doit && caretOffset == -1);
		return event.doit;
	}

	/**
	 * 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 commandOffset the offset of the region to replace
	 * @param commandLength the length of the region to replace
	 * @param commandText the text to replace with, may be <code>null</code>
	 * @param commandOwner 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 commandOffset, int commandLength, String commandText, IDocumentListener commandOwner) throws BadLocationException {
		final Command command= new Command(commandOffset, commandLength, commandText, commandOwner);

		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(fCommands.get(insertionIndex), command))
			throw new BadLocationException();

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

		fCommands.add(insertionIndex, command);
	}

	/**
	 * 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<Command> getCommandIterator() {
		Command command= new Command(offset, length, text, owner);
		return new CommandIterator(fCommands, command, true);
	}

	/**
	 * 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 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) {
		// 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;
		return 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) {
		// 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;
		return true;
	}

	/**
	 * Executes the document commands on a document.
	 *
	 * @param document the document on which to execute the commands
	 * @throws BadLocationException in case access to the given document fails
	 * @since 2.1
	 */
	void execute(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<Command> iterator= new CommandIterator(fCommands, originalCommand, false); iterator.hasNext(); )
				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();
			}
		}
	}

	/**
	 * 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;
	}

	/**
	 * 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();
	}

}
