/*******************************************************************************
 * 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.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
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.swt.widgets.Shell;
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.ui.part.MultiPageEditorPart;
import org.eclipse.ui.part.MultiPageEditorSite;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.exceptions.SourceEditingRuntimeException;
import org.eclipse.wst.sse.ui.internal.StructuredTextEditor;
import org.eclipse.wst.xml.core.internal.provisional.IXMLPreferenceNames;
import org.eclipse.wst.xml.ui.internal.Logger;
import org.eclipse.wst.xml.ui.internal.provisional.StructuredTextEditorXML;
import org.eclipse.wst.xml.ui.internal.tabletree.XMLEditorMessages;

public class WSDLMultiPageEditorPart extends MultiPageEditorPart 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 exception) {
	      // dispose editor
	      dispose();

	      throw new SourceEditingRuntimeException(exception, WSDLEditorPlugin.getWSDLString("An_error_has_occurred_when1_ERROR_")); //$NON-NLS-1$
	    }
	  }


	  /* (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 MultiPageEditorSite(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;
	        }
	      };
	    }
	    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 StructuredTextEditorXML();
	  }

	  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();
	    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) {
	      if (e instanceof SourceEditingRuntimeException) {
	        Throwable t = ((SourceEditingRuntimeException) e).getOriginalException();
	        if (t instanceof IOException) {
	          System.out.println(t);
	          // file not found
	        }
	      }
	    }
	    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());
	  }

	  /**
	   * IExtendedMarkupEditor method
	   */
	  public IStatus validateEdit(Shell context) {
	    if (getTextEditor() == null)
	      return new Status(IStatus.ERROR, WSDLEditorPlugin.PLUGIN_ID, IStatus.INFO, "", null); //$NON-NLS-1$

	    return getTextEditor().validateEdit(context);
	  }
	  
	}
