package org.eclipse.cdt.internal.ui.editor;

/**********************************************************************
 * Copyright (c) 2002,2003 Rational Software Corporation and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v0.5
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors: 
 * Rational Software - Initial API and implementation
***********************************************************************/


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

import org.eclipse.cdt.core.model.BufferChangedEvent;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.IBuffer;
import org.eclipse.cdt.core.model.IBufferChangedListener;
import org.eclipse.cdt.core.model.IOpenable;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.ILineTracker;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.util.Assert;
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.
 * 
 * This class is similar to the JDT DocumentAdapter class.
 */
public class DocumentAdapter implements IBuffer, IDocumentListener {

	/**
	 * Internal implementation of a NULL instanceof IBuffer.
	 */
	static private class NullBuffer implements IBuffer {
			
		public void addBufferChangedListener(IBufferChangedListener listener) {}
		
		public void append(char[] text) {}
		
		public void append(String text) {}
		
		public void close() {}
		
		public char getChar(int position) {
			return 0;
		}
		
		public char[] getCharacters() {
			return null;
		}
		
		public String getContents() {
			return null;
		}
		
		public int getLength() {
			return 0;
		}
		
		public IOpenable getOwner() {
			return null;
		}
		
		public String getText(int offset, int length) {
			return null;
		}
		
		public IResource getUnderlyingResource() {
			return null;
		}
		
		public boolean hasUnsavedChanges() {
			return false;
		}
		
		public boolean isClosed() {
			return false;
		}
		
		public boolean isReadOnly() {
			return true;
		}
		
		public void removeBufferChangedListener(IBufferChangedListener listener) {}
		
		public void replace(int position, int length, char[] text) {}
		
		public void replace(int position, int length, String text) {}
		
		public void save(IProgressMonitor progress, boolean force) throws CModelException {}
		
		public void setContents(char[] contents) {}
		
		public void setContents(String contents) {}
	};
		
	
	/** NULL implementing <code>IBuffer</code> */
	public final static IBuffer NULL= new NullBuffer();
	/*
	 * @see IBuffer#addBufferChangedListener(IBufferChangedListener)
	 */
	public void addBufferChangedListener(IBufferChangedListener listener) {
		Assert.isNotNull(listener);
		if (!fBufferListeners.contains(listener))
			fBufferListeners.add(listener);
	}
	/**
	 *  Executes a document set content call in the ui thread.
	 */
	protected class DocumentSetCommand implements Runnable {
		
		private String fContents;
		
		public void run() {
			fDocument.set(fContents);
		}
	
		public void set(String contents) {
			fContents= contents;
			Display.getDefault().syncExec(this);
		}
	};
	/**
	 * Executes a document replace call in the ui thread.
	 */
	protected class DocumentReplaceCommand implements Runnable {
		
		private int fOffset;
		private int fLength;
		private String fText;
		
		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 IOpenable fOwner;
	IDocument fDocument;
	private DocumentSetCommand fSetCmd= new DocumentSetCommand();
	private DocumentReplaceCommand fReplaceCmd= new DocumentReplaceCommand();
	
	private Object fProviderKey;
	private CDocumentProvider fProvider;
	private String fLineDelimiter;
	private ILineTracker fLineTracker;
		
	private List fBufferListeners= new ArrayList(3);
	
	private IStatus fStatus;

	
	public DocumentAdapter(IOpenable owner, IDocument document, ILineTracker lineTracker, CDocumentProvider provider, Object providerKey) {
		
			Assert.isNotNull(document);
			Assert.isNotNull(lineTracker);
		
			fOwner= owner;
			fDocument= document;
			fLineTracker= lineTracker;
			fProvider= provider;
			fProviderKey= providerKey;		
			
			fDocument.addPrenotifiedDocumentListener(this);

		}
	/**
	 * Sets the status of this document adapter.
	 */
	public void setStatus(IStatus status) {
		fStatus= status;
	}
	
	/**
	 * Returns the status of this document adapter.
	 */
	public IStatus getStatus() {
		return fStatus;
	}
	
	/**
	 * Returns the adapted document.
	 * 
	 * @return the adapted document
	 */
	public IDocument getDocument() {
		return fDocument;
	}
	/**
	 * Returns the line delimiter of this buffer. As a document has a set of
	 * valid line delimiters, this set must be reduced to size 1.
	 */
	protected String getLineDelimiter() {
		
		if (fLineDelimiter == null) {
			
			try {
				fLineDelimiter= fDocument.getLineDelimiter(0);
			} catch (BadLocationException x) {
			}
			
			if (fLineDelimiter == null) {
				/*
				 * Follow up fix for: 1GF5UU0: ITPJUI:WIN2000 - "Organize Imports" in java editor inserts lines in wrong format
				 * The line delimiter must always be a legal document line delimiter.
				 */
				String sysLineDelimiter= System.getProperty("line.separator"); //$NON-NLS-1$
				String[] delimiters= fDocument.getLegalLineDelimiters();
				Assert.isTrue(delimiters.length > 0);
				for (int i= 0; i < delimiters.length; i++) {
					if (delimiters[i].equals(sysLineDelimiter)) {
						fLineDelimiter= sysLineDelimiter;
						break;
					}
				}
				
				if (fLineDelimiter == null) {
					// system line delimiter is not a legal document line delimiter
					fLineDelimiter= delimiters[0];
				}
			}
		}
		
		return fLineDelimiter;
	}	

	/**
	 * Converts the given string to the line delimiter of this buffer.
	 * This method is <code>public</code> for test purposes only.
	 */
	public String normalize(String text) {
		fLineTracker.set(text);
		
		int lines= fLineTracker.getNumberOfLines();
		if (lines <= 1)
			return text;
			
		StringBuffer buffer= new StringBuffer(text);
		
		try {
			IRegion previous= fLineTracker.getLineInformation(0);
			for (int i= 1; i < lines; i++) {
				int lastLineEnd= previous.getOffset() + previous.getLength();
				int lineStart= fLineTracker.getLineInformation(i).getOffset();
				fLineTracker.replace(lastLineEnd,  lineStart - lastLineEnd, getLineDelimiter());
				buffer.replace(lastLineEnd, lineStart, getLineDelimiter());
				previous= fLineTracker.getLineInformation(i);
			}
			
			// last line
			String delimiter= fLineTracker.getLineDelimiter(lines -1);
			if (delimiter != null && delimiter.length() > 0)
				buffer.replace(previous.getOffset() + previous.getLength(), buffer.length(), getLineDelimiter());
				
			return buffer.toString();
		} catch (BadLocationException x) {
		}
		
		return text;
	}
	/**
	 * @see org.eclipse.cdt.internal.core.model.IBuffer#append(char)
	 */
	public void append(char[] text) {
		append(new String(text));		
	}

	/**
	 * @see org.eclipse.cdt.internal.core.model.IBuffer#append(java.lang.String)
	 */
	public void append(String text) {
		fReplaceCmd.replace(fDocument.getLength(), 0, normalize(text));		
	}


	/**
	 * @see org.eclipse.cdt.internal.core.model.IBuffer#close()
	 */
	public void close() {
		if (isClosed())
			return;
			
		IDocument d= fDocument;
		fDocument= null;
		d.removePrenotifiedDocumentListener(this);
		
		fireBufferChanged(new BufferChangedEvent(this, 0, 0, null));
		fBufferListeners.clear();		
	}

	/**
	 * @see org.eclipse.cdt.internal.core.model.IBuffer#getChar(int)
	 */
	public char getChar(int position) {
		try {
			return fDocument.getChar(position);
		} catch (BadLocationException x) {
			throw new ArrayIndexOutOfBoundsException();
		}
	}

	/**
	 * @see org.eclipse.cdt.internal.core.model.IBuffer#getCharacters()
	 */
	public char[] getCharacters() {
		String content= getContents();
		return content == null ? null : content.toCharArray();
	}

	/**
	 * @see org.eclipse.cdt.internal.core.model.IBuffer#getContents()
	 */
	public String getContents() {
		return fDocument.get();
	}

	/**
	 * @see org.eclipse.cdt.internal.core.model.IBuffer#getLength()
	 */
	public int getLength() {
		return fDocument.getLength();
	}

	/**
	 * @see org.eclipse.cdt.internal.core.model.IBuffer#getOwner()
	 */
	public IOpenable getOwner() {
		return (IOpenable) fOwner;
	}

	/**
	 * @see org.eclipse.cdt.internal.core.model.IBuffer#getText(int, int)
	 */
	public String getText(int offset, int length) {
		try {
			return fDocument.get(offset, length);
		} catch (BadLocationException x) {
			throw new ArrayIndexOutOfBoundsException();
		}
	}

	/**
	 * @see org.eclipse.cdt.internal.core.model.IBuffer#getUnderlyingResource()
	 */
	public IResource getUnderlyingResource() {
		//return null;
		return fProvider != null ? fProvider.getUnderlyingResource(fProviderKey) : null;
	}

	/**
	 * @see org.eclipse.cdt.internal.core.model.IBuffer#hasUnsavedChanges()
	 */
	public boolean hasUnsavedChanges() {
		//return false;
		return fProvider != null ? fProvider.canSaveDocument(fProviderKey) : false;		
	}

	/**
	 * @see org.eclipse.cdt.internal.core.model.IBuffer#isClosed()
	 */
	public boolean isClosed() {
		return fDocument == null;
	}

	/**
	 * @see org.eclipse.cdt.internal.core.model.IBuffer#isReadOnly()
	 */
	public boolean isReadOnly() {
		//return false;
		IResource resource= getUnderlyingResource();
		return resource == null ? true : resource.isReadOnly();		
	}

	/*
	 * @see IBuffer#removeBufferChangedListener(IBufferChangedListener)
	 */
	public void removeBufferChangedListener(IBufferChangedListener listener) {
		Assert.isNotNull(listener);
		fBufferListeners.remove(listener);
	}
	/**
	 * @see org.eclipse.cdt.internal.core.model.IBuffer#replace(int, int, char)
	 */
	public void replace(int position, int length, char[] text) {
		replace(position, length, new String(text));		
	}

	/**
	 * @see org.eclipse.cdt.internal.core.model.IBuffer#replace(int, int, java.lang.String)
	 */
	public void replace(int position, int length, String text) {
		fReplaceCmd.replace(position, length, normalize(text));
	}

	/**
	 * @see org.eclipse.cdt.internal.core.model.IBuffer#save(org.eclipse.core.runtime.IProgressMonitor, boolean)
	 */
	public void save(IProgressMonitor progress, boolean force) throws CModelException {
			if (fProvider != null) {
				try {
					fProvider.saveDocumentContent(progress, fProviderKey, fDocument, force);
				} catch (CoreException e) {
					throw new CModelException(e);
				}
			}	
	}

	/**
	 * @see org.eclipse.cdt.internal.core.model.IBuffer#setContents(char)
	 */
	public void setContents(char[] contents) {
		setContents(new String(contents));		
	}

	/**
	 * @see org.eclipse.cdt.internal.core.model.IBuffer#setContents(java.lang.String)
	 */
	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
			String newContents= normalize(contents);
			int newLength= newContents.length();
			
			if (oldLength != newLength || !newContents.equals(fDocument.get()))
				fSetCmd.set(newContents);
		}
	}
	/*
	 * @see IDocumentListener#documentAboutToBeChanged(DocumentEvent)
	 */
	public void documentAboutToBeChanged(DocumentEvent event) {
		// there is nothing to do here
	}

	/*
	 * @see IDocumentListener#documentChanged(DocumentEvent)
	 */
	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 e= new ArrayList(fBufferListeners).iterator();
			while (e.hasNext())
				((IBufferChangedListener) e.next()).bufferChanged(event);
		}
	}

}
