/*******************************************************************************
 * 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 java.util.List;

import org.eclipse.core.internal.resources.ResourceException;
import org.eclipse.core.resources.IMarker;
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.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.swt.events.ShellAdapter;
import org.eclipse.swt.events.ShellEvent;
import org.eclipse.swt.graphics.Point;
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.IStructuredModel;
import org.eclipse.wst.sse.core.exceptions.SourceEditingRuntimeException;
import org.eclipse.wst.sse.core.internal.SSECorePlugin;
import org.eclipse.wst.sse.ui.internal.StructuredTextEditor;
import org.eclipse.wst.xml.core.IXMLPreferenceNames;
import org.eclipse.wst.xml.ui.StructuredTextEditorXML;
import org.w3c.dom.Document;
import org.w3c.dom.Node;

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(SSECorePlugin.getResourceString("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)) {
	        // todo use message formatter for {0}
	        Throwable coreException = coreExceptionArray[0];
	        if (coreException instanceof ResourceException) {
	          // 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(SSECorePlugin.getResourceString("23concat_EXC_", (new Object[]{input.getName()}))); //$NON-NLS-1$
	          //$NON-NLS-1$ = "Resource {0} does not exist."
	        }
	        else {
	          throw new PartInitException(SSECorePlugin.getResourceString("32concat_EXC_", (new Object[]{input.getName()}))); //$NON-NLS-1$
	          //$NON-NLS-1$ = "Editor could not be open on {0}"
	        }
	      }
	    }
	    else if (input instanceof IStorageEditorInput) {
	      InputStream contents = null;
	      try {
	        contents = ((IStorageEditorInput) input).getStorage().getContents();
	      }
	      catch (CoreException noStorageExc) {
	      }
	      if (contents == null) {
	        throw new PartInitException(SSECorePlugin.getResourceString("32concat_EXC_", (new Object[]{input.getName()}))); //$NON-NLS-1$
	      }
	      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;
	  }

	  /**
	   * IExtendedMarkupEditor method
	   */
	  public Node getCaretNode() {
	    if (getTextEditor() == null)
	      return null;

	    return getTextEditor().getCaretNode();
	  }

	  /**
	   * IExtendedSimpleEditor method
	   */
	  public int getCaretPosition() {
	    if (getTextEditor() == null)
	      return -1;

	    return getTextEditor().getCaretPosition();
	  }

	  /**
	   * IExtendedSimpleEditor method
	   */
	  public IDocument getDocument() {
	    if (getTextEditor() == null)
	      return null;

	    return getTextEditor().getDocument();
	  }

	  /**
	   * IExtendedMarkupEditor method
	   */
	  public Document getDOMDocument() {
	    if (getTextEditor() == null)
	      return null;

	    return getTextEditor().getDOMDocument();
	  }

	  /**
	   * IExtendedSimpleEditor method
	   */
	  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();
	  }

	  /**
	   * IExtendedMarkupEditor method
	   */
	  public List getSelectedNodes() {
	    if (getTextEditor() == null)
	      return null;
	    return getTextEditor().getSelectedNodes();
	  }

	  /**
	   * IExtendedSimpleEditor method
	   */
	  public Point getSelectionRange() {
	    if (getTextEditor() == null)
	      return new Point(-1, -1);

	    return getTextEditor().getSelectionRange();
	  }

	  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);
	  }
	  
	}
