/*******************************************************************************
 * Copyright (c) 2007, 2009 Oracle. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0, which accompanies this distribution
 * and is available at http://www.eclipse.org/legal/epl-v10.html.
 * 
 * Contributors:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.utility.internal.model.value.swing;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.EventObject;

import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.EventListenerList;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.Element;
import javax.swing.text.PlainDocument;
import javax.swing.text.Position;
import javax.swing.text.Segment;

import org.eclipse.jpt.utility.internal.StringTools;
import org.eclipse.jpt.utility.internal.model.listener.awt.AWTPropertyChangeListenerWrapper;
import org.eclipse.jpt.utility.model.event.PropertyChangeEvent;
import org.eclipse.jpt.utility.model.listener.PropertyChangeListener;
import org.eclipse.jpt.utility.model.value.PropertyValueModel;
import org.eclipse.jpt.utility.model.value.WritablePropertyValueModel;

/**
 * This javax.swing.text.Document can be used to keep a DocumentListener
 * (e.g. a JTextField) in synch with a PropertyValueModel that holds a string.
 * 
 * NB: This model should only be used for "small" documents;
 * i.e. documents used by text fields, not text panes.
 * @see #synchronizeDelegate(String)
 */
public class DocumentAdapter
	implements Document, Serializable
{

	/** The delegate document whose behavior we "enhance". */
	protected final Document delegate;

	/** A listener that allows us to forward any changes made to the delegate document. */
	protected final CombinedListener delegateListener;

	/** A value model on the underlying model string. */
	protected final WritablePropertyValueModel<String> stringHolder;

	/** A listener that allows us to synchronize with changes made to the underlying model string. */
	protected transient PropertyChangeListener stringListener;

    /** The event listener list for the document. */
    protected final EventListenerList listenerList = new EventListenerList();

	private static final long serialVersionUID = 1L;


	// ********** constructors **********

	/**
	 * Constructor - the string holder is required.
	 * Wrap the specified document.
	 */
	public DocumentAdapter(WritablePropertyValueModel<String> stringHolder, Document delegate) {
		super();
		if (stringHolder == null || delegate == null) {
			throw new NullPointerException();
		}
		this.stringHolder = stringHolder;
		// postpone listening to the underlying model string
		// until we have listeners ourselves...
		this.delegate = delegate;
		this.stringListener = this.buildStringListener();
		this.delegateListener = this.buildDelegateListener();
	}

	/**
	 * Constructor - the string holder is required.
	 * Wrap a plain document.
	 */
	public DocumentAdapter(WritablePropertyValueModel<String> stringHolder) {
		this(stringHolder, new PlainDocument());
	}


	// ********** initialization **********

	protected PropertyChangeListener buildStringListener() {
		return new AWTPropertyChangeListenerWrapper(this.buildStringListener_());
	}

	protected PropertyChangeListener buildStringListener_() {
		return new PropertyChangeListener() {
			public void propertyChanged(PropertyChangeEvent event) {
				DocumentAdapter.this.stringChanged(event);
			}
			@Override
			public String toString() {
				return "string listener"; //$NON-NLS-1$
			}
		};
	}

	protected CombinedListener buildDelegateListener() {
		return new InternalListener();
	}


	// ********** Document implementation **********

	public int getLength() {
		return this.delegate.getLength();
	}

	/**
	 * Extend to start listening to the underlying models if necessary.
	 */
	public void addDocumentListener(DocumentListener listener) {
		if (this.listenerList.getListenerCount(DocumentListener.class) == 0) {
			this.delegate.addDocumentListener(this.delegateListener);
			this.engageStringHolder();
		}
		this.listenerList.add(DocumentListener.class, listener);
	}

	/**
	 * Extend to stop listening to the underlying models if appropriate.
	 */
	public void removeDocumentListener(DocumentListener listener) {
		this.listenerList.remove(DocumentListener.class, listener);
		if (this.listenerList.getListenerCount(DocumentListener.class) == 0) {
			this.disengageStringHolder();
			this.delegate.removeDocumentListener(this.delegateListener);
		}
	}

	/**
	 * Extend to start listening to the delegate document if necessary.
	 */
	public void addUndoableEditListener(UndoableEditListener listener) {
		if (this.listenerList.getListenerCount(UndoableEditListener.class) == 0) {
			this.delegate.addUndoableEditListener(this.delegateListener);
		}
		this.listenerList.add(UndoableEditListener.class, listener);
	}

	/**
	 * Extend to stop listening to the delegate document if appropriate.
	 */
	public void removeUndoableEditListener(UndoableEditListener listener) {
		this.listenerList.remove(UndoableEditListener.class, listener);
		if (this.listenerList.getListenerCount(UndoableEditListener.class) == 0) {
			this.delegate.removeUndoableEditListener(this.delegateListener);
		}
	}

	public Object getProperty(Object key) {
		return this.delegate.getProperty(key);
	}

	public void putProperty(Object key, Object value) {
		this.delegate.putProperty(key, value);
	}

	/**
	 * Extend to update the underlying model string directly.
	 * The resulting event will be ignored: @see #synchronizeDelegate(String).
	 */
	public void remove(int offset, int len) throws BadLocationException {
		this.delegate.remove(offset, len);
		this.stringHolder.setValue(this.delegate.getText(0, this.delegate.getLength()));
	}

	/**
	 * Extend to update the underlying model string directly.
	 * The resulting event will be ignored: @see #synchronizeDelegate(String).
	 */
	public void insertString(int offset, String insertedString, AttributeSet a) throws BadLocationException {
		this.delegate.insertString(offset, insertedString, a);
		this.stringHolder.setValue(this.delegate.getText(0, this.delegate.getLength()));
	}

	public String getText(int offset, int length) throws BadLocationException {
		return this.delegate.getText(offset, length);
	}

	public void getText(int offset, int length, Segment txt) throws BadLocationException {
		this.delegate.getText(offset, length, txt);
	}

	public Position getStartPosition() {
		return this.delegate.getStartPosition();
	}

	public Position getEndPosition() {
		return this.delegate.getEndPosition();
	}

	public Position createPosition(int offs) throws BadLocationException {
		return this.delegate.createPosition(offs);
	}

	public Element[] getRootElements() {
		return this.delegate.getRootElements();
	}

	public Element getDefaultRootElement() {
		return this.delegate.getDefaultRootElement();
	}

	public void render(Runnable r) {
		this.delegate.render(r);
	}


	// ********** queries **********

	public DocumentListener[] documentListeners() {
		return this.listenerList.getListeners(DocumentListener.class);
	}

	public UndoableEditListener[] undoableEditListeners() {
		return this.listenerList.getListeners(UndoableEditListener.class);
	}


	// ********** behavior **********

	/**
	 * A third party has modified the underlying model string.
	 * Synchronize the delegate document accordingly.
	 */
	protected void stringChanged(PropertyChangeEvent event) {
		this.synchronizeDelegate((String) event.getNewValue());
	}

	/**
	 * Replace the document's entire text string with the new string.
	 */
	protected void synchronizeDelegate(String s) {
		try {
			int len = this.delegate.getLength();
			// check to see whether the delegate has already been synchronized
			// (via #insertString() or #remove())
			if ( ! this.delegate.getText(0, len).equals(s)) {
				this.delegate.remove(0, len);
				this.delegate.insertString(0, s, null);
			}
		} catch (BadLocationException ex) {
			throw new IllegalStateException(ex.getMessage());	// this should not happen...
		}
	}

	protected void engageStringHolder() {
		this.stringHolder.addPropertyChangeListener(PropertyValueModel.VALUE, this.stringListener);
		this.synchronizeDelegate(this.stringHolder.getValue());
	}

	protected void disengageStringHolder() {
		this.stringHolder.removePropertyChangeListener(PropertyValueModel.VALUE, this.stringListener);
	}

	protected void delegateChangedUpdate(DocumentEvent event) {
		// no need to lazy-initialize the event;
		// we wouldn't get here if we did not have listeners...
		DocumentEvent ee = new InternalDocumentEvent(this, event);
		DocumentListener[] listeners = this.documentListeners();
		for (int i = listeners.length; i-- > 0; ) {
			listeners[i].changedUpdate(ee);
		}
	}

	protected void delegateInsertUpdate(DocumentEvent event) {
		// no need to lazy-initialize the event;
		// we wouldn't get here if we did not have listeners...
		DocumentEvent ee = new InternalDocumentEvent(this, event);
		DocumentListener[] listeners = this.documentListeners();
		for (int i = listeners.length; i-- > 0; ) {
			listeners[i].insertUpdate(ee);
		}
	}

	protected void delegateRemoveUpdate(DocumentEvent event) {
		// no need to lazy-initialize the event;
		// we wouldn't get here if we did not have listeners...
		DocumentEvent ee = new InternalDocumentEvent(this, event);
		DocumentListener[] listeners = this.documentListeners();
		for (int i = listeners.length; i-- > 0; ) {
			listeners[i].removeUpdate(ee);
		}
	}

	protected void delegateUndoableEditHappened(UndoableEditEvent event) {
		// no need to lazy-initialize the event;
		// we wouldn't get here if we did not have listeners...
		UndoableEditEvent ee = new UndoableEditEvent(this, event.getEdit());
		UndoableEditListener[] listeners = this.undoableEditListeners();
		for (int i = listeners.length; i-- > 0; ) {
			listeners[i].undoableEditHappened(ee);
		}
	}

	// ********** standard methods **********

	@Override
	public String toString() {
		return StringTools.buildToStringFor(this, this.stringHolder);
	}

	private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException {
		// read in any hidden stuff
		s.defaultReadObject();
		this.stringListener = this.buildStringListener();
	}


// ********** inner class **********

	protected interface CombinedListener extends DocumentListener, UndoableEditListener, Serializable {
		// just consolidate the two interfaces
	}

	protected class InternalListener implements CombinedListener {
		private static final long serialVersionUID = 1L;
		public void changedUpdate(DocumentEvent event) {
			DocumentAdapter.this.delegateChangedUpdate(event);
		}
		public void insertUpdate(DocumentEvent event) {
			DocumentAdapter.this.delegateInsertUpdate(event);
		}
		public void removeUpdate(DocumentEvent event) {
			DocumentAdapter.this.delegateRemoveUpdate(event);
		}
		public void undoableEditHappened(UndoableEditEvent event) {
			DocumentAdapter.this.delegateUndoableEditHappened(event);
		}
	}
	
	protected static class InternalDocumentEvent
		extends EventObject
		implements DocumentEvent
	{
		protected DocumentEvent delegate;
	
		protected InternalDocumentEvent(Document document, DocumentEvent delegate) {
			super(document);
			this.delegate = delegate;
		}
		public ElementChange getChange(Element elem) {
			return this.delegate.getChange(elem);
		}
		public Document getDocument() {
			return (Document) this.source;
		}
		public int getLength() {
			return this.delegate.getLength();
		}
		public int getOffset() {
			return this.delegate.getOffset();
		}
		public EventType getType() {
			return this.delegate.getType();
		}
	}

}
