/*
 * Copyright (c) 2006-2008 Maskat Project.
 *
 * 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:
 *     Maskat Project - initial API and implementation
 */
package org.maskat.ui.editors;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.part.MultiPageEditorPart;
import org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor;

import org.maskat.ui.MaskatUIPlugin;
import org.maskat.ui.Messages;
import org.maskat.ui.editors.layout.LayoutGraphicalEditor;
import org.maskat.ui.editors.preview.LayoutPreviewBrowser;
import org.maskat.ui.editors.xml.MaskatXMLEditor;

public class MaskatEditor extends MultiPageEditorPart implements ISelectionListener,
		IResourceChangeListener, ITabbedPropertySheetPageContributor {

	/** The editor ID */
	public static final String EDITOR_ID = MaskatUIPlugin.PLUGIN_ID + ".maskatEditor"; //$NON-NLS-1$

	/** The graphical layout editor */
	private LayoutGraphicalEditor graphicalEditor;

	/** The layout definition XML editor */
	private MaskatXMLEditor xmlEditor;

	/** The web browser used to preview layout */
	private LayoutPreviewBrowser browser;

	public MaskatEditor() {
		super();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.part.MultiPageEditorPart#createPages()
	 */
	protected void createPages() {
		createLayoutGraphicalEditorPage();
		createLayoutXMLPage();
		createPreviewPage();
	}

	private void createLayoutGraphicalEditorPage() {
		try {
			graphicalEditor = new LayoutGraphicalEditor();
			int index = addPage(graphicalEditor, getEditorInput());
			setPageText(index, Messages.getString("editor.layout.tabname")); //$NON-NLS-1$
		} catch (PartInitException e) {
			ErrorDialog.openError(getSite().getShell(),
					Messages.getString("editor.msg.error.title"), //$NON-NLS-1$
					Messages.getString("editor.msg.error.createlayout"), //$NON-NLS-1$
					e.getStatus());
			
		} catch (Exception e) {
			MessageDialog.openError(getSite().getShell(),
					Messages.getString("editor.msg.error.title"), //$NON-NLS-1$
					Messages.getString("editor.msg.error.invalidlayout")); //$NON-NLS-1$
			MaskatUIPlugin.log(new Status(IStatus.ERROR, MaskatUIPlugin.PLUGIN_ID,	IStatus.ERROR,
					e.getMessage() == null ? e.getClass().getName() : e.getMessage(), e));
		}
	}

	private void createLayoutXMLPage() {
		try {
			xmlEditor = new MaskatXMLEditor();
			int index = addPage(xmlEditor, getEditorInput());
			setPageText(index, Messages.getString("editor.source.tabname")); //$NON-NLS-1$
		} catch (PartInitException e) {
			ErrorDialog.openError(getSite().getShell(),
					Messages.getString("editor.msg.error.title"), //$NON-NLS-1$
					Messages.getString("editor.msg.error.createsource"), //$NON-NLS-1$
					e.getStatus());
		}
	}

	private void createPreviewPage() {
		try {
			browser = new LayoutPreviewBrowser();
			int index = addPage(browser, getEditorInput());
			setPageText(index, Messages.getString("editor.preview.tabname")); //$NON-NLS-1$
		} catch (PartInitException e) {
			ErrorDialog.openError(getSite().getShell(),
					Messages.getString("editor.msg.error.title"), //$NON-NLS-1$
					Messages.getString("editor.msg.error.createpreview"), //$NON-NLS-1$
					e.getStatus());
		}
	}

	/**
	 * The <code>MultiPageEditorPart</code> implementation of this
	 * <code>IWorkbenchPart</code> method disposes all nested editors.
	 * Subclasses may extend.
	 */
	public void dispose() {
		ResourcesPlugin.getWorkspace().removeResourceChangeListener(this);
		getSite().getWorkbenchWindow().getSelectionService()
				.removeSelectionListener(this);
		super.dispose();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.part.EditorPart#doSave(org.eclipse.core.runtime.IProgressMonitor)
	 */
	public void doSave(IProgressMonitor monitor) {
		IEditorPart editor = getActiveEditor();
		if (editor != null) {
			if (editor == browser) {
				graphicalEditor.doSave(monitor);
				browser.setFocus();
			} else {
				editor.doSave(monitor);
			}
			if (editor == graphicalEditor) {
				graphicalEditor.setFocus();
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.part.EditorPart#doSaveAs()
	 */
	public void doSaveAs() {
		IEditorPart editor = getActiveEditor();
		if (editor != null) {
			editor.doSaveAs();
		}
	}

	/**
	 * Checks that the input is an instance of <code>IFileEditorInput</code>.
	 */
	public void init(IEditorSite site, IEditorInput editorInput) throws PartInitException {
		if (!(editorInput instanceof IFileEditorInput)) {
			throw new PartInitException(Messages.getString(
					"editor.msg.error.invalidinput")); //$NON-NLS-1$
		}
		super.init(site, editorInput);
		setPartName(editorInput.getName());

		ResourcesPlugin.getWorkspace().addResourceChangeListener(this);
		site.getWorkbenchWindow().getSelectionService().addSelectionListener(this);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.part.EditorPart#isSaveAsAllowed()
	 */
	public boolean isSaveAsAllowed() {
		IEditorPart editor = getActiveEditor();
		if (editor != null) {
			return editor.isSaveAsAllowed();
		}
		return false;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.part.MultiPageEditorPart#pageChange(int)
	 */
	protected void pageChange(int newPageIndex) {
		super.pageChange(newPageIndex);
		setFocus();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.core.resources.IResourceChangeListener#resourceChanged(org.eclipse.core.resources.IResourceChangeEvent)
	 */
	public void resourceChanged(final IResourceChangeEvent event) {
		final IFile file = ((FileEditorInput) getEditorInput()).getFile();
		if (event.getResource() instanceof IProject
				&& event.getType() == IResourceChangeEvent.PRE_CLOSE) {
			Display.getDefault().asyncExec(new Runnable() {
				public void run() {
					IWorkbenchPage[] pages = getSite().getWorkbenchWindow().getPages();
					for (int i = 0; i < pages.length; i++) {
						if (file.getProject().equals(event.getResource())) {
							IEditorPart editorPart = pages[i]
									.findEditor(getEditorInput());
							pages[i].closeEditor(editorPart, true);
						}
					}
				}
			});
		} else {
			IResourceDelta delta = event.getDelta();
			if (delta != null) {
				delta = delta.findMember(file.getFullPath());
			}
			if (delta != null && delta.getKind() == IResourceDelta.REMOVED) {
				Display.getDefault().asyncExec(new Runnable() {
					public void run() {
						IWorkbenchPage[] pages = getSite().getWorkbenchWindow()
								.getPages();
						for (int i = 0; i < pages.length; i++) {
							IEditorPart editorPart = pages[i]
									.findEditor(getEditorInput());
							pages[i].closeEditor(editorPart, true);
						}
					}
				});
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart,
	 *      org.eclipse.jface.viewers.ISelection)
	 */
	public void selectionChanged(IWorkbenchPart part, ISelection selection) {
		if (this.equals(part) && getActiveEditor() == graphicalEditor) {
			graphicalEditor.selectionChanged(graphicalEditor, selection);
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor#getContributorId()
	 */
	public String getContributorId() {
		return LayoutGraphicalEditor.EDITOR_ID;
	}
}
