/*****************************************************************************
 * Copyright (c) 2013, 2017 CEA LIST 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:
 *   CEA LIST - Initial API and implementation
 *   Eike Stepper (CEA) - bug 466520
 *****************************************************************************/
package org.eclipse.papyrus.cdo.internal.ui.editors;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.commands.operations.IOperationHistory;
import org.eclipse.core.commands.operations.IUndoContext;
import org.eclipse.core.commands.operations.IUndoableOperation;
import org.eclipse.emf.cdo.CDOObject;
import org.eclipse.emf.cdo.common.id.CDOID;
import org.eclipse.emf.cdo.common.lock.CDOLockState;
import org.eclipse.emf.cdo.common.revision.CDOIDAndBranch;
import org.eclipse.emf.cdo.dawn.gmf.util.DawnDiagramUpdater;
import org.eclipse.emf.cdo.dawn.spi.DawnState;
import org.eclipse.emf.cdo.transaction.CDOTransactionConflictEvent;
import org.eclipse.emf.cdo.transaction.CDOTransactionFinishedEvent;
import org.eclipse.emf.cdo.util.CDOUtil;
import org.eclipse.emf.cdo.view.CDOView;
import org.eclipse.emf.cdo.view.CDOViewInvalidationEvent;
import org.eclipse.emf.cdo.view.CDOViewLocksChangedEvent;
import org.eclipse.emf.common.command.CommandStack;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.notify.impl.BasicNotifierImpl.EObservableAdapterList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.change.util.ChangeRecorder;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EContentAdapter;
import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.workspace.IWorkspaceCommandStack;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.net4j.util.event.IEvent;
import org.eclipse.net4j.util.event.IListener;
import org.eclipse.papyrus.cdo.core.resource.CDOUndoContext;
import org.eclipse.papyrus.cdo.internal.core.CDOUtils;
import org.eclipse.papyrus.cdo.internal.ui.Activator;
import org.eclipse.papyrus.cdo.internal.ui.decorators.CDOStateAdapter;
import org.eclipse.papyrus.cdo.internal.ui.decorators.CDOStateLabelDecorator;
import org.eclipse.papyrus.cdo.internal.ui.l10n.Messages;
import org.eclipse.papyrus.cdo.internal.ui.util.UIUtil;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.papyrus.infra.core.services.ServicesRegistry;
import org.eclipse.papyrus.infra.widgets.toolbox.notification.Type;
import org.eclipse.papyrus.infra.widgets.toolbox.notification.builders.NotificationBuilder;

import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
 * This is the PapyrusTransactionListener type. Enjoy.
 */
public class PapyrusTransactionListener implements IListener {

	private final ServicesRegistry services;

	private final Predicate<Adapter> shouldPropagate = new Predicate<Adapter>() {

		@Override
		public boolean apply(Adapter input) {
			return (input instanceof ECrossReferenceAdapter) //
					|| (input instanceof EContentAdapter) //
					|| (input instanceof ChangeRecorder);
		}
	};

	private final Set<Adapter> contentAdapters;

	public PapyrusTransactionListener(ServicesRegistry services, ResourceSet resourceSet) {
		super();

		this.services = services;

		contentAdapters = Sets.newHashSet(Iterables.filter(resourceSet.eAdapters(), shouldPropagate));
		((EObservableAdapterList) resourceSet.eAdapters()).addListener(new EObservableAdapterList.Listener() {

			@Override
			public void added(Notifier notifier, Adapter adapter) {
				if (adapter instanceof EContentAdapter) {
					contentAdapters.add(adapter);
				}
			}

			@Override
			public void removed(Notifier notifier, Adapter adapter) {
				contentAdapters.remove(adapter);
			}
		});

	}

	@Override
	public void notifyEvent(IEvent event) {
		if (event instanceof CDOViewInvalidationEvent) {
			handleViewInvalidationEvent((CDOViewInvalidationEvent) event);
		} else if (event instanceof CDOTransactionConflictEvent) {
			handleTransactionConflictEvent((CDOTransactionConflictEvent) event);
		} else if (event instanceof CDOViewLocksChangedEvent) {
			handleLocksChangedEvent((CDOViewLocksChangedEvent) event);
		} else if (event instanceof CDOTransactionFinishedEvent) {
			handleTransactionFinishedEvent((CDOTransactionFinishedEvent) event);
		} else {
			handleEvent(event);
		}
	}

	protected void handleTransactionConflictEvent(CDOTransactionConflictEvent event) {
		if (UIUtil.ensureUIThread(this, event)) {
			CDOObject cdoObject = event.getConflictingObject();
			EObject element = CDOUtil.getEObject(cdoObject);
			View view = DawnDiagramUpdater.findViewByContainer(element);

			if (view == null) {
				// it's not actually a view that is conflicted, but a model
				// element
				if (cdoObject.cdoConflict()) {
					CDOStateAdapter.setState(element, DawnState.CONFLICT);

					CDOStateLabelDecorator.fireLabelUpdates();
				}
			}
		}
	}

	protected void handleLocksChangedEvent(CDOViewLocksChangedEvent event) {
		if (UIUtil.ensureUIThread(this, event)) {
			Map<EObject, DawnState> changedObjects = new HashMap<EObject, DawnState>();
			CDOView cdoView = event.getSource();

			for (CDOLockState state : event.getLockStates()) {
				Object lockedObject = state.getLockedObject();

				CDOID id;
				if (lockedObject instanceof CDOID) {
					id = (CDOID) lockedObject;
				} else if (lockedObject instanceof CDOIDAndBranch) {
					id = ((CDOIDAndBranch) lockedObject).getID();
				} else {
					throw new RuntimeException("Unexpected object type: " //$NON-NLS-1$
							+ lockedObject);
				}

				if (id != null) {
					CDOObject object = cdoView.getObject(id);
					EObject element = CDOUtil.getEObject(object);

					View view = DawnDiagramUpdater.findViewByContainer(element);

					if (view == null) {
						// it's not actually a view that is locked, but a model
						// element
						if (CDOUtils.isLocked(object, true)) {
							changedObjects.put(element, DawnState.LOCKED_REMOTELY);
						} else {
							changedObjects.put(element, DawnState.CLEAN);
						}
					}
				}
			}

			handleLocks(changedObjects);
		}
	}

	/**
	 * @precondition The current thread is the UI thread
	 */
	void handleLocks(Map<EObject, DawnState> changedObjects) {
		if (!changedObjects.isEmpty()) {
			for (Map.Entry<EObject, DawnState> next : changedObjects.entrySet()) {

				EObject element = next.getKey();
				DawnState state = next.getValue();

				CDOStateAdapter.setState(element, state);
			}

			CDOStateLabelDecorator.fireLabelUpdates();
		}
	}

	protected void handleViewInvalidationEvent(CDOViewInvalidationEvent event) {
		if (UIUtil.ensureUIThread(this, event)) {
			// process changed objects to ensure propagation of adapters to new objects.
			// CDO doesn't tell us about new objects, but it does tell us that their
			// containers changed, so we have to go fishing
			for (EObject next : CDOUtils.getEObjects(event.getDirtyObjects())) {
				for (EObject possiblyNew : next.eContents()) {
					synchronizeAdapters(possiblyNew);
				}
			}

			// also, purge any operations from the local history that changed the objects that
			// were changed by the remote transaction
			handleOperationHistory(event);
		}
	}

	protected void synchronizeAdapters(EObject object) {
		object.eAdapters().addAll(Sets.difference(contentAdapters, ImmutableSet.copyOf(object.eAdapters())));
	}

	protected void handleOperationHistory(CDOViewInvalidationEvent event) {
		IOperationHistory history = getOperationHistory();
		if (history != null) {
			Iterable<EObject> affectedObjects = CDOUtils.getEObjects(Iterables.concat(event.getDirtyObjects(), event.getDetachedObjects()));
			if (!Iterables.isEmpty(affectedObjects)) {
				IUndoContext context = new CDOUndoContext(affectedObjects);
				if (context != null) {
					IUndoableOperation undoOperation = history.getUndoOperation(context);
					IUndoableOperation redoOperation = history.getRedoOperation(context);

					if ((undoOperation != null) || (redoOperation != null)) {
						// notify listeners of the impending changes. We do this before flushing
						// the undo context because we depend on the fact that the UndoActionHandler
						// and RedoActionHandler only react when the operation is their current
						// operation (which means it mustn't have the context removed yet) *and* the
						// update is posted asynchronously
						if (undoOperation != null) {
							history.operationChanged(undoOperation);
						}
						if (redoOperation != null) {
							history.operationChanged(redoOperation);
						}

						// flush the history for this editor
						history.dispose(getEditorUndoContext(), true, true, false);

						NotificationBuilder.createAsyncPopup(Messages.PapyrusTransactionListener_0).setType(Type.INFO).run();
					}
				}
			}
		}
	}

	protected IOperationHistory getOperationHistory() {
		IOperationHistory result = null;

		try {
			EditingDomain domain = services.getService(TransactionalEditingDomain.class);
			if (domain != null) {
				CommandStack stack = domain.getCommandStack();
				if (stack instanceof IWorkspaceCommandStack) {
					result = ((IWorkspaceCommandStack) stack).getOperationHistory();
				}
			}
		} catch (ServiceException e) {
			Activator.log.error("Failed to get editor operation history from service registry.", e); //$NON-NLS-1$
		}

		return result;
	}

	protected IUndoContext getEditorUndoContext() {
		IUndoContext result = null;

		try {
			result = services.getService(IUndoContext.class);
		} catch (ServiceException e) {
			Activator.log.error("Failed to get editor undo context from service registry.", e); //$NON-NLS-1$
		}

		return result;
	}

	protected void handleTransactionFinishedEvent(CDOTransactionFinishedEvent event) {
		// review all conflicts and locks
		Map<EObject, DawnState> stateUpdates = Maps.newHashMap();

		for (CDOStateAdapter next : CDOStateAdapter.getAll(event.getSource().getResourceSet())) {

			Object target = next.getTarget();
			if (target instanceof EObject) {
				EObject object = (EObject) target;
				stateUpdates.put(object, CDOUtils.computeState(object));
			}
		}

		for (Map.Entry<EObject, DawnState> next : stateUpdates.entrySet()) {
			CDOStateAdapter.setState(next.getKey(), next.getValue());
		}

		CDOStateLabelDecorator.fireLabelUpdates();
	}

	protected void handleEvent(IEvent event) {
		// pass
	}
}
