/*******************************************************************************
 * 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.xsd.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.sse.ui.internal.provisional.extensions.ISourceEditingTextTools;
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.provisional.IDOMSourceEditingTextTools;
import org.eclipse.wst.xml.ui.internal.tabletree.XMLEditorMessages;
import org.w3c.dom.Document;

public class XSDMultiPageEditorPart extends PostSelectionMultiPageEditorPart implements IPropertyListener
{

  /**
   * 
   */
  public XSDMultiPageEditorPart()
  {
    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 == XSDMultiPageEditorPart.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, XSDEditorPlugin.getXSDString("_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) {
				public IEditorActionBarContributor getActionBarContributor() {
					IEditorActionBarContributor contributor = super.getActionBarContributor();
					XSDMultiPageEditorPart.this.getEditorSite().getActionBarContributor();
					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);
    }
    fTextEditor = null;

    // 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 Document getDOMDocument() {
    if (getTextEditor() == null)
      return null;

    ISourceEditingTextTools tools = (ISourceEditingTextTools) getAdapter(ISourceEditingTextTools.class);
    if(tools != null && tools instanceof IDOMSourceEditingTextTools) {
    	return ((IDOMSourceEditingTextTools)tools).getDOMDocument();
    }
    return null;
  }

  protected IStructuredModel getModel() {
    IStructuredModel model = null;
    if (fTextEditor != null)
      model = fTextEditor.getModel();
    return model;
  }

  protected IPreferenceStore getPreferenceStore() {
    return XSDEditorPlugin.getPlugin().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());
  }
  
}
