/*******************************************************************************
 * Copyright (c) 2000, 2019 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Paul Pazderski  - Contributions for:
 *                          Bug 547064: use binary search for getPartition
 *                          Bug 548356: fixed user input handling
 *                          Bug 550618: getStyleRanges produced invalid overlapping styles
 *                          Bug 550621: Implementation of IConsoleDocumentPartitionerExtension
 *                          Bug 76936:  Support interpretation of \b and \r in console output
 *******************************************************************************/
package org.eclipse.ui.internal.console;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitionerExtension;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.MultiStringMatcher;
import org.eclipse.jface.text.MultiStringMatcher.Match;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TypedRegion;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.console.ConsolePlugin;
import org.eclipse.ui.console.IConsoleDocumentPartitioner;
import org.eclipse.ui.console.IConsoleDocumentPartitionerExtension;
import org.eclipse.ui.console.IOConsole;
import org.eclipse.ui.console.IOConsoleInputStream;
import org.eclipse.ui.console.IOConsoleOutputStream;
import org.eclipse.ui.progress.UIJob;
import org.eclipse.ui.progress.WorkbenchJob;

/**
 * Partitions an IOConsole's document
 *
 * @since 3.1
 */
public class IOConsolePartitioner
		implements IConsoleDocumentPartitioner, IConsoleDocumentPartitionerExtension, IDocumentPartitionerExtension {
	/**
	 * Enumeration used to distinct sources of document updates. (especially to
	 * distinct updates triggered by this partitioner from other document changes)
	 */
	private enum DocUpdateType {
		/**
		 * Default if reason for document change is not known. Document change is
		 * interpreted as user input.
		 */
		INPUT,
		/**
		 * Document update was triggered from this partitioner by appending content
		 * received from output streams.
		 */
		OUTPUT,
		/** Document update was triggered from this partitioner's {@link TrimJob}. */
		TRIM,
	}

	/**
	 * If true validate partitioning after changes and do other additional
	 * assertions. Useful for developing/debugging.
	 */
	private static final boolean ASSERT = false;

	/**
	 * Comparator to sort or search {@link IRegion}s by {@link IRegion#getOffset()}.
	 */
	private static final Comparator<IRegion> CMP_REGION_BY_OFFSET = Comparator.comparing(IRegion::getOffset);

	/**
	 * Pattern used to find supported ASCII control characters <b>except</b>
	 * carriage return.
	 */
	private static final String CONTROL_CHARACTERS_PATTERN_STR = "(?:\b+)"; //$NON-NLS-1$
	/**
	 * Pattern used to find supported ASCII control characters <b>including</b>
	 * carriage return.
	 */
	private static final String CONTROL_CHARACTERS_WITH_CR_PATTERN_STR = "(?:\b+|\r+(?!\n))"; //$NON-NLS-1$

	/** The connected {@link IDocument} this partitioner manages. */
	private IDocument document;
	/**
	 * List of all partitions. Must always be sorted ascending by
	 * {@link IRegion#getOffset()} and not contain <code>null</code> or 0-length
	 * elements. (see also {@link #checkPartitions()})
	 */
	private final ArrayList<IOConsolePartition> partitions = new ArrayList<>();
	/** Blocks of data that have not yet been appended to the document. */
	private final ArrayList<PendingPartition> pendingPartitions = new ArrayList<>();
	/** Total length of pending partitions content. */
	private int pendingSize;
	/** Job that appends pending partitions to the document. */
	private final QueueProcessingJob queueJob = new QueueProcessingJob();
	/** Job that trims console content if it exceeds {@link #highWaterMark}. */
	private final TrimJob trimJob = new TrimJob();
	/**
	 * Reason for document update. Set before changing document inside this
	 * partitioner to prevent that change is interpreted as user input.
	 * <p>
	 * Automatically reset to {@link DocUpdateType#INPUT} after every document
	 * change.
	 * </p>
	 */
	private DocUpdateType updateType = DocUpdateType.INPUT;
	private IRegion changedRegion;
	/**
	 * A list of partitions containing input from the console, that have not been
	 * appended to the input stream yet. No guarantees on element order.
	 */
	private ArrayList<IOConsolePartition> inputPartitions;
	/**
	 * A matcher to search for legal line delimiters in new input. Never
	 * <code>null</code> but match nothing if no document connected.
	 */
	private MultiStringMatcher legalLineDelimiterMatcher;
	/**
	 * The high mark for console content trimming. If console content exceeds this
	 * length trimming is scheduled. Trimming is disabled if value is negative.
	 */
	private int highWaterMark = -1;
	/**
	 * The low mark for console content trimming. If trim is performed approximate
	 * this many characters are remain in console.
	 */
	private int lowWaterMark = -1;

	/** The partitioned {@link IOConsole}. */
	private IOConsole console;

	/** Set after console signaled that all streams are closed. */
	private volatile boolean streamsClosed;
	/**
	 * Active pattern to search for supported control characters. If
	 * <code>null</code> control characters are treated as any other characters.
	 */
	private Pattern controlCharacterPattern = null;
	/**
	 * Whether <code>\r</code> is interpreted as control characters
	 * (<code>true</code>) or not in console output. If <code>false</code> they are
	 * probably handled as newline.
	 */
	private boolean carriageReturnAsControlCharacter = true;
	/**
	 * Offset where next output is written to console.
	 */
	private int outputOffset = 0;

	/**
	 * Create new partitioner for an {@link IOConsole}.
	 * <p>
	 * The partitioner must be explicit {@link #connect(IDocument) connected} with
	 * the consoles {@link IDocument}.
	 * </p>
	 *
	 * @param console the partitioned console. Not <code>null</code>.
	 */
	public IOConsolePartitioner(IOConsole console) {
		this.console = Objects.requireNonNull(console);
		queueJob.setRule(console.getSchedulingRule());
		trimJob.setRule(console.getSchedulingRule());
	}

	/**
	 * Get partitioned document or <code>null</code> if none connected.
	 *
	 * @return partitioned document
	 */
	public IDocument getDocument() {
		return document;
	}

	@Override
	public void connect(IDocument doc) {
		if (doc == document) {
			return;
		}
		disconnect();
		if (doc != null) {
			synchronized (partitions) {
				inputPartitions = new ArrayList<>();
				document = doc;
				legalLineDelimiterMatcher = MultiStringMatcher.create(document.getLegalLineDelimiters());
			}
		}
	}

	@Override
	public void disconnect() {
		synchronized (pendingPartitions) {
			pendingPartitions.clear();
			pendingSize = 0;
			pendingPartitions.notifyAll();
		}
		synchronized (partitions) {
			trimJob.cancel();
			queueJob.cancel();
			legalLineDelimiterMatcher = null;
			document = null;
			inputPartitions = null;
			partitions.clear();
		}
	}

	/**
	 * Get high water mark.
	 *
	 * @return the trim if exceeded mark
	 * @see IOConsole#getHighWaterMark()
	 */
	public int getHighWaterMark() {
		return highWaterMark;
	}

	/**
	 * Get low water mark.
	 *
	 * @return the trim to this length mark
	 * @see IOConsole#getLowWaterMark()
	 */
	public int getLowWaterMark() {
		return lowWaterMark;
	}

	/**
	 * Set low and high water marks.
	 *
	 * @param low  the trim to this length mark
	 * @param high the trim if exceeded mark
	 * @see IOConsole#setWaterMarks(int, int)
	 */
	public void setWaterMarks(int low, int high) {
		lowWaterMark = low;
		highWaterMark = high;
		ConsolePlugin.getStandardDisplay().asyncExec(this::checkBufferSize);
	}

	/**
	 * Notification from the console that all of its streams have been closed.
	 */
	public void streamsClosed() {
		if (streamsClosed) {
			log(IStatus.ERROR, "Streams are already closed."); //$NON-NLS-1$
			return;
		}
		streamsClosed = true;
		checkFinished();
	}

	/**
	 * Check if partitioner is finished and does not expect any new data appended to
	 * document.
	 */
	private void checkFinished() {
		if (streamsClosed) {
			// do not expect new data since all streams are closed
			// check if pending data is queued
			final boolean morePending;
			synchronized (pendingPartitions) {
				morePending = !pendingPartitions.isEmpty();
			}
			if (morePending) {
				queueJob.schedule();
			} else {
				console.partitionerFinished();
			}
		}
	}

	@Override
	public void documentAboutToBeChanged(DocumentEvent event) {
	}

	@Override
	public boolean documentChanged(DocumentEvent event) {
		return documentChanged2(event) != null;
	}

	@Override
	public String[] getLegalContentTypes() {
		return new String[] { IOConsolePartition.OUTPUT_PARTITION_TYPE, IOConsolePartition.INPUT_PARTITION_TYPE };
	}

	@Override
	public String getContentType(int offset) {
		return getPartition(offset).getType();
	}

	@Override
	public ITypedRegion[] computePartitioning(int offset, int length) {
		return computeIOPartitioning(offset, length);
	}

	/**
	 * Same as {@link #computePartitioning(int, int)} but with more specific return
	 * type.
	 *
	 * @param offset the offset of the range of interest
	 * @param length the length of the range of interest
	 * @return the partitioning of the requested range (never <code>null</code>)
	 */
	private IOConsolePartition[] computeIOPartitioning(int offset, int length) {
		return computePartitioning(offset, length, true, true);
	}

	/**
	 * Get partitioning for a given range with possibility to filter partitions by
	 * their read-only property.
	 *
	 * @param offset          the offset of the range of interest
	 * @param length          the length of the range of interest
	 * @param includeWritable if false writable partitions are skipped
	 * @param includeReadOnly if false read-only partitions are skipped
	 * @return the partitioning of the requested range (never <code>null</code>)
	 */
	private IOConsolePartition[] computePartitioning(int offset, int length, boolean includeWritable,
			boolean includeReadOnly) {
		final List<IOConsolePartition> result = new ArrayList<>();
		synchronized (partitions) {
			int index = findPartitionCandidate(offset);
			if (index < 0) { // requested range starts before any known partition offset
				index = 0; // so we start collecting at first known partition
			}

			final int end = offset + length;
			for (; index < partitions.size(); index++) {
				final IOConsolePartition partition = partitions.get(index);
				if (partition.getOffset() >= end) {
					break;
				}
				if ((includeWritable && !partition.isReadOnly()) || (includeReadOnly && partition.isReadOnly())) {
					result.add(partition);
				}
			}
		}
		return result.toArray(new IOConsolePartition[0]);
	}

	@Override
	public ITypedRegion getPartition(int offset) {
		final ITypedRegion partition = getIOPartition(offset);
		return partition != null ? partition : new TypedRegion(offset, 0, IOConsolePartition.INPUT_PARTITION_TYPE);
	}

	/**
	 * Like {@link #getPartition(int)} but returns <code>null</code> for
	 * unpartitioned or invalid offsets.
	 *
	 * @param offset the offset for which to determine the partition
	 * @return the partition containing this offset or <code>null</code> if offset
	 *         is not partitioned
	 */
	private IOConsolePartition getIOPartition(int offset) {
		synchronized (partitions) {
			final int index = findPartitionCandidate(offset);
			if (index >= 0) {
				final IOConsolePartition partition = partitions.get(index);
				if (partition.getOffset() + partition.getLength() > offset) {
					return partition;
				}
			}
			return null;
		}
	}

	/**
	 * Search {@link #partitions} for the partition which is most likely containing
	 * the requested offset.
	 * <p>
	 * This (index + 1) can be used to insert a new partition with this offset. The
	 * resulting {@link #partitions} list is guaranteed to still be sorted. (as long
	 * as you do proper synchronization and consider concurrency problems)
	 * </p>
	 *
	 * @param offset the offset for which to determine the partition candidate
	 * @return index of partition element with partition offset closest to requested
	 *         offset or <code>-1</code> if requested offset is lower than offset of
	 *         any known partition
	 */
	private int findPartitionCandidate(int offset) {
		final Region target = new Region(offset, 0);
		final int index = Collections.binarySearch(partitions, target, CMP_REGION_BY_OFFSET);
		if (index >= 0) {
			// found partition whose offset equals the requested offset
			return index;
		}
		// no exact offset match. Adjust index to point at partition which is closest to
		// requested offset but whose offset is still lower than requested offset.
		// Results in -1 if all known offsets are greater.
		return (-index) - 2;
	}

	/**
	 * Enforces the buffer size.
	 * <p>
	 * When the number of lines in the document exceeds the high water mark, the
	 * beginning of the document is trimmed until the number of lines equals the low
	 * water mark.
	 * </p>
	 */
	private void checkBufferSize() {
		if (document != null && highWaterMark > 0) {
			int length = document.getLength();
			if (length > highWaterMark) {
				if (trimJob.getState() == Job.NONE) { // if the job isn't already running
					trimJob.setOffset(length - lowWaterMark);
					trimJob.schedule();
				}
			}
		}
	}

	/**
	 * Clears the console content.
	 */
	public void clearBuffer() {
		trimJob.setOffset(-1);
		trimJob.schedule();
	}

	@Override
	public IRegion documentChanged2(DocumentEvent event) {
		try {
			if (document != event.getDocument()) {
				log(IStatus.WARNING, "IOConsolePartitioner is connected to wrong document."); //$NON-NLS-1$
				return null;
			}
			if (document.getLength() == 0) { // document cleared
				synchronized (partitions) {
					partitions.clear();
					inputPartitions.clear();
					outputOffset = 0;
				}
				return new Region(0, 0);
			}

			synchronized (partitions) {
				switch (updateType) {
				case INPUT:
					if (event.getOffset() <= outputOffset) { // move output offset if necessary
						outputOffset -= Math.min(event.getLength(), outputOffset - event.getOffset());
						if (event.getText() != null) {
							outputOffset += event.getText().length();
						}
					}
					return applyUserInput(event);

				// update and trim jobs are triggered by this partitioner and all partitioning
				// changes are applied separately
				case OUTPUT:
					return changedRegion;
				case TRIM:
					return null; // trim does not change partition types

				default:
					log(IStatus.ERROR, "Invalid enum value " + updateType); //$NON-NLS-1$
					return null;
				}
			}
		} finally {
			// always reset type since all change events not triggered by this partitioner
			// are interpreted as user input
			updateType = DocUpdateType.INPUT;
		}
	}

	/**
	 * Update partitioning due to document change. All document change events not
	 * triggered by this partitioner are considered user input and therefore
	 * partitioned as input.
	 * <p>
	 * This method does not care if the document event removed or replaced parts of
	 * read-only partitions. It assumes manipulating read-only partitions is valid
	 * or is blocked before this method is used.
	 * </p>
	 *
	 * @param event the event describing the document change
	 * @return the region of the document in which the partition type changed or
	 *         <code>null</code>
	 */
	// Required for a false 'resource not closed' warning on inputStream.
	// This input stream must not be closed by this method.
	@SuppressWarnings("resource")
	private IRegion applyUserInput(DocumentEvent event) {
		final int eventTextLength = event.getText() != null ? event.getText().length() : 0;
		final int offset = event.getOffset();
		final int amountDeleted = event.getLength();
		final IOConsoleInputStream inputStream = console.getInputStream(); // do not close this stream

		if (amountDeleted == 0 && eventTextLength == 0) {
			// event did not changed document
			return null;
		}

		final int eventPartitionIndex = findPartitionCandidate(offset);
		int lastPartitionWithValidOffset = eventPartitionIndex;

		if (amountDeleted > 0 && eventPartitionIndex >= 0) {
			// adjust length of all partitions affected by replace/remove event
			int toDelete = amountDeleted;
			for (int i = eventPartitionIndex; i < partitions.size() && toDelete > 0; i++) {
				final IOConsolePartition partition = partitions.get(i);
				final int removeLength = Math.min(partition.getLength(), toDelete);
				partition.setLength(partition.getLength() - removeLength);
				toDelete -= removeLength;
			}
			if (ASSERT) {
				Assert.isTrue(toDelete == 0, "Tried to delete outside partitioned range."); //$NON-NLS-1$
			}
			lastPartitionWithValidOffset--; // update one more since first affected partition may be empty now
		}

		if (eventTextLength > 0) {
			// find best partition for event text
			int inputPartitionIndex = eventPartitionIndex;
			IOConsolePartition inputPartition = getPartitionByIndex(inputPartitionIndex);
			if (inputPartition != null && inputPartition.isReadOnly() && offset == inputPartition.getOffset()) {
				// if we could not reuse partition at event offset we may append the partition
				// right before our event offset (e.g. if input is at end of document)
				inputPartitionIndex--;
				lastPartitionWithValidOffset--;
				inputPartition = getPartitionByIndex(inputPartitionIndex);
			}

			// process event text in parts split on line delimiters
			int textOffset = 0;
			while (textOffset < eventTextLength) {
				final Match nextNewline = legalLineDelimiterMatcher.indexOf(event.getText(), textOffset);
				final int newTextOffset = nextNewline != null ? nextNewline.getOffset() + nextNewline.getText().length()
						: eventTextLength;
				final int inputLength = newTextOffset - textOffset;

				if (inputPartition == null || inputPartition.isReadOnly()) {
					final int inputOffset = offset + textOffset;
					if (inputPartition != null
							&& inputOffset < inputPartition.getOffset() + inputPartition.getLength()) {
						// input is inside an existing read-only partition
						splitPartition(inputOffset);
					}
					inputPartition = new IOConsolePartition(inputOffset, inputStream);
					inputPartitionIndex++;
					partitions.add(inputPartitionIndex, inputPartition);
					inputPartitions.add(inputPartition);
					lastPartitionWithValidOffset++; // new input partitions get build with correct offsets
				}

				inputPartition.setLength(inputPartition.getLength() + inputLength);

				if (nextNewline != null) {
					inputPartitions.sort(CMP_REGION_BY_OFFSET);
					final StringBuilder inputLine = new StringBuilder();
					for (IOConsolePartition p : inputPartitions) {
						try {
							final String fragment = document.get(p.getOffset(), p.getLength());
							inputLine.append(fragment);
						} catch (BadLocationException e) {
							log(e);
						}
						p.setReadOnly();
					}
					inputPartitions.clear();
					if (ASSERT) {
						Assert.isTrue(inputLine.length() > 0);
					}
					if (inputStream != null) {
						inputStream.appendData(inputLine.toString());
					}
				}
				Assert.isTrue(newTextOffset > textOffset); // can prevent infinity loop
				textOffset = newTextOffset;
			}
		}

		// repair partition offsets
		int newOffset = 0;
		if (lastPartitionWithValidOffset >= 0) {
			// reduce number of partition to update by skipping still valid entries
			final IOConsolePartition partition = partitions.get(lastPartitionWithValidOffset);
			newOffset = partition.getOffset() + partition.getLength();
		}
		final Iterator<IOConsolePartition> it = partitions.listIterator(lastPartitionWithValidOffset + 1);
		while (it.hasNext()) {
			final IOConsolePartition partition = it.next();
			if (partition.getLength() <= 0) {
				if (ASSERT) {
					Assert.isTrue(partition.getLength() == 0);
				}
				it.remove();
				if (isInputPartition(partition)) {
					final boolean removed = inputPartitions.remove(partition);
					if (ASSERT) {
						Assert.isTrue(removed);
					}
				}
			} else {
				partition.setOffset(newOffset);
				newOffset += partition.getLength();
			}
		}

		if (ASSERT) {
			checkPartitions();
		}
		return new Region(0, document.getLength());
	}

	/**
	 * Split an existing partition at offset. The offset must not be the first or
	 * last offset of the existing partition because this leads to empty partitions
	 * not bearable by this partitioner.
	 * <p>
	 * New partition is added to {@link #partitions} (always) and
	 * {@link #inputPartitions} (if applicable).
	 * </p>
	 *
	 * @param offset the offset where the existing partition will end after split
	 *               and a new partition will start
	 * @return the newly created partition (i.e. the right side of the split)
	 */
	private IOConsolePartition splitPartition(int offset) {
		final int partitionIndex = findPartitionCandidate(offset);
		final IOConsolePartition existingPartition = partitions.get(partitionIndex);
		final IOConsolePartition newPartition;
		if (isInputPartition(existingPartition)) {
			newPartition = new IOConsolePartition(offset, existingPartition.getInputStream());
			if (existingPartition.isReadOnly()) {
				newPartition.setReadOnly();
			}
			if (inputPartitions.contains(existingPartition)) {
				inputPartitions.add(newPartition);
			}
		} else {
			newPartition = new IOConsolePartition(offset, existingPartition.getOutputStream());
		}
		newPartition.setLength((existingPartition.getOffset() + existingPartition.getLength()) - offset);
		existingPartition.setLength(offset - existingPartition.getOffset());
		partitions.add(partitionIndex + 1, newPartition);
		return newPartition;
	}

	/**
	 * A stream has been appended, add to pendingPartions list and schedule
	 * updateJob. updateJob is scheduled with a slight delay, this allows the
	 * console to run the job less frequently and update the document with a greater
	 * amount of data each time the job is run
	 *
	 * @param stream The stream that was written to.
	 * @param s      The string that should be appended to the document.
	 * @throws IOException if partitioner is not connected to a document
	 */
	public void streamAppended(IOConsoleOutputStream stream, String s) throws IOException {
		if (document == null) {
			throw new IOException("Document is closed"); //$NON-NLS-1$
		}
		if (s == null) {
			return;
		}
		synchronized (pendingPartitions) {
			final PendingPartition lastPending = pendingPartitions.size() > 0
					? pendingPartitions.get(pendingPartitions.size() - 1)
					: null;
			if (lastPending != null && lastPending.stream == stream) {
				lastPending.append(s);
			} else {
				pendingPartitions.add(new PendingPartition(stream, s));
			}

			if (pendingSize > 1000) {
				queueJob.schedule();
			} else {
				queueJob.schedule(50);
			}

			if (pendingSize > 160000) {
				if (Display.getCurrent() == null) {
					try {
						pendingPartitions.wait();
					} catch (InterruptedException e) {
					}
				} else {
					// if we are in UI thread we cannot lock it, so process queued output.
					processPendingPartitions();
				}
			}
		}
	}

	/**
	 * Holds data until updateJob can be run and the document can be updated.
	 */
	private class PendingPartition {
		StringBuilder text = new StringBuilder(8192);
		IOConsoleOutputStream stream;

		PendingPartition(IOConsoleOutputStream stream, String text) {
			this.stream = stream;
			append(text);
		}

		void append(String moreText) {
			text.append(moreText);
			pendingSize += moreText.length();
		}
	}

	/**
	 * Updates the document and partitioning structure. Will append everything
	 * received from output streams that is available before finishing.
	 */
	private class QueueProcessingJob extends UIJob {

		QueueProcessingJob() {
			super("IOConsole Updater"); //$NON-NLS-1$
			setSystem(true);
			setPriority(Job.INTERACTIVE);
		}

		@Override
		public IStatus runInUIThread(IProgressMonitor monitor) {
			processPendingPartitions();
			if (ASSERT) {
				checkPartitions();
			}
			return Status.OK_STATUS;
		}

		/*
		 * Job will process as much as it can each time it's run, but it gets scheduled
		 * everytime a PendingPartition is added to the list, meaning that this job
		 * could get scheduled unnecessarily in cases of heavy output. Note however,
		 * that schedule() will only reschedule a running/scheduled Job once even if
		 * it's called many times.
		 */
		@Override
		public boolean shouldRun() {
			synchronized (pendingPartitions) {
				final boolean shouldRun = pendingPartitions.size() > 0;
				return shouldRun;
			}
		}
	}

	/**
	 * Process {@link #pendingPartitions}, append their content to document and
	 * update partitioning.
	 */
	private void processPendingPartitions() {
		final List<PendingPartition> pendingCopy;
		final int size;
		synchronized (pendingPartitions) {
			pendingCopy = new ArrayList<>(pendingPartitions);
			size = pendingSize;
			pendingPartitions.clear();
			pendingSize = 0;
			pendingPartitions.notifyAll();
		}
		synchronized (partitions) {
			if (isHandleControlCharacters()) {
				applyStreamOutput(pendingCopy, size);
			} else {
				// Old implementation of output appending. The control character aware variant
				// {@link #applyStreamOutput(List, int)} should do exactly the same if control
				// character processing is disabled but since there is not so much time for
				// testing in current development cycle the old implementation is used to
				// process output when control character interpretation is disabled.
				// TODO remove in next development cycle
				final StringBuilder addedContent = new StringBuilder(size);
				IOConsolePartition lastPartition = getPartitionByIndex(partitions.size() - 1);
				int nextOffset = document.getLength();
				for (PendingPartition pendingPartition : pendingCopy) {
					if (lastPartition == null || lastPartition.getOutputStream() != pendingPartition.stream) {
						lastPartition = new IOConsolePartition(nextOffset, pendingPartition.stream);
						partitions.add(lastPartition);
					}
					final int pendingLength = pendingPartition.text.length();
					lastPartition.setLength(lastPartition.getLength() + pendingLength);
					nextOffset += pendingLength;
					addedContent.append(pendingPartition.text);
				}
				try {
					updateType = DocUpdateType.OUTPUT;
					document.replace(document.getLength(), 0, addedContent.toString());
					outputOffset += addedContent.length();
				} catch (BadLocationException e) {
					log(e);
				}
			}
		}
		checkFinished();
		checkBufferSize();
	}

	/**
	 * Apply content collected in pending partitions to document and update
	 * partitioning structure.
	 * <p>
	 * This method is also responsible to interpret control characters if enabled
	 * (see {@link #isHandleControlCharacters()}).
	 * </p>
	 *
	 * @param pendingCopy the pending partitions to process
	 * @param sizeHint    a hint for expected content length to initialize buffer
	 *                    size. Does not have to be exact as long as it is not
	 *                    negative.
	 */
	private void applyStreamOutput(List<PendingPartition> pendingCopy, int sizeHint) {
		// local reference to get consistent parsing without blocking pattern changes
		final Pattern controlPattern = controlCharacterPattern;
		// Variables to collect required data to reduce number of document updates. The
		// partitioning must be updated in smaller iterations as the actual document
		// content. E.g. pending partitions are distinct on source output stream
		// resulting in multiple partitions but if all the content is appended to the
		// document there is only one update required to add the actual content.
		int nextWriteOffset = outputOffset;
		final StringBuilder content = new StringBuilder(sizeHint);
		int replaceLength = 0;
		// the partition which contains the current output offset
		IOConsolePartition atOutputPartition = null;
		// the index of atOutputPartition in the partitions list
		int atOutputPartitionIndex = -1;

		for (PendingPartition pending : pendingCopy) {
			// create matcher to find control characters in pending content (if enabled)
			final Matcher controlCharacterMatcher = controlPattern != null ? controlPattern.matcher(pending.text)
					: null;

			for (int textOffset = 0; textOffset < pending.text.length();) {
				// Process pending content in chunks.
				// Processing is primary split on control characters since there interpretation
				// is easier if all content changes before are already applied.
				// Additional processing splits may result while overwriting existing output and
				// overwrite overlaps partitions.
				final boolean foundControlCharacter;
				final int partEnd;
				if (controlCharacterMatcher != null && controlCharacterMatcher.find()) {
					if (ASSERT) {
						// check used pattern. Assert it matches only sequences of same characters.
						final String match = controlCharacterMatcher.group();
						Assert.isTrue(match.length() > 0);
						final char matchedChar = match.charAt(0);
						for (char c : match.toCharArray()) {
							Assert.isTrue(c == matchedChar);
						}
					}
					partEnd = controlCharacterMatcher.start();
					foundControlCharacter = true;
				} else {
					partEnd = pending.text.length();
					foundControlCharacter = false;
				}

				while (textOffset < partEnd) {
					// Process content part. This part never contains control characters.
					// Processing may require multiple iterations if we overwrite existing content
					// which consists of distinct partitions.

					if (outputOffset >= document.getLength()) {
						// content is appended to document end (the easy case)
						if (atOutputPartition == null) {
							// get the last existing partition to try to expand it
							atOutputPartitionIndex = partitions.size() - 1;
							atOutputPartition = getPartitionByIndex(atOutputPartitionIndex);
							if (ASSERT) {
								Assert.isTrue(atOutputPartitionIndex == findPartitionCandidate(outputOffset - 1));
							}
						}
						if (atOutputPartition == null || atOutputPartition.getOutputStream() != pending.stream) {
							// no partitions yet or last partition is incompatible to reuse -> add new one
							atOutputPartition = new IOConsolePartition(outputOffset, pending.stream);
							partitions.add(atOutputPartition);
							atOutputPartitionIndex = partitions.size() - 1;
						}
						final int appendedLength = partEnd - textOffset;
						content.append(pending.text, textOffset, partEnd);
						atOutputPartition.setLength(atOutputPartition.getLength() + appendedLength);
						outputOffset += appendedLength;
						textOffset = partEnd;
					} else {
						// content overwrites existing console content (the tricky case)
						if (atOutputPartition == null) {
							// find partition where output will overwrite or create one if unpartitioned
							atOutputPartitionIndex = findPartitionCandidate(outputOffset);
							atOutputPartition = getPartitionByIndex(atOutputPartitionIndex);
							if (atOutputPartition == null) {
								atOutputPartition = new IOConsolePartition(outputOffset, pending.stream);
								atOutputPartitionIndex++;
								partitions.add(atOutputPartitionIndex, atOutputPartition);
							}
						}

						// we do not overwrite input partitions at the moment so they need to be skipped
						if (isInputPartition(atOutputPartition)) {
							outputOffset = atOutputPartition.getOffset() + atOutputPartition.getLength();
							atOutputPartitionIndex++;
							atOutputPartition = getPartitionByIndex(atOutputPartitionIndex);

							// apply document changes collected until now
							applyOutputToDocument(content.toString(), nextWriteOffset, replaceLength);
							content.setLength(0);
							replaceLength = 0;
							nextWriteOffset = outputOffset;
							continue; // to check if next selected partition is also input or appending now
						}

						// limit chunks to overwrite only one existing partition at a time
						final int chunkLength = Math.min(partEnd - textOffset,
								atOutputPartition.getLength() - (outputOffset - atOutputPartition.getOffset()));
						Assert.isTrue(chunkLength > 0); // do not remove since it can prevent an infinity loop

						if (atOutputPartition.getOutputStream() != pending.stream) {
							// new output is from other stream then overwritten output

							// Note: this implementation ignores the possibility to reuse the partition
							// where the overwrite chunk ends and expand it towards replace begin since this
							// makes things code much more complex. In some cases this may leads to
							// consecutive partitions which could be merged to one partition. Merging is not
							// implemented at the moment.

							// in this part outputPartition is used to partition the new content
							// and atOutputPartition points to the partition whose content is overwritten
							// i.e. the new partition grows and the old one must shrink
							IOConsolePartition outputPartition = null;
							if (atOutputPartition.getOffset() == outputOffset) {
								// try to expand the partition before our output offset
								outputPartition = getPartitionByIndex(atOutputPartitionIndex - 1);
							} else {
								// overwrite starts inside existing incompatible partition
								atOutputPartition = splitPartition(outputOffset);
								atOutputPartitionIndex++;
							}
							if (outputPartition == null || outputPartition.getOutputStream() != pending.stream) {
								outputPartition = new IOConsolePartition(outputOffset, pending.stream);
								partitions.add(atOutputPartitionIndex, outputPartition);
								atOutputPartitionIndex++;
							}

							// update partitioning of the overwritten chunk
							outputPartition.setLength(outputPartition.getLength() + chunkLength);
							atOutputPartition.setOffset(atOutputPartition.getOffset() + chunkLength);
							atOutputPartition.setLength(atOutputPartition.getLength() - chunkLength);

							if (atOutputPartition.getLength() == 0) {
								// overwritten partition is now empty and must be be removed
								partitions.remove(atOutputPartitionIndex);
								atOutputPartition = getPartitionByIndex(atOutputPartitionIndex);
							}
						}
						content.append(pending.text, textOffset, textOffset + chunkLength);
						replaceLength += chunkLength;
						textOffset += chunkLength;
						outputOffset += chunkLength;
						if (atOutputPartition != null
								&& outputOffset == atOutputPartition.getOffset() + atOutputPartition.getLength()) {
							atOutputPartitionIndex++;
							atOutputPartition = getPartitionByIndex(atOutputPartitionIndex);
						}
					}
				}
				// finished processing of regular content before control characters
				// now interpret control characters if any
				if (controlCharacterMatcher != null && foundControlCharacter) {
					// at first update console document since it is easier to interpret control
					// characters on an up-to-date document and partitioning
					applyOutputToDocument(content.toString(), nextWriteOffset, replaceLength);
					content.setLength(0);
					replaceLength = 0;

					final String controlCharacterMatch = controlCharacterMatcher.group();
					final char controlCharacter = controlCharacterMatch.charAt(0);
					switch (controlCharacter) {
					case '\b':
						// move virtual output cursor one step back for each \b
						// but stop at current line start and skip any input partitions
						final int outputLineStartOffset = findOutputLineStartOffset(outputOffset);
						int backStepCount = controlCharacterMatch.length();
						if (partitions.size() == 0) {
							outputOffset = 0;
							break;
						}
						if (atOutputPartition == null) {
							atOutputPartitionIndex = partitions.size() - 1;
							atOutputPartition = getPartitionByIndex(atOutputPartitionIndex);
						}
						while (backStepCount > 0 && outputOffset > outputLineStartOffset) {
							if (atOutputPartition != null && isInputPartition(atOutputPartition)) {
								do {
									outputOffset = atOutputPartition.getOffset() - 1;
									atOutputPartitionIndex--;
									atOutputPartition = getPartitionByIndex(atOutputPartitionIndex);
								} while (atOutputPartition != null && isInputPartition(atOutputPartition));
								backStepCount--;
							}
							if (atOutputPartition == null) {
								outputOffset = 0;
								break;
							}
							final int backSteps = Math.min(outputOffset - atOutputPartition.getOffset(), backStepCount);
							outputOffset -= backSteps;
							backStepCount -= backSteps;
							atOutputPartitionIndex--;
							atOutputPartition = getPartitionByIndex(atOutputPartitionIndex);
						}
						outputOffset = Math.max(outputOffset, outputLineStartOffset);
						break;

					case '\r':
						// move virtual output cursor to start of output line
						outputOffset = findOutputLineStartOffset(outputOffset);
						atOutputPartitionIndex = -1;
						atOutputPartition = null;
						break;

					default:
						// should never happen as long as the used regex pattern is valid
						log(IStatus.ERROR, "No implementation to handle control character 0x" //$NON-NLS-1$
								+ Integer.toHexString(controlCharacter));
						break;
					}
					nextWriteOffset = outputOffset;
					textOffset = controlCharacterMatcher.end();
				}
			}
		}
		applyOutputToDocument(content.toString(), nextWriteOffset, replaceLength);
	}

	/**
	 * Find offset of line start from given output offset. This method ignores line
	 * breaks partitioned as input. I.e. it looks at the document as if it only
	 * consist of the output parts.
	 *
	 * @param outOffset offset where output should be written
	 * @return the start offset of line where output should be written
	 */
	private int findOutputLineStartOffset(int outOffset) {
		int outputLineStartOffset = 0;
		try {
			for (int lineIndex = document.getLineOfOffset(outOffset); lineIndex >= 0; lineIndex--) {
				outputLineStartOffset = document.getLineOffset(lineIndex);
				final IOConsolePartition lineBreakPartition = getIOPartition(outputLineStartOffset - 1);
				if (lineBreakPartition == null || !isInputPartition(lineBreakPartition)) {
					break;
				}
			}
		} catch (BadLocationException e) {
			log(e);
			outputLineStartOffset = 0;
		}
		if (ASSERT) {
			Assert.isTrue(outputLineStartOffset <= outOffset);
		}
		return outputLineStartOffset;
	}

	/**
	 * Apply content from output streams to document. It expects the partitioning
	 * has or will update partitioning to reflect the change since it prevents this
	 * partitioner's {@link #documentChanged2(DocumentEvent)} method from changing
	 * partitioning.
	 *
	 * @param content       collected content from output streams
	 * @param offset        offset where content is inserted
	 * @param replaceLength length of overwritten old output
	 */
	private void applyOutputToDocument(String content, int offset, int replaceLength) {
		if (content.length() > 0 || replaceLength > 0) {
			if (ASSERT) {
				Assert.isTrue(replaceLength <= content.length());
			}
			try {
				updateType = DocUpdateType.OUTPUT;
				document.replace(offset, replaceLength, content);
			} catch (BadLocationException e) {
				log(e);
			}
		}
	}

	/**
	 * Job to trim the console document, runs in the UI thread.
	 */
	private class TrimJob extends WorkbenchJob {

		/**
		 * Trims output up to the line containing the given offset, or all output if -1.
		 */
		private int truncateOffset;

		/**
		 * Creates a new job to trim the buffer.
		 */
		TrimJob() {
			super("Trim Job"); //$NON-NLS-1$
			setSystem(true);
		}

		/**
		 * Sets the trim offset.
		 *
		 * @param offset trims output up to the line containing the given offset
		 */
		public void setOffset(int offset) {
			truncateOffset = offset;
		}

		@Override
		public IStatus runInUIThread(IProgressMonitor monitor) {
			synchronized (partitions) {
				if (document == null) {
					return Status.OK_STATUS;
				}

				int length = document.getLength();
				if (truncateOffset < length) {
					try {
						if (truncateOffset < 0) {
							// clear
							updateType = DocUpdateType.TRIM;
							document.set(""); //$NON-NLS-1$
						} else {
							// overflow
							int cutoffLine = document.getLineOfOffset(truncateOffset);
							int cutOffset = document.getLineOffset(cutoffLine);

							// set the new length of the first partition
							IOConsolePartition partition = (IOConsolePartition) getPartition(cutOffset);
							partition.setLength(partition.getOffset() + partition.getLength() - cutOffset);

							updateType = DocUpdateType.TRIM;
							document.replace(0, cutOffset, ""); //$NON-NLS-1$

							// remove partitions and reset Partition offsets
							int index = partitions.indexOf(partition);
							for (int i = 0; i < index; i++) {
								partitions.remove(0);
							}

							int offset = 0;
							for (IOConsolePartition p : partitions) {
								p.setOffset(offset);
								offset += p.getLength();
							}

							// fix output offset
							int removedLength = cutOffset;
							outputOffset = Math.max(outputOffset - removedLength, 0);
						}
						if (ASSERT) {
							checkPartitions();
						}
					} catch (BadLocationException e) {
					}
				}
			}
			return Status.OK_STATUS;
		}
	}

	@Override
	public boolean isReadOnly(int offset) {
		final IOConsolePartition partition = getIOPartition(offset);
		return partition != null ? partition.isReadOnly() : true;
	}

	@Override
	public StyleRange[] getStyleRanges(int offset, int length) {
		final IOConsolePartition[] computedPartitions = computeIOPartitioning(offset, length);
		final StyleRange[] styles = new StyleRange[computedPartitions.length];
		for (int i = 0; i < computedPartitions.length; i++) {
			int rangeStart = computedPartitions[i].getOffset();
			int rangeLength = computedPartitions[i].getLength();

			// snap partitions to requested range
			final int underflow = offset - rangeStart;
			if (underflow > 0) {
				rangeStart += underflow;
				rangeLength -= underflow;
			}
			final int overflow = (rangeStart + rangeLength) - (offset + length);
			if (overflow > 0) {
				rangeLength -= overflow;
			}

			styles[i] = computedPartitions[i].getStyleRange(rangeStart, rangeLength);
		}
		return styles;
	}

	@Override
	public ITypedRegion[] computeReadOnlyPartitions() {
		if (document == null) {
			return new IOConsolePartition[0];
		}
		return computeReadOnlyPartitions(0, document.getLength());
	}

	@Override
	public ITypedRegion[] computeReadOnlyPartitions(int offset, int length) {
		return computePartitioning(offset, length, false, true);
	}

	@Override
	public ITypedRegion[] computeWritablePartitions() {
		if (document == null) {
			return new IOConsolePartition[0];
		}
		return computeWritablePartitions(0, document.getLength());
	}

	@Override
	public ITypedRegion[] computeWritablePartitions(int offset, int length) {
		return computePartitioning(offset, length, true, false);
	}

	@Override
	public boolean isReadOnly(int offset, int length) {
		final ITypedRegion[] readOnlyRegions = computeReadOnlyPartitions(offset, length);
		int o = offset;
		int end = offset + length;
		for (ITypedRegion readOnlyRegion : readOnlyRegions) {
			if (o < readOnlyRegion.getOffset()) {
				return false;
			}
			o += readOnlyRegion.getLength();
			if (o >= end) {
				return true;
			}
		}
		return false;
	}

	@Override
	public boolean containsReadOnly(int offset, int length) {
		return computeReadOnlyPartitions(offset, length).length > 0;
	}

	@Override
	public int getPreviousOffsetByState(int offset, boolean searchWritable) {
		synchronized (partitions) {
			int partitionIndex = findPartitionCandidate(offset);
			for (; partitionIndex >= 0; partitionIndex--) {
				final IOConsolePartition partition = partitions.get(partitionIndex);
				if (partition.isReadOnly() != searchWritable) {
					return Math.min(partition.getOffset() + partition.getLength() - 1, offset);
				}
			}
		}
		return -1;
	}

	@Override
	public int getNextOffsetByState(int offset, boolean searchWritable) {
		synchronized (partitions) {
			int partitionIndex = findPartitionCandidate(offset);
			if (partitionIndex >= 0) {
				for (; partitionIndex < partitions.size(); partitionIndex++) {
					final IOConsolePartition partition = partitions.get(partitionIndex);
					if (partition.isReadOnly() != searchWritable) {
						return Math.max(partition.getOffset(), offset);
					}
				}
			}
		}
		return document != null ? document.getLength() : 0;
	}

	/**
	 * Check if console currently interprets ASCII control characters.
	 *
	 * @return <code>true</code> if console interprets ASCII control characters
	 * @since 3.9
	 */
	public boolean isHandleControlCharacters() {
		return controlCharacterPattern != null;
	}

	/**
	 * Enable or disable interpretation of ASCII control characters like backspace
	 * (<code>\b</code>).
	 *
	 * @param handleControlCharacters interpret control characters if
	 *                                <code>true</code>
	 * @since 3.9
	 */
	public void setHandleControlCharacters(boolean handleControlCharacters) {
		if (handleControlCharacters) {
			controlCharacterPattern = Pattern
					.compile(carriageReturnAsControlCharacter ? CONTROL_CHARACTERS_WITH_CR_PATTERN_STR
							: CONTROL_CHARACTERS_PATTERN_STR);
		} else {
			controlCharacterPattern = null;
		}
	}

	/**
	 * Check if carriage returns (<code>\r</code>) are interpreted as control
	 * characters. They are also not interpreted if general control character
	 * handling is disabled.
	 *
	 * @return if <code>true</code> carriage returns are interpreted as control
	 *         characters.
	 * @see #isHandleControlCharacters()
	 * @since 3.9
	 */
	public boolean isCarriageReturnAsControlCharacter() {
		return carriageReturnAsControlCharacter;
	}

	/**
	 * If control characters are interpreted by this console carriage returns
	 * (<code>\r</code>) are either ignored (<code>false</code>) and usually handled
	 * as line break by connected console document or if <code>true</code>
	 * interpreted with there control character meaning.
	 * <p>
	 * Note: this option has no effect if control character interpretation is
	 * disabled in general.
	 * </p>
	 *
	 * @param carriageReturnAsControlCharacter set <code>false</code> to exclude
	 *                                         carriage return from control
	 *                                         character interpretation
	 * @see #setHandleControlCharacters(boolean)
	 * @since 3.9
	 */
	public void setCarriageReturnAsControlCharacter(boolean carriageReturnAsControlCharacter) {
		this.carriageReturnAsControlCharacter = carriageReturnAsControlCharacter;
		// reset to update control character pattern
		setHandleControlCharacters(isHandleControlCharacters());
	}

	/**
	 * Get a partition by its index. Safe from out of bounds exceptions.
	 *
	 * @param index index of requested partition
	 * @return the requested partition or <code>null</code> if index is invalid
	 */
	private IOConsolePartition getPartitionByIndex(int index) {
		return (index >= 0 && index < partitions.size()) ? partitions.get(index) : null;
	}

	/**
	 * Check if given partition is from type input partition.
	 *
	 * @param partition partition to check (not <code>null</code>)
	 * @return true if partition is an input partition
	 */
	private static boolean isInputPartition(IOConsolePartition partition) {
		return IOConsolePartition.INPUT_PARTITION_TYPE.equals(partition.getType());
	}

	private static void log(Throwable t) {
		ConsolePlugin.log(t);
	}

	private static void log(int status, String msg) {
		ConsolePlugin.log(new Status(status, ConsolePlugin.getUniqueIdentifier(), msg));
	}

	/**
	 * For debug purpose. Check if whole document is partitioned, partitions are
	 * ordered by offset, every partition has length greater 0 and all writable
	 * input partitions are listed in {@link #inputPartitions}.
	 */
	private void checkPartitions() {
		if (document == null) {
			return;
		}
		synchronized (partitions) {
			final List<IOConsolePartition> knownInputPartitions = new ArrayList<>(inputPartitions);
			int offset = 0;
			for (IOConsolePartition partition : partitions) {
				Assert.isTrue(offset == partition.getOffset());
				Assert.isTrue(partition.getLength() > 0);
				offset += partition.getLength();

				if (isInputPartition(partition) && !partition.isReadOnly()) {
					Assert.isTrue(knownInputPartitions.remove(partition));
				}
			}
			Assert.isTrue(offset == document.getLength());
			Assert.isTrue(knownInputPartitions.isEmpty());
		}
	}
}
