/*******************************************************************************
 * Copyright (c) 2005, 2017 IBM Corporation and others.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 * 
 * SPDX-License-Identifier: EPL-2.0
 *
 *******************************************************************************/
package org.eclipse.dltk.internal.ui.editor;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.filebuffers.ITextFileBufferManager;
import org.eclipse.core.filebuffers.LocationKind;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.dltk.core.BufferChangedEvent;
import org.eclipse.dltk.core.IBuffer;
import org.eclipse.dltk.core.IBufferChangedListener;
import org.eclipse.dltk.core.IOpenable;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.ui.DLTKUIPlugin;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DefaultLineTracker;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.ISynchronizable;
import org.eclipse.swt.widgets.Display;

/**
 * Adapts <code>IDocument</code> to <code>IBuffer</code>. Uses the same
 * algorithm as the text widget to determine the buffer's line delimiter. All
 * text inserted into the buffer is converted to this line delimiter. This class
 * is <code>public</code> for test purposes only.
 */
public class DocumentAdapter implements IBuffer, IDocumentListener {

	/**
	 * Internal implementation of a NULL instanceof IBuffer.
	 */
	static private class NullBuffer implements IBuffer {
		@Override
		public void addBufferChangedListener(IBufferChangedListener listener) {
		}

		@Override
		public void append(char[] text) {
		}

		@Override
		public void append(String text) {
		}

		@Override
		public void close() {
		}

		@Override
		public char getChar(int position) {
			return 0;
		}

		@Override
		public char[] getCharacters() {
			return null;
		}

		@Override
		public String getContents() {
			return null;
		}

		@Override
		public int getLength() {
			return 0;
		}

		@Override
		public IOpenable getOwner() {
			return null;
		}

		@Override
		public String getText(int offset, int length) {
			return null;
		}

		@Override
		public IResource getUnderlyingResource() {
			return null;
		}

		@Override
		public boolean hasUnsavedChanges() {
			return false;
		}

		@Override
		public boolean isClosed() {
			return false;
		}

		@Override
		public boolean isReadOnly() {
			return true;
		}

		@Override
		public void removeBufferChangedListener(
				IBufferChangedListener listener) {
		}

		@Override
		public void replace(int position, int length, char[] text) {
		}

		@Override
		public void replace(int position, int length, String text) {
		}

		@Override
		public void save(IProgressMonitor progress, boolean force)
				throws ModelException {
		}

		@Override
		public void setContents(char[] contents) {
		}

		@Override
		public void setContents(String contents) {
		}
	}

	/** NULL implementing <code>IBuffer</code> */
	public final static IBuffer NULL = new NullBuffer();

	/*
	*
	 */
	private IPath fPath;

	/**
	 * Executes a document set content call in the ui thread.
	 */
	protected class DocumentSetCommand implements Runnable {

		private String fContents;

		@Override
		public void run() {
			fDocument.set(fContents);
		}

		public void set(String contents) {
			fContents = contents;
			// Display.getDefault().syncExec(this);
			DocumentAdapter.run(this);
		}
	}

	/**
	 * Executes a document replace call in the ui thread.
	 */
	protected class DocumentReplaceCommand implements Runnable {

		private int fOffset;
		private int fLength;
		private String fText;

		@Override
		public void run() {
			try {
				fDocument.replace(fOffset, fLength, fText);
			} catch (BadLocationException x) {
				// ignore
			}
		}

		public void replace(int offset, int length, String text) {
			fOffset = offset;
			fLength = length;
			fText = text;
			Display.getDefault().syncExec(this);
		}
	}

	private static final boolean DEBUG_LINE_DELIMITERS = true;

	private IOpenable fOwner;
	private IFile fFile;
	private ITextFileBuffer fTextFileBuffer;
	private IDocument fDocument;

	private DocumentSetCommand fSetCmd = new DocumentSetCommand();
	private DocumentReplaceCommand fReplaceCmd = new DocumentReplaceCommand();

	private Set<String> fLegalLineDelimiters;

	private List<IBufferChangedListener> fBufferListeners = new ArrayList<>(3);
	private IStatus fStatus;

	/** @since 4.0 */
	private LocationKind fLocationKind;

	/** @since 4.0 */
	private IFileStore fFileStore;

	/**
	 * Constructs a new document adapter.
	 */
	public DocumentAdapter(IOpenable owner, IFile file) {

		fOwner = owner;
		fFile = file;
		fPath = fFile.getFullPath();
		fLocationKind = LocationKind.IFILE;

		initialize();
	}

	/**
	 * Constructs a new document adapter.
	 *
	 *
	 */
	public DocumentAdapter(IOpenable owner, IPath path) {
		Assert.isLegal(path != null);

		fOwner = owner;
		fPath = path;
		fLocationKind = LocationKind.NORMALIZE;

		initialize();
	}

	/**
	 * Constructs a new document adapter.
	 *
	 * @param owner
	 *            the owner of this buffer
	 * @param fileStore
	 *            the file store of the file that backs the buffer
	 * @param path
	 *            the path of the file that backs the buffer
	 * @since 4.0
	 */
	public DocumentAdapter(IOpenable owner, IFileStore fileStore, IPath path) {
		Assert.isLegal(fileStore != null);
		Assert.isLegal(path != null);
		fOwner = owner;
		fFileStore = fileStore;
		fPath = path;
		fLocationKind = LocationKind.NORMALIZE;

		initialize();
	}

	private void initialize() {
		ITextFileBufferManager manager = FileBuffers.getTextFileBufferManager();
		try {
			if (fFileStore != null) {
				manager.connectFileStore(fFileStore, new NullProgressMonitor());
				fTextFileBuffer = manager
						.getFileStoreTextFileBuffer(fFileStore);
			} else {
				manager.connect(fPath, fLocationKind,
						new NullProgressMonitor());
				fTextFileBuffer = manager.getTextFileBuffer(fPath,
						fLocationKind);
			}
			fDocument = fTextFileBuffer.getDocument();
		} catch (CoreException x) {
			fStatus = x.getStatus();
			fDocument = manager.createEmptyDocument(fPath,
					LocationKind.NORMALIZE);
			if (fDocument instanceof ISynchronizable)
				((ISynchronizable) fDocument).setLockObject(new Object());
		}
		fDocument.addPrenotifiedDocumentListener(this);
	}

	/**
	 * Returns the status of this document adapter.
	 */
	public IStatus getStatus() {
		if (fStatus != null)
			return fStatus;
		if (fTextFileBuffer != null)
			return fTextFileBuffer.getStatus();
		return null;
	}

	/**
	 * Returns the adapted document.
	 *
	 * @return the adapted document
	 */
	public IDocument getDocument() {
		return fDocument;
	}

	/*
	 * @see IBuffer#addBufferChangedListener(IBufferChangedListener)
	 */
	@Override
	public void addBufferChangedListener(IBufferChangedListener listener) {
		Assert.isNotNull(listener);
		if (!fBufferListeners.contains(listener))
			fBufferListeners.add(listener);
	}

	/*
	 * @see IBuffer#removeBufferChangedListener(IBufferChangedListener)
	 */
	@Override
	public void removeBufferChangedListener(IBufferChangedListener listener) {
		Assert.isNotNull(listener);
		fBufferListeners.remove(listener);
	}

	@Override
	public void append(char[] text) {
		append(new String(text));
	}

	@Override
	public void append(String text) {
		if (DEBUG_LINE_DELIMITERS) {
			validateLineDelimiters(text);
		}
		fReplaceCmd.replace(fDocument.getLength(), 0, text);
	}

	@Override
	public void close() {

		if (isClosed())
			return;

		IDocument d = fDocument;
		fDocument = null;
		d.removePrenotifiedDocumentListener(this);

		if (fTextFileBuffer != null) {
			ITextFileBufferManager manager = FileBuffers
					.getTextFileBufferManager();
			try {
				if (fFileStore != null)
					manager.disconnectFileStore(fFileStore,
							new NullProgressMonitor());
				else
					manager.disconnect(fPath, fLocationKind,
							new NullProgressMonitor());
			} catch (CoreException x) {
				// ignore
			}
			fTextFileBuffer = null;
		}

		fireBufferChanged(new BufferChangedEvent(this, 0, 0, null));
		fBufferListeners.clear();
	}

	@Override
	public char getChar(int position) {
		try {
			return fDocument.getChar(position);
		} catch (BadLocationException x) {
			throw new ArrayIndexOutOfBoundsException();
		}
	}

	@Override
	public char[] getCharacters() {
		String content = getContents();
		return content == null ? null : content.toCharArray();
	}

	@Override
	public String getContents() {
		return fDocument.get();
	}

	@Override
	public int getLength() {
		return fDocument.getLength();
	}

	@Override
	public IOpenable getOwner() {
		return fOwner;
	}

	@Override
	public String getText(int offset, int length) {
		try {
			return fDocument.get(offset, length);
		} catch (BadLocationException x) {
			throw new ArrayIndexOutOfBoundsException();
		}
	}

	@Override
	public IResource getUnderlyingResource() {
		return fFile;
	}

	@Override
	public boolean hasUnsavedChanges() {
		return fTextFileBuffer != null ? fTextFileBuffer.isDirty() : false;
	}

	@Override
	public boolean isClosed() {
		return fDocument == null;
	}

	@Override
	public boolean isReadOnly() {
		IResource resource = getUnderlyingResource();
		return resource == null ? true
				: resource.getResourceAttributes().isReadOnly();
	}

	@Override
	public void replace(int position, int length, char[] text) {
		replace(position, length, new String(text));
	}

	@Override
	public void replace(int position, int length, String text) {
		if (DEBUG_LINE_DELIMITERS) {
			validateLineDelimiters(text);
		}
		fReplaceCmd.replace(position, length, text);
	}

	@Override
	public void save(IProgressMonitor progress, boolean force)
			throws ModelException {
		try {
			if (fTextFileBuffer != null)
				fTextFileBuffer.commit(progress, force);
		} catch (CoreException e) {
			throw new ModelException(e);
		}
	}

	@Override
	public void setContents(char[] contents) {
		setContents(new String(contents));
	}

	@Override
	public void setContents(String contents) {
		int oldLength = fDocument.getLength();

		if (contents == null) {

			if (oldLength != 0)
				fSetCmd.set(""); //$NON-NLS-1$

		} else {

			// set only if different
			if (DEBUG_LINE_DELIMITERS) {
				validateLineDelimiters(contents);
			}

			if (!contents.equals(fDocument.get()))
				fSetCmd.set(contents);
		}
	}

	private void validateLineDelimiters(String contents) {

		if (fLegalLineDelimiters == null) {
			// collect all line delimiters in the document
			HashSet<String> existingDelimiters = new HashSet<>();

			for (int i = fDocument.getNumberOfLines() - 1; i >= 0; i--) {
				try {
					String curr = fDocument.getLineDelimiter(i);
					if (curr != null) {
						existingDelimiters.add(curr);
					}
				} catch (BadLocationException e) {
					DLTKUIPlugin.log(e);
				}
			}
			if (existingDelimiters.isEmpty()) {
				return; // first insertion of a line delimiter: no test
			}
			fLegalLineDelimiters = existingDelimiters;

		}

		DefaultLineTracker tracker = new DefaultLineTracker();
		tracker.set(contents);

		int lines = tracker.getNumberOfLines();
		if (lines <= 1)
			return;

		for (int i = 0; i < lines; i++) {
			try {
				String curr = tracker.getLineDelimiter(i);
				if (curr != null && !fLegalLineDelimiters.contains(curr)) {
					StringBuffer buf = new StringBuffer(
							"WARNING: DocumentAdapter added new line delimiter to code: "); //$NON-NLS-1$
					for (int k = 0; k < curr.length(); k++) {
						if (k > 0)
							buf.append(' ');
						buf.append((int) curr.charAt(k));
					}
					IStatus status = new Status(IStatus.WARNING,
							DLTKUIPlugin.PLUGIN_ID, IStatus.OK, buf.toString(),
							new Throwable());
					DLTKUIPlugin.log(status);
				}
			} catch (BadLocationException e) {
				DLTKUIPlugin.log(e);
			}
		}
	}

	@Override
	public void documentAboutToBeChanged(DocumentEvent event) {
		// there is nothing to do here
	}

	@Override
	public void documentChanged(DocumentEvent event) {
		fireBufferChanged(new BufferChangedEvent(this, event.getOffset(),
				event.getLength(), event.getText()));
	}

	private void fireBufferChanged(BufferChangedEvent event) {
		if (fBufferListeners != null && fBufferListeners.size() > 0) {
			Iterator<IBufferChangedListener> e = new ArrayList<>(
					fBufferListeners).iterator();
			while (e.hasNext())
				e.next().bufferChanged(event);
		}
	}

	/**
	 * Run the given runnable in the UI thread.
	 *
	 * @param runnable
	 *            the runnable
	 * @since 3.3
	 */
	private static final void run(Runnable runnable) {
		Display currentDisplay = Display.getCurrent();
		if (currentDisplay != null)
			runnable.run();
		else
			Display.getDefault().syncExec(runnable);
	}

}
