package org.eclipse.team.examples.filesystem.ui;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.team.core.history.IFileRevision;
import org.eclipse.team.ui.history.HistoryPage;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.BaseSelectionListenerAction;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.progress.IProgressService;

import it.mice.voila2.sync.plugin.Activator;

public class OpenFileSystemRevisionAction extends BaseSelectionListenerAction {

	private IStructuredSelection selection;
	private HistoryPage page;

	public OpenFileSystemRevisionAction(String text) {
		super(text);
	}

	public void run() {
		IStructuredSelection structSel = selection;

		Object[] objArray = structSel.toArray();

		for (int i = 0; i < objArray.length; i++) {
			Object tempRevision = objArray[i];

			final IFileRevision revision = (IFileRevision) tempRevision;
			if (revision == null || !revision.exists()) {
				MessageDialog.openError(page.getSite().getShell(), "Deleted Revision", "Can't open a deleted revision");
			} else {
				IRunnableWithProgress runnable = new IRunnableWithProgress() {
					public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
						IStorage file;
						try {
							file = revision.getStorage(monitor);
							String id = getEditorID(file.getName(), file.getContents());

							if (file instanceof IFile) {
								//if this is the current workspace file, open it
								IDE.openEditor(page.getSite().getPage(), (IFile) file);
							} else {
								FileSystemRevisionEditorInput fileRevEditorInput = new FileSystemRevisionEditorInput(revision);
								if (!editorAlreadyOpenOnContents(fileRevEditorInput))
									page.getSite().getPage().openEditor(fileRevEditorInput, id);
							}
						} catch (CoreException e) {
							throw new InvocationTargetException(e);
						}

					}
				};

				IProgressService progressService = PlatformUI.getWorkbench().getProgressService();
				try {
					progressService.run(false, false, runnable);
				} catch (InvocationTargetException e) {
				} catch (InterruptedException e) {
				}
			}

		}
	}

	/* private */String getEditorID(String fileName, InputStream contents) {
		IWorkbench workbench = Activator.getDefault().getWorkbench();
		IEditorRegistry registry = workbench.getEditorRegistry();
		IContentType type = null;
		if (contents != null) {
			try {
				type = Platform.getContentTypeManager().findContentTypeFor(contents, fileName);
			} catch (IOException e) {

			}
		}
		if (type == null) {
			type = Platform.getContentTypeManager().findContentTypeFor(fileName);
		}
		IEditorDescriptor descriptor = registry.getDefaultEditor(fileName, type);
		String id;
		if (descriptor == null || descriptor.isOpenExternal()) {
			id = "org.eclipse.ui.DefaultTextEditor"; //$NON-NLS-1$
		} else {
			id = descriptor.getId();
		}

		return id;
	}

	protected boolean updateSelection(IStructuredSelection selection) {
		this.selection = selection;
		return shouldShow();
	}

	public void setPage(HistoryPage page) {
		this.page = page;
	}

	private boolean shouldShow() {
		IStructuredSelection structSel = selection;
		Object[] objArray = structSel.toArray();

		if (objArray.length == 0)
			return false;

		for (int i = 0; i < objArray.length; i++) {
			IFileRevision revision = (IFileRevision) objArray[i];
			//check to see if any of the selected revisions are deleted revisions
			if (revision != null && !revision.exists())
				return false;
		}

		return true;
	}

	private boolean editorAlreadyOpenOnContents(FileSystemRevisionEditorInput input) {
		IEditorReference[] editorRefs = page.getSite().getPage().getEditorReferences();
		for (int i = 0; i < editorRefs.length; i++) {
			IEditorPart part = editorRefs[i].getEditor(false);
			if (part != null && part.getEditorInput() instanceof FileSystemRevisionEditorInput) {
				IFileRevision inputRevision = (IFileRevision) input.getAdapter(IFileRevision.class);
				IFileRevision editorRevision = (IFileRevision) part.getEditorInput().getAdapter(IFileRevision.class);

				if (inputRevision.equals(editorRevision)) {
					//make the editor that already contains the revision current
					page.getSite().getPage().activate(part);
					return true;
				}
			}
		}
		return false;
	}

}
