
/*******************************************************************************
 * Copyright (c) 2001, 2004 IBM Corporation and others.
 * 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.wsdl.ui.internal;

import java.io.IOException;
import java.io.InputStream;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceStatus;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextInputListener;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorActionBarContributor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.IStorageEditorInput;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IGotoMarker;
import org.eclipse.wst.common.ui.provisional.editors.PostMultiPageEditorSite;
import org.eclipse.wst.common.ui.provisional.editors.PostSelectionMultiPageEditorPart;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.ui.StructuredTextEditor;
import org.eclipse.wst.xml.core.internal.provisional.IXMLPreferenceNames;
import org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML;
import org.eclipse.wst.xml.ui.internal.tabletree.XMLEditorMessages;

public class WSDLMultiPageEditorPart extends PostSelectionMultiPageEditorPart implements IPropertyListener {

	/**
	 * 
	 */
	public WSDLMultiPageEditorPart() {
		super();
	}

	/**
	 * Internal part activation listener
	 */
	class PartListener extends ShellAdapter implements IPartListener {
		private IWorkbenchPart fActivePart;
		private boolean fIsHandlingActivation = false;

		private void handleActivation() {

			if (fIsHandlingActivation)
				return;

			if (fActivePart == WSDLMultiPageEditorPart.this) {
				fIsHandlingActivation = true;
				try {
					safelySanityCheckState();
				}
				finally {
					fIsHandlingActivation = false;
				}
			}
		}

		/**
		 * @see IPartListener#partActivated(IWorkbenchPart)
		 */
		public void partActivated(IWorkbenchPart part) {
			fActivePart = part;
			handleActivation();
		}

		/**
		 * @see IPartListener#partBroughtToTop(IWorkbenchPart)
		 */
		public void partBroughtToTop(IWorkbenchPart part) {
		}

		/**
		 * @see IPartListener#partClosed(IWorkbenchPart)
		 */
		public void partClosed(IWorkbenchPart part) {
		}

		/**
		 * @see IPartListener#partDeactivated(IWorkbenchPart)
		 */
		public void partDeactivated(IWorkbenchPart part) {
			fActivePart = null;
		}

		/**
		 * @see IPartListener#partOpened(IWorkbenchPart)
		 */
		public void partOpened(IWorkbenchPart part) {
		}

		/*
		 * @see ShellListener#shellActivated(ShellEvent)
		 */
		public void shellActivated(ShellEvent e) {
			handleActivation();
		}
	}

	class TextInputListener implements ITextInputListener {
		public void inputDocumentAboutToBeChanged(IDocument oldInput, IDocument newInput) {
		}

		public void inputDocumentChanged(IDocument oldInput, IDocument newInput) {
		}
	}

	/** The source page index. */
	private int fSourcePageIndex;
	/** The text editor. */
	private StructuredTextEditor fTextEditor;

	private PartListener partListener;


	/*
	 * This method is just to make firePropertyChanged accessbible from some
	 * (anonomous) inner classes.
	 */
	protected void _firePropertyChange(int property) {
		super.firePropertyChange(property);
	}

	/**
	 * Adds the source page of the multi-page editor.
	 */
	protected void addSourcePage() throws PartInitException {
		try {
			fSourcePageIndex = addPage(fTextEditor, getEditorInput());
			setPageText(fSourcePageIndex, WSDLEditorPlugin.getWSDLString("_UI_TAB_SOURCE")); //$NON-NLS-1$
			// the update's critical, to get viewer selection manager and
			// highlighting to work
			fTextEditor.update();

			firePropertyChange(PROP_TITLE);

			// Changes to the Text Viewer's document instance should also
			// force an
			// input refresh
			fTextEditor.getTextViewer().addTextInputListener(new TextInputListener());
		}
		catch (PartInitException e) {
			// dispose editor
			dispose();

			// log for now, unless we find reason not to
			Logger.log(Logger.INFO, e.getMessage());
		}
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.part.MultiPageEditorPart#createPages()
	 */
	protected void createPages() {
		try {
			// source page MUST be created before design page, now
			createSourcePage();
			addSourcePage();
			setActivePage();

			// future_TODO: add a catch block here for any exception the
			// design
			// page throws and convert it into a more informative message.
		}
		catch (PartInitException e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * @see org.eclipse.ui.part.MultiPageEditorPart#createSite(org.eclipse.ui.IEditorPart)
	 */
	protected IEditorSite createSite(IEditorPart editor) {
		IEditorSite site = null;
		if (editor == fTextEditor) {
			site = new PostMultiPageEditorSite(this, editor) {
				/**
				 * @see org.eclipse.ui.part.MultiPageEditorSite#getActionBarContributor()
				 */
				public IEditorActionBarContributor getActionBarContributor() {
					IEditorActionBarContributor contributor = super.getActionBarContributor();
//					IEditorActionBarContributor multiContributor = WSDLMultiPageEditorPart.this.getEditorSite().getActionBarContributor();
					// if (multiContributor instanceof
					// XMLMultiPageEditorActionBarContributor) {
					// contributor = ((XMLMultiPageEditorActionBarContributor)
					// multiContributor).sourceViewerActionContributor;
					// }
					return contributor;
				}

				public String getId() {
					// sets this id so nested editor is considered xml source
					// page
					return ContentTypeIdForXML.ContentTypeID_XML + ".source"; //$NON-NLS-1$;
				}
			};
		}
		else {
			site = super.createSite(editor);
		}
		return site;
	}

	/**
	 * Creates the source page of the multi-page editor.
	 */
	protected void createSourcePage() throws PartInitException {
		fTextEditor = createTextEditor();
		fTextEditor.setEditorPart(this);

		// Set the SourceViewerConfiguration now so the text editor won't use
		// the default configuration first
		// and switch to the StructuredTextViewerConfiguration later.
		// DMW removed setSourceViewerConfiguration 3/26/2003 since added
		// createPartControl to our text editor.
		// fTextEditor.setSourceViewerConfiguration();
		fTextEditor.addPropertyListener(this);
	}

	/**
	 * Method createTextEditor.
	 * 
	 * @return StructuredTextEditor
	 */
	protected StructuredTextEditor createTextEditor() {
		return new StructuredTextEditor();
	}

	public void dispose() {
		IWorkbenchWindow window = getSite().getWorkbenchWindow();
		window.getPartService().removePartListener(partListener);
		window.getShell().removeShellListener(partListener);

		getSite().getPage().removePartListener(partListener);
		if (fTextEditor != null) {
			fTextEditor.removePropertyListener(this);
		}

		// moved to last when added window ... seems like
		// we'd be in danger of losing some data, like site,
		// or something.
		super.dispose();
	}

	/*
	 * (non-Javadoc) Saves the contents of this editor. <p> Subclasses must
	 * override this method to implement the open-save-close lifecycle for an
	 * editor. For greater details, see <code> IEditorPart </code></p>
	 * 
	 * @see IEditorPart
	 */
	public void doSave(IProgressMonitor monitor) {
		fTextEditor.doSave(monitor);
		// // this is a temporary way to force validation.
		// // when the validator is a workbench builder, the following lines
		// can be removed
		// if (fDesignViewer != null)
		// fDesignViewer.saveOccurred();

	}

	/*
	 * (non-Javadoc) Saves the contents of this editor to another object. <p>
	 * Subclasses must override this method to implement the open-save-close
	 * lifecycle for an editor. For greater details, see <code> IEditorPart
	 * </code></p>
	 * 
	 * @see IEditorPart
	 */
	public void doSaveAs() {
		fTextEditor.doSaveAs();
		// 253619
		// following used to be executed here, but is
		// now called "back" from text editor (since
		// mulitiple paths to the performSaveAs in StructuredTextEditor.
		// doSaveAsForStructuredTextMulitPagePart();
	}

	private void editorInputIsAcceptable(IEditorInput input) throws PartInitException {
		if (input instanceof IFileEditorInput) {
			// verify that it can be opened
			CoreException[] coreExceptionArray = new CoreException[1];
			if (fileDoesNotExist((IFileEditorInput) input, coreExceptionArray)) {
				CoreException coreException = coreExceptionArray[0];
				if (coreException.getStatus().getCode() == IResourceStatus.FAILED_READ_LOCAL) {
					// I'm assuming this is always 'does not exist'
					// we'll refresh local go mimic behavior of default
					// editor, where the
					// troublesome file is refreshed (and will cause it to
					// 'disappear' from Navigator.
					try {
						((IFileEditorInput) input).getFile().refreshLocal(IResource.DEPTH_ZERO, new NullProgressMonitor());
					}
					catch (CoreException ce) {
						// very unlikely
						Logger.logException(ce);
					}
					throw new PartInitException(NLS.bind(XMLEditorMessages.Resource__does_not_exist, (new Object[]{input.getName()})));
				}
				else {
					throw new PartInitException(NLS.bind(XMLEditorMessages.Editor_could_not_be_open, (new Object[]{input.getName()})));
				}
			}
		}
		else if (input instanceof IStorageEditorInput) {
			InputStream contents = null;
			try {
				contents = ((IStorageEditorInput) input).getStorage().getContents();
			}
			catch (CoreException noStorageExc) {
			}
			if (contents == null) {
				throw new PartInitException(NLS.bind(XMLEditorMessages.Editor_could_not_be_open, (new Object[]{input.getName()})));
			}
			else {
				try {
					contents.close();
				}
				catch (IOException e) {
				}
			}
		}
	}

	// void doSaveAsForStructuredTextMulitPagePart() {
	// setPageText(getActivePage(), fTextEditor.getTitle());
	// setInput(fTextEditor.getEditorInput());
	// if (fDesignViewer != null) {
	// //fDesignViewer.setEditorInput(fTextEditor.getEditorInput());
	// fDesignViewer.setModel(getModel());
	// fDesignViewer.saveAsOccurred();
	// }
	// // even though we've set title etc., several times already!
	// // only now is all prepared for it.
	// firePropertyChange(IWorkbenchPart.PROP_TITLE);
	// firePropertyChange(PROP_DIRTY);
	// }
	/*
	 * (non-Javadoc) Initializes the editor part with a site and input. <p>
	 * Subclasses of <code> EditorPart </code> must implement this method.
	 * Within the implementation subclasses should verify that the input type
	 * is acceptable and then save the site and input. Here is sample code:
	 * </p><pre> if (!(input instanceof IFileEditorInput)) throw new
	 * PartInitException("Invalid Input: Must be IFileEditorInput");
	 * setSite(site); setInput(editorInput); </pre>
	 */
	protected boolean fileDoesNotExist(IFileEditorInput input, Throwable[] coreException) {
		boolean result = false;
		InputStream inStream = null;
		if ((!(input.exists())) || (!(input.getFile().exists()))) {
			result = true;
		}
		else {
			try {
				inStream = input.getFile().getContents(true);
			}
			catch (CoreException e) {
				// very likely to be file not found
				result = true;
				coreException[0] = e;
			}
			finally {
				if (input != null) {
					try {
						if (inStream != null) {
							inStream.close();
						}
					}
					catch (IOException e) {

					}
				}
			}
		}
		return result;
	}

	public Object getAdapter(Class key) {
		Object result = null;

		// DMW: I'm bullet-proofing this because
		// its been reported (on 4.03 version) a null pointer sometimes
		// happens here on startup, when an editor has been left
		// open when workbench shutdown.
		if (fTextEditor != null) {
			result = fTextEditor.getAdapter(key);
		}
		return result;
	}

	public IEditorPart getEditorPart() {
		return this;
	}

	protected IStructuredModel getModel() {
		IStructuredModel model = null;
		if (fTextEditor != null) {
			model = fTextEditor.getModel();
//			IDocument doc = fTextEditor.getDocumentProvider().getDocument(getEditorInput());	
//	    	IModelManager modelManager = ModelManagerImpl.getInstance();    	
//	    	model = modelManager.getModelForRead((IStructuredDocument) doc);
		}

		return model;
	}

	protected IPreferenceStore getPreferenceStore() {
		return WSDLEditorPlugin.getInstance().getPreferenceStore();
	}

	public StructuredTextEditor getTextEditor() {
		return fTextEditor;
	}

	/*
	 * (non-Javadoc) Method declared on IWorkbenchPart.
	 */
	public String getTitle() {
		String title = null;
		if (getTextEditor() == null) {
			if (getEditorInput() != null) {
				title = getEditorInput().getName();
			}
		}
		else {
			title = getTextEditor().getTitle();
		}
		if (title == null) {
			title = getPartName();
		}
		return title;
	}

	/*
	 * (non-Javadoc) Sets the cursor and selection state for this editor to
	 * the passage defined by the given marker. <p> Subclasses may override.
	 * For greater details, see <code> IEditorPart </code></p>
	 * 
	 * @see IEditorPart
	 */
	public void gotoMarker(IMarker marker) {
		// (pa) 20020217 this was null when opening an editor that was
		// already open
		if (fTextEditor != null) {
			IGotoMarker markerGotoer = (IGotoMarker) fTextEditor.getAdapter(IGotoMarker.class);
			markerGotoer.gotoMarker(marker);
		}
	}

	public void init(IEditorSite site, IEditorInput input) throws PartInitException {
		editorInputIsAcceptable(input);
		try {
			super.init(site, input);
			if (partListener == null) {
				partListener = new PartListener();
			}
			// getSite().getPage().addPartListener(partListner);
			// we want to listen for our own activation
			IWorkbenchWindow window = getSite().getWorkbenchWindow();
			window.getPartService().addPartListener(partListener);
			window.getShell().addShellListener(partListener);
		}
		catch (Exception e) {
			// log for now, unless we find reason not to
			Logger.log(Logger.INFO, e.getMessage());
		}
		setPartName(input.getName());
	}

	/*
	 * (non-Javadoc) Returns whether the "save as" operation is supported by
	 * this editor. <p> Subclasses must override this method to implement the
	 * open-save-close lifecycle for an editor. For greater details, see
	 * <code> IEditorPart </code></p>
	 * 
	 * @see IEditorPart
	 */
	public boolean isSaveAsAllowed() {
		return fTextEditor != null && fTextEditor.isSaveAsAllowed();
	}

	/*
	 * (non-Javadoc) Returns whether the contents of this editor should be
	 * saved when the editor is closed. <p> This method returns <code> true
	 * </code> if and only if the editor is dirty ( <code> isDirty </code> ).
	 * </p>
	 */
	public boolean isSaveOnCloseNeeded() {
		// overriding super class since it does a lowly isDirty!
		if (fTextEditor != null)
			return fTextEditor.isSaveOnCloseNeeded();
		return isDirty();
	}

	/**
	 * Notifies this multi-page editor that the page with the given id has
	 * been activated. This method is called when the user selects a different
	 * tab.
	 * 
	 * @param newPageIndex
	 *            the index of the activated page
	 */
	protected void pageChange(int newPageIndex) {
		super.pageChange(newPageIndex);

		saveLastActivePageIndex(newPageIndex);
	}

	/**
	 * Posts the update code "behind" the running operation.
	 */
	protected void postOnDisplayQue(Runnable runnable) {
		IWorkbench workbench = PlatformUI.getWorkbench();
		IWorkbenchWindow[] windows = workbench.getWorkbenchWindows();
		if (windows != null && windows.length > 0) {
			Display display = windows[0].getShell().getDisplay();
			display.asyncExec(runnable);
		}
		else
			runnable.run();
	}

	/**
	 * Indicates that a property has changed.
	 * 
	 * @param source
	 *            the object whose property has changed
	 * @param propId
	 *            the id of the property which has changed; property ids are
	 *            generally defined as constants on the source class
	 */
	public void propertyChanged(Object source, int propId) {
		switch (propId) {
			// had to implement input changed "listener" so that
			// strucutedText could tell it containing editor that
			// the input has change, when a 'resource moved' event is
			// found.
			case IEditorPart.PROP_INPUT :
			case IEditorPart.PROP_DIRTY : {
				if (source == fTextEditor) {
					if (fTextEditor.getEditorInput() != getEditorInput()) {
						setInput(fTextEditor.getEditorInput());
						// title should always change when input changes.
						// create runnable for following post call
						Runnable runnable = new Runnable() {
							public void run() {
								_firePropertyChange(IWorkbenchPart.PROP_TITLE);
							}
						};
						// Update is just to post things on the display queue
						// (thread). We have to do this to get the dirty
						// property to get updated after other things on the
						// queue are executed.
						postOnDisplayQue(runnable);
					}
				}
				break;
			}
			case IWorkbenchPart.PROP_TITLE : {
				// update the input if the title is changed
				if (source == fTextEditor) {
					if (fTextEditor.getEditorInput() != getEditorInput()) {
						setInput(fTextEditor.getEditorInput());
					}
				}
				break;
			}
			default : {
				// propagate changes. Is this needed? Answer: Yes.
				if (source == fTextEditor) {
					firePropertyChange(propId);
				}
				break;
			}
		}

	}

	protected void safelySanityCheckState() {
		// If we're called before editor is created, simply ignore since we
		// delegate this function to our embedded TextEditor
		if (getTextEditor() == null)
			return;

		getTextEditor().safelySanityCheckState(getEditorInput());

	}

	protected void saveLastActivePageIndex(int newPageIndex) {
		// save the last active page index to preference manager
		getPreferenceStore().setValue(IXMLPreferenceNames.LAST_ACTIVE_PAGE, newPageIndex);
	}

	/**
	 * Sets the currently active page.
	 */
	protected void setActivePage() {
		// retrieve the last active page index from preference manager
		int activePageIndex = getPreferenceStore().getInt(IXMLPreferenceNames.LAST_ACTIVE_PAGE);

		// We check this range since someone could hand edit the XML
		// preference file to an invalid value ... which I know from
		// experience :( ... if they do, we'll reset to default and continue
		// rather than throw an assertion error in the setActivePage(int)
		// method.
		if (activePageIndex < 0 || activePageIndex >= getPageCount()) {
			activePageIndex = fSourcePageIndex;
		}
		setActivePage(activePageIndex);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.part.EditorPart#setInput(org.eclipse.ui.IEditorInput)
	 */
	protected void setInput(IEditorInput input) {
		// If driven from the Source page, it's "model" may not be up to date
		// with the input just yet. We'll rely on later notification from the
		// TextViewer to set us straight
		super.setInput(input);
		setPartName(input.getName());
	}

}
