//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 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 implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.authoring.ui.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.epf.authoring.ui.AuthoringUIPlugin;
import org.eclipse.epf.authoring.ui.AuthoringUIResources;
import org.eclipse.epf.authoring.ui.editors.MethodElementEditor;
import org.eclipse.epf.authoring.ui.views.ConfigurationView;
import org.eclipse.epf.authoring.ui.views.LibraryView;
import org.eclipse.epf.library.ILibraryManager;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.persistence.refresh.IRefreshHandler;
import org.eclipse.epf.persistence.refresh.RefreshJob;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.dialogs.ListSelectionDialog;

/**
 * @author Phong Nguyen Le
 * @since 1.0
 */
public class RefreshHandler implements IRefreshHandler {

	private LibraryView libView;

	/**
	 * 
	 */
	public RefreshHandler() {
		super();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.epf.persistence.util.IRefreshHandler#refresh(org.eclipse.core.runtime.IProgressMonitor)
	 */
	public void refresh(final IProgressMonitor monitor) {
		libView = LibraryView.getView();
		Viewer viewer = libView != null ? libView.getViewer() : null;
		Control ctrl = viewer.getControl();
		if (ctrl == null || ctrl.isDisposed())
			return;

		if (ctrl.getDisplay().getThread() == Thread.currentThread()) {
			doRefresh(monitor);
		} else {
			ctrl.getDisplay().asyncExec(new Runnable() {

				public void run() {
					doRefresh(monitor);
				}

			});
		}
	}

	private void doRefresh(IProgressMonitor monitor) {
		if (!RefreshJob.getInstance().getRemovedResources().isEmpty()) {
			ArrayList removedResources = new ArrayList(RefreshJob.getInstance()
					.getRemovedResources());
			handleRemovedResources(removedResources);
			RefreshJob.getInstance().getRemovedResources().removeAll(
					removedResources);
		}
		if (!RefreshJob.getInstance().getChangedResources().isEmpty()) {
			ArrayList changedResources = new ArrayList(RefreshJob.getInstance()
					.getChangedResources());
			handleChangedResources(changedResources);
			RefreshJob.getInstance().getChangedResources().removeAll(
					changedResources);
		}
	}

	/**
	 * @param removedResources2
	 */
	private Collection handleRemovedResources(Collection removedResources) {
		return removedResources;
	}

	/**
	 * 
	 * @param changedResources
	 * @return resources that have been reloaded
	 */
	private Collection handleChangedResources(Collection changedResources) {
		Control ctrl = libView.getViewer().getControl();
		if (ctrl == null || ctrl.isDisposed())
			return Collections.EMPTY_LIST;
		IWorkbenchPage workbenchPage = libView.getSite().getPage();
		Shell shell = AuthoringUIPlugin.getDefault().getWorkbench()
				.getDisplay().getActiveShell();
		IEditorReference[] editorReferences = workbenchPage
				.getEditorReferences();
		ArrayList dirtyEditorsWithConflict = new ArrayList();
		ArrayList changedResourceList = new ArrayList(changedResources);
		// find all editor with dirty conflict
		//
		for (int i = 0; i < editorReferences.length; i++) {
			IEditorReference reference = editorReferences[i];
			IEditorPart editor = reference.getEditor(true);
			if (editor instanceof MethodElementEditor && editor.isDirty()) {
				Collection usedResources = ((MethodElementEditor) editor)
						.getUsedResources();
				check_resource: for (int j = 0; j < changedResourceList.size(); j++) {
					Resource resource = (Resource) changedResourceList.get(j);
					if (usedResources.contains(resource)) {
						dirtyEditorsWithConflict.add(editor);
						break check_resource;
					}
				}
			}
		}
		final ArrayList editorsToRefresh = new ArrayList();
		if (!dirtyEditorsWithConflict.isEmpty()) {
			// prompt user to discard changes in editors that conflict with
			// outside change
			//
			IStructuredContentProvider contentProvider = new IStructuredContentProvider() {
				List fContents;

				public Object[] getElements(Object inputElement) {
					if (fContents != null && fContents == inputElement)
						return fContents.toArray();
					return new Object[0];
				}

				public void dispose() {
				}

				public void inputChanged(Viewer viewer, Object oldInput,
						Object newInput) {
					if (newInput instanceof List)
						fContents = (List) newInput;
					else
						fContents = null;

				}

			};
			ILabelProvider labelProvider = new LabelProvider() {
				/*
				 * (non-Javadoc)
				 * 
				 * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
				 */
				public String getText(Object element) {
					if (element instanceof IEditorPart) {
						return ((IEditorPart) element).getTitle();
					}
					return super.getText(element);
				}

				/*
				 * (non-Javadoc)
				 * 
				 * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object)
				 */
				public Image getImage(Object element) {
					if (element instanceof IEditorPart) {
						return ((IEditorPart) element).getTitleImage();
					}
					return super.getImage(element);
				}
			};
			String title = AuthoringUIResources._UI_FileConflict_label; //$NON-NLS-1$
			String msg = AuthoringUIResources._WARN_FileConflict; 
			ListSelectionDialog dlg = new ListSelectionDialog(shell,
					dirtyEditorsWithConflict, contentProvider, labelProvider,
					msg);
			dlg.setTitle(title);
			dlg.setBlockOnOpen(true);
			dlg.open();
			Object[] result = dlg.getResult();
			for (int i = 0; i < result.length; i++) {
				Object editor = result[i];
				editorsToRefresh.add(editor);
				dirtyEditorsWithConflict.remove(editor);
			}
			// remove all resources used by dirty editors with conflict from the
			// collection of changed resources
			//
			for (int i = 0; i < dirtyEditorsWithConflict.size(); i++) {
				MethodElementEditor editor = (MethodElementEditor) dirtyEditorsWithConflict
						.get(i);
				Collection usedResources = editor.getUsedResources();
				changedResourceList.removeAll(usedResources);
			}
		}

		if (!changedResourceList.isEmpty()) {
			for (int i = 0; i < editorReferences.length; i++) {
				IEditorReference reference = editorReferences[i];
				IEditorPart editor = reference.getEditor(true);
				if (editor instanceof MethodElementEditor && !editor.isDirty()) {
					Collection usedResources = ((MethodElementEditor) editor)
							.getUsedResources();
					check_resource: for (int j = 0; j < changedResourceList
							.size(); j++) {
						Resource resource = (Resource) changedResourceList
								.get(j);
						if (usedResources.contains(resource)) {
							editorsToRefresh.add(editor);
							break check_resource;
						}
					}
				}
			}

			// Reload the selected changed resources.
			ILibraryManager manager = (ILibraryManager) LibraryService
					.getInstance().getCurrentLibraryManager();
			if (manager != null) {
				manager.reloadResources(changedResourceList);
			}

			libView.getViewer().refresh();
			ConfigurationView configView = ConfigurationView.getView();
			if (configView != null) {
				ctrl = configView.getViewer().getControl();
				if (ctrl != null && !ctrl.isDisposed()) {
					configView.getViewer().refresh();
				}
			}
		}
		if (!editorsToRefresh.isEmpty()) {
			shell.getDisplay().asyncExec(new Runnable() {

				public void run() {
					for (int i = 0; i < editorsToRefresh.size(); i++) {
						MethodElementEditor editor = (MethodElementEditor) editorsToRefresh
								.get(i);
						editor.refresh();
					}
				}

			});
		}

		return changedResourceList;
	}

}
