/*******************************************************************************
 * 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.StructuredTextEditor;
import org.eclipse.wst.xml.core.XMLPreferenceNames;
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(XMLPreferenceNames.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(XMLPreferenceNames.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);
	  }
	  
	}
