/*=============================================================================#
 # Copyright (c) 2000, 2017 IBM Corporation and others.
 # 
 # This program and the accompanying materials are made available under the
 # terms of the Eclipse Public License 2.0 which is available at
 # https://www.eclipse.org/legal/epl-2.0.
 # 
 # SPDX-License-Identifier: EPL-2.0
 # 
 # Contributors:
 #     IBM Corporation - org.eclipse.ui.console: initial API and implementation
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.internal.nico.ui.console;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.text.AbstractDocument;
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.Region;
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.progress.WorkbenchJob;

import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.collections.ImList;

import org.eclipse.statet.nico.ui.console.NIConsole;
import org.eclipse.statet.nico.ui.console.NIConsoleOutputStream;


/**
 * Partitioner for a NIConsole's document.
 */
public class NIConsolePartitioner implements IConsoleDocumentPartitioner, IDocumentPartitionerExtension {
	
	
	/**
	 * Holds data until updateJob can be run and the document can be updated.
	 */
	final class PendingPartition {
		
		
		private final NIConsoleOutputStream stream;
		
		private final StringBuilder text;
		
		
		PendingPartition(final NIConsoleOutputStream stream, final String text) {
			this.stream= stream;
			this.text= new StringBuilder(Math.max(4, 2 + (text.length()/1014)) * 1024);
			append(text);
		}
		
		
		public NIConsoleOutputStream getStream() {
			return this.stream;
		}
		
		public StringBuilder getText() {
			return this.text;
		}
		
		private void append(final String text) {
			this.text.append(text);
			NIConsolePartitioner.this.pendingTextLength+= text.length();
		}
		
	}
	
	
	private final NIConsole console;
	
	private final String[] partitionIds;
	
	private AbstractDocument document;
	
	private boolean isConnected= false;
	
	private final ArrayList<NIConsolePartition> partitions= new ArrayList<>();
	
	/**
	 * The last partition appended to the document
	 */
	private NIConsolePartition lastPartition;
	
	/**
	 * Blocks of data that have not yet been appended to the document.
	 */
	private final ArrayList<PendingPartition> pendingPartitions= new ArrayList<>();
	
	private int pendingTextLength; 
	
	/**
	 * A list of PendingPartitions to be appended by the updateJob
	 */
	private ImList<PendingPartition> updatePartitions;
	
	private final QueueProcessingJob queueJob= new QueueProcessingJob();
	
	private final TrimJob trimJob= new TrimJob();
	
	/**
	 * Flag to indicate that the updateJob is updating the document.
	 */
	private boolean updateInProgress;
	/**
	 * offset used by updateJob
	 */
	private final StreamProcessor streamProcessor;
	
	
	/**
	 * An array of legal line delimiters
	 */
	private int highWaterMark= -1;
	private int lowWaterMark= -1;
	
	/**
	 * Lock for appending to and removing from the document - used
	 * to synchronize addition of new text/partitions in the update
	 * job and handling buffer overflow/clearing of the console. 
	 */
	private final Object overflowLock= new Object();
	
	
	public NIConsolePartitioner(final NIConsole console, final List<String> ids) {
		this.console= console;
		this.streamProcessor= new StreamProcessor(this);
		this.partitionIds= ids.toArray(new String[ids.size()]);
		this.trimJob.setRule(console.getSchedulingRule());
		
		this.queueJob.setRule(this.console.getSchedulingRule());
	}
	
	
	public NIConsole getConsole() {
		return this.console;
	}
	
	public AbstractDocument getDocument() {
		return this.document;
	}
	
	NIConsolePartition getLastPartition() {
		return this.lastPartition;
	}
	
	
	@Override
	public void connect(final IDocument doc) {
		this.document= (AbstractDocument) doc;
		this.document.setDocumentPartitioner(this);
		
		this.isConnected= true;
	}
	
	public int getHighWaterMark() {
		return this.highWaterMark;
	}
	
	public int getLowWaterMark() {
		return this.lowWaterMark;
	}
	
	public void setWaterMarks(final int low, final int high) {
		this.lowWaterMark= low;
		this.highWaterMark= high;
		ConsolePlugin.getStandardDisplay().asyncExec(new Runnable() {
			@Override
			public void run() {
				checkBufferSize();
			}
		});
	}
	
	/**
	 * Notification from the console that all of its streams have been closed.
	 */
	public void finish() {
		synchronized (this.pendingPartitions) {
			this.pendingPartitions.add(null);
		}
		this.queueJob.schedule(); //ensure that all pending partitions are processed.
	}
	
	@Override
	public void disconnect() {
		synchronized (this.overflowLock) {
			this.isConnected= false;
			this.document= null;
			this.partitions.clear();
		}
	}
	
	@Override
	public void documentAboutToBeChanged(final DocumentEvent event) {
	}
	
	@Override
	public boolean documentChanged(final DocumentEvent event) {
		return documentChanged2(event) != null;
	}
	
	@Override
	public String[] getLegalContentTypes() {
		return this.partitionIds;
	}
	
	@Override
	public String getContentType(final int offset) {
		return getPartition(offset).getType();
	}
	
	@Override
	public ITypedRegion[] computePartitioning(final int offset, final int length) {
		final int rangeEnd= offset + length;
		int left= 0;
		int right= this.partitions.size() - 1;
		int mid= 0;
		NIConsolePartition position= null;
		
		if (right <= 0) {
			if (right == 0) {
				return new NIConsolePartition[] { this.partitions.get(0) };
			}
			return new NIConsolePartition[0];
		}
		while (left < right) {
			mid= (left + right) / 2;
			position= this.partitions.get(mid);
			if (rangeEnd < position.getOffset()) {
				if (left == mid) {
					right= left;
				} else {
					right= mid -1;
				}
			}
			else if (offset > (position.getOffset() + position.getLength() - 1)) {
				if (right == mid) {
					left= right;
				} else {
					left= mid  +1;
				}
			}
			else {
				left= right= mid;
			}
		}
		
		final List<NIConsolePartition> list= new ArrayList<>();
		int index= left - 1;
		if (index >= 0) {
			position= this.partitions.get(index);
			while (index >= 0 && (position.getOffset() + position.getLength()) > offset) {
				index--;
				if (index >= 0) {
					position= this.partitions.get(index);
				}
			}
		}
		index++;
		position= this.partitions.get(index);
		while (index < this.partitions.size() && (position.getOffset() < rangeEnd)) {
			list.add(position);
			index++;
			if (index < this.partitions.size()) {
				position= this.partitions.get(index);
			}
		}
		
		return list.toArray(new NIConsolePartition[list.size()]);
	}
	
	@Override
	public ITypedRegion getPartition(final int offset) {
		for (int i= 0; i < this.partitions.size(); i++) {
			final ITypedRegion partition= this.partitions.get(i);
			final int start= partition.getOffset();
			final int end= start + partition.getLength();
			if (offset >= start && offset < end) {
				return partition;
			}
		}
		
		return (this.lastPartition != null) ? 
				this.lastPartition : new NIConsolePartition(this.partitionIds[0], null);
	}
	
	/**
	 * Enforces the buffer size.
	 * 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.
	 */
	private void checkBufferSize() {
		if (this.document != null && this.highWaterMark > 0) {
			final int length= this.document.getLength();
			if (length > this.highWaterMark) {
				if (this.trimJob.getState() == Job.NONE) { //if the job isn't already running
					this.trimJob.setOffset(length - this.lowWaterMark);
					this.trimJob.schedule();
				}
			}
		}
	}
	
	/**
	 * Clears the console
	 */
	public void clearBuffer() {
		synchronized (this.overflowLock) {
			this.trimJob.setOffset(-1);
			this.trimJob.schedule();
		}
	}
	
	@Override
	public IRegion documentChanged2(final DocumentEvent event) {
		if (this.document == null) {
			return null; //another thread disconnected the partitioner
		}
		if (this.document.getLength() == 0) { //document cleared
			this.partitions.clear();
			this.lastPartition= null;
			this.streamProcessor.clear();
			return new Region(0, 0);
		}
		
		if (this.updateInProgress) {
			if (this.updatePartitions != null) {
				int offset= this.streamProcessor.getTextOffsetInDoc();
				NIConsolePartition partition= this.lastPartition;
				for (final PendingPartition pp : this.updatePartitions) {
					if (pp != null) {
						final int ppLen= pp.text.length();
						if (partition != null) {
							if (partition.getStream() == pp.stream) {
								partition.setLength(
										offset + ppLen - partition.getOffset() );
								offset+= ppLen;
								continue;
							}
							
							if (partition.getLength() == 0) {
								final int idx= this.partitions.lastIndexOf(partition);
								if (idx >= 0) {
									this.partitions.remove(idx);
								}
							}
							partition= null;
						}
						
						if (ppLen > 0) {
							partition= new NIConsolePartition(
									pp.stream.getId(), pp.stream, offset, ppLen);
							this.partitions.add(partition);
							offset+= ppLen;
						}
					}
				}
				this.lastPartition= partition;
				this.streamProcessor.updateApplied();
			}
		}
		
		return new Region(event.fOffset, event.fText.length());
	}
	
	private void setUpdateInProgress(final boolean b) {
		this.updateInProgress= b;
	}
	
	/**
	 * 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.
	 */
	public void streamAppended(final NIConsoleOutputStream stream, final String s) throws IOException {
		if (this.document == null) {
			throw new IOException("Document is closed"); //$NON-NLS-1$
		}
		if (stream == null) {
			throw new NullPointerException("stream"); //$NON-NLS-1$
		}
		synchronized(this.pendingPartitions) {
			final PendingPartition last= (this.pendingPartitions.size() > 0 ?
					this.pendingPartitions.get(this.pendingPartitions.size() - 1) : null );
			if (last != null && last.stream == stream) {
				last.append(s);
			}
			else {
				this.pendingPartitions.add(new PendingPartition(stream, s));
				if (this.pendingTextLength > 0x1ff) {
					this.queueJob.schedule();
				} else {
					this.queueJob.schedule(50);
				}
			}
			
			if (this.pendingTextLength > 0xffff) {
				if (Display.getCurrent() == null){
					try {
						this.pendingPartitions.wait();
					}
					catch (final InterruptedException e) {
					}
				}
				else {
					/*
					 * if we are in UI thread we cannot lock it, so process
					 * queued output directly.
					 */
					processQueue();
				}
			}
		}
	}
	
	/**
	 * Updates the document. Will append everything that is available before 
	 * finishing.
	 */
	private class QueueProcessingJob extends WorkbenchJob {
		
		QueueProcessingJob() {
			super("IOConsole Updater"); //$NON-NLS-1$
			setSystem(true);
			setPriority(Job.INTERACTIVE);
		}
		
		@Override
		public IStatus runInUIThread(final IProgressMonitor monitor) {
			processQueue();
			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() {
			final boolean shouldRun= NIConsolePartitioner.this.isConnected
					&& NIConsolePartitioner.this.pendingPartitions.size() > 0;
			return shouldRun;
		}
		
	}
	
	private void processQueue() {
		synchronized (this.overflowLock) {
			final ImList<PendingPartition> pendingCopy;
			final int pendingLength;
			synchronized(this.pendingPartitions) {
				pendingCopy= ImCollections.toList(this.pendingPartitions);
				this.pendingPartitions.clear();
				pendingLength= this.pendingTextLength;
				this.pendingTextLength= 0;
				this.pendingPartitions.notifyAll();
			}
			if (pendingCopy.isEmpty()) {
				return;
			}
			
			this.streamProcessor.prepareUpdate(pendingCopy, pendingLength);
			
			if (this.isConnected) {
				setUpdateInProgress(true);
				this.updatePartitions= pendingCopy;
				try {
					this.document.replace(
							this.streamProcessor.getTextOffsetInDoc(),
							this.streamProcessor.getTextReplaceLengthInDoc(),
							this.streamProcessor.getText() );
				}
				catch (final BadLocationException e) {}
				finally {
					this.updatePartitions= null;
					setUpdateInProgress(false);
				}
			}
			
			if (this.streamProcessor.wasFinished()) {
				this.console.partitionerFinished();
			}
			
			this.streamProcessor.updateDone();
			
			checkBufferSize();
		}
	}
	
	
	/**
	 * 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(final int offset) {
			this.truncateOffset= offset;
		}
		
		@Override
		public IStatus runInUIThread(final IProgressMonitor monitor) {
			final IJobManager jobManager= Job.getJobManager();
			try {
				jobManager.join(NIConsolePartitioner.this.console, monitor);
			}
			catch (final OperationCanceledException e1) {
				return Status.CANCEL_STATUS;
			}
			catch (final InterruptedException e1) {
				return Status.CANCEL_STATUS;
			}
			if (NIConsolePartitioner.this.document == null) {
				return Status.OK_STATUS;
			}
			
			final int length= NIConsolePartitioner.this.document.getLength();
			if (this.truncateOffset < length) {
				synchronized (NIConsolePartitioner.this.overflowLock) {
					try {
						if (this.truncateOffset < 0) {
							// clear
							setUpdateInProgress(true);
							NIConsolePartitioner.this.document.set(""); //$NON-NLS-1$
							setUpdateInProgress(false);
							NIConsolePartitioner.this.partitions.clear();
						}
						else {
							// overflow
							final int cutoffLine= NIConsolePartitioner.this.document.getLineOfOffset(this.truncateOffset);
							final int cutOffset= NIConsolePartitioner.this.document.getLineOffset(cutoffLine);
							
							// set the new length of the first partition
							final NIConsolePartition partition= (NIConsolePartition) getPartition(cutOffset);
							partition.setLength(partition.getOffset() + partition.getLength() - cutOffset);
							
							setUpdateInProgress(true);
							NIConsolePartitioner.this.document.replace(0, cutOffset, ""); //$NON-NLS-1$
							setUpdateInProgress(false);
							
							//remove partitions and reset Partition offsets
							final int index= NIConsolePartitioner.this.partitions.indexOf(partition);
							for (int i= 0; i < index; i++) {
								NIConsolePartitioner.this.partitions.remove(0);
							}
							
							int offset= 0;
							for (final Iterator<NIConsolePartition> i= NIConsolePartitioner.this.partitions.iterator(); i.hasNext();) {
								final NIConsolePartition p= i.next();
								p.setOffset(offset);
								offset += p.getLength();
							}
						}
					} catch (final BadLocationException e) {
					}
				}
			}
			return Status.OK_STATUS;
		}
	}
	
	@Override
	public boolean isReadOnly(final int offset) {
		return true;
	}
	
	@Override
	public StyleRange[] getStyleRanges(final int offset, final int length) {
		if (!this.isConnected) {
			return new StyleRange[0];
		}
		final NIConsolePartition[] computedPartitions= (NIConsolePartition[]) computePartitioning(offset, length);
		final StyleRange[] styles= new StyleRange[computedPartitions.length];
		for (int i= 0; i < computedPartitions.length; i++) {
			final int rangeStart= Math.max(computedPartitions[i].getOffset(), offset);
			final int rangeLength= computedPartitions[i].getLength();
			styles[i]= new StyleRange(rangeStart, rangeLength,
					computedPartitions[i].getStream().getColor(),
					computedPartitions[i].getStream().getBackgroundColor(),
					computedPartitions[i].getStream().getFontStyle() );
		}
		return styles;
	}
	
}
