/*****************************************************************************
 * Copyright (c) 2013, 2017 CEA LIST.
 *
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *   CEA LIST - Initial API and implementation
 *****************************************************************************/
package org.eclipse.papyrus.cdo.validation.problems.util;

import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.concurrent.CopyOnWriteArrayList;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.notify.impl.BasicNotifierImpl.EObservableAdapterList;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.ECrossReferenceAdapter;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.papyrus.cdo.validation.problems.EProblem;
import org.eclipse.papyrus.cdo.validation.problems.EProblemsContainer;
import org.eclipse.papyrus.cdo.validation.problems.ESeverity;
import org.eclipse.papyrus.cdo.validation.problems.ProblemsFactory;
import org.eclipse.papyrus.cdo.validation.problems.ProblemsPackage;
import org.eclipse.papyrus.cdo.validation.problems.internal.ProblemsPlugin;

/**
 * A utility for managing a single {@link EProblemsContainer} containing
 * problems for model elements in a {@link ResourceSet} scope.
 */
public class ProblemsManager {

	private final ManagerAdapter adapter;

	private EProblemsContainer problems;

	private ECrossReferenceAdapter xrefs;

	private ProblemsAdapter problemsAdapter;

	private CopyOnWriteArrayList<ProblemsListener> listeners = new CopyOnWriteArrayList<ProblemsListener>();

	ProblemsManager(Notifier notifier) {
		adapter = new ManagerAdapter();
		notifier.eAdapters().add(adapter);
		((EObservableAdapterList) notifier.eAdapters()).addListener(adapter);

		xrefs = ECrossReferenceAdapter.getCrossReferenceAdapter(notifier);

		problems = ProblemsFactory.eINSTANCE.createEProblemsContainer();
		if (xrefs != null) {
			problems.eAdapters().add(xrefs);
		}

		problemsAdapter = new ProblemsAdapter();
		problems.eAdapters().add(problemsAdapter);
	}

	/**
	 * Gets the problems manager associated with the specified {@code resourceSet}. If none has been created yet, then it is created and
	 * associated on demand.
	 *
	 * @param resourceSet
	 *            a resource set
	 *
	 * @return the {@code resourceSet}'s problems manager (never {@code null})
	 */
	public static ProblemsManager getProblemsManager(ResourceSet resourceSet) {
		ProblemsManager result = null;

		for (Adapter next : resourceSet.eAdapters()) {
			if (next instanceof ManagerAdapter) {
				result = ((ManagerAdapter) next).getManager();
				break;
			}
		}

		if (result == null) {
			result = new ProblemsManager(resourceSet);
		}

		return result;
	}

	/**
	 * Creates a new problems manager on a custom problem class and associates
	 * it with the specified {@code resourceSet}.
	 *
	 * @param resourceSet
	 *            a resource set
	 * @param customProblemClass
	 *            an {@link EClass} conforming to <tt>EProblem</tt> to create
	 *            instead of the default <tt>EProblem</tt> type
	 *
	 * @return the new problems manager
	 */
	public static ProblemsManager createProblemsManager(ResourceSet resourceSet, EClass customProblemClass) {
		if (customProblemClass == null) {
			throw new IllegalArgumentException("null customProblemClass"); //$NON-NLS-1$
		}

		return new ProblemsManager.Custom(resourceSet, customProblemClass);
	}

	public static IStatus toIStatus(EProblem problem) {
		return new StatusWrapper(problem);
	}

	public EProblem createProblem(Diagnostic diagnostic) {
		return createProblem(diagnostic, null);
	}

	public EProblem createProblem(Diagnostic diagnostic, String type) {
		EProblem result;
		EObject element = null;

		Iterator<?> data = diagnostic.getData().iterator();
		while (data.hasNext()) {
			Object next = data.next();

			// CDOResources are EObjects
			if ((next instanceof EObject) && !(next instanceof Resource)) {
				element = (EObject) next;
				break;
			}
		}

		if (element == null) {
			// can't create a problem without the element to attach it to
			result = null;
		} else {
			result = createProblem();

			result.setSeverity(ESeverity.get(diagnostic.getSeverity()));
			result.setSource(diagnostic.getSource());
			result.setCode(diagnostic.getCode());
			result.setMessage(diagnostic.getMessage());

			if (type != null) {
				result.setType(type);
			}

			result.setElement(element);
			while (data.hasNext()) {
				Object next = data.next();

				// CDOResources are EObjects
				if ((next instanceof EObject) && !(next instanceof Resource)) {
					result.getRelated().add((EObject) next);
				}
			}
		}

		return result;
	}

	/**
	 * Obtains all of the problems tracked by this problems manager.
	 */
	public Iterator<EProblem> getAllProblems() {
		return problems.allProblems();
	}

	/**
	 * Obtains all of the problems tracked by this problems manager for the
	 * specified {@code eObject}.
	 *
	 * @param eObject
	 *            an object in the resource set scope for which I track problems
	 */
	public Iterator<EProblem> getAllProblems(EObject eObject) {
		Iterator<EProblem> result;

		if (xrefs == null) {
			result = problems.allProblems(eObject);
		} else {
			result = new EProblemsIterator<EStructuralFeature.Setting>(xrefs.getNonNavigableInverseReferences(eObject).iterator()) {

				@Override
				protected EProblem convert(EStructuralFeature.Setting object) {
					return object.getEStructuralFeature() == ProblemsPackage.Literals.EPROBLEM__ELEMENT ? (EProblem) object.getEObject() : null;
				}
			};
		}

		return result;
	}

	/**
	 * Obtains all of the problems tracked by this problems manager for the
	 * objects in the specified {@code resource}.
	 *
	 * @param resource
	 *            an resource in the resource set scope for which I track
	 *            problems
	 */
	public Iterator<EProblem> getAllProblems(final Resource resource) {
		Iterator<EProblem> result;

		if (xrefs == null) {
			// more efficient to iterate all problems and filter for those whose
			// element is in the resource than to repeat iteration over the
			// problems for each object in the resource
			result = new Iterator<EProblem>() {

				private final Iterator<EProblem> all = getAllProblems();

				private EProblem next;

				@Override
				public boolean hasNext() {
					if (next == null) {
						while (all.hasNext()) {
							EProblem couldBe = all.next();
							if (couldBe.getElement().eResource() == resource) {
								next = couldBe;
								break;
							}
						}
					}

					return next != null;
				}

				@Override
				public EProblem next() {
					if (!hasNext()) {
						throw new NoSuchElementException();
					}

					EProblem result = next;
					next = null;
					return result;
				}

				@Override
				public void remove() {
					throw new UnsupportedOperationException("remove"); //$NON-NLS-1$
				}
			};
		} else {
			// concatenate iterators for all of the proper contents of the
			// resource
			result = new Iterator<EProblem>() {

				private final Iterator<EObject> objects = EcoreUtil.getAllProperContents(resource, false);

				private Iterator<EProblem> iterator = Collections.<EProblem> emptyList().iterator();

				@Override
				public boolean hasNext() {
					while (!iterator.hasNext() && objects.hasNext()) {
						iterator = getAllProblems(objects.next());
					}

					return iterator.hasNext();
				}

				@Override
				public EProblem next() {
					if (!hasNext()) {
						throw new NoSuchElementException();
					}

					return iterator.next();
				}

				@Override
				public void remove() {
					throw new UnsupportedOperationException("remove"); //$NON-NLS-1$
				}
			};
		}

		return result;
	}

	public boolean addProblem(EProblem problem) {
		return problems.getProblems().add(problem);
	}

	public boolean addDiagnostic(Diagnostic diagnostic) {
		return addDiagnostic(diagnostic, null);
	}

	public boolean addDiagnostic(Diagnostic diagnostic, String type) {
		boolean result;

		if (!diagnostic.getChildren().isEmpty()) {
			// add the children
			result = false;
			for (Diagnostic next : diagnostic.getChildren()) {
				result = addDiagnostic(next, type) || result;
			}
		} else {
			EProblem problem = createProblem(diagnostic, type);
			result = problem != null && addProblem(problem);
		}

		return result;
	}

	public void purgeProblems(EObject object) {
		purgeProblems(Collections.singleton(object));
	}

	@SuppressWarnings("unchecked")
	public void purgeProblems(Collection<? extends EObject> objects) {
		purgeProblems((Iterator<? extends EObject>) EcoreUtil.getAllContents(objects));
	}

	public void purgeProblems(Resource resource) {
		purgeProblems(EcoreUtil.<EObject> getAllProperContents(resource, false));
	}

	public void purgeAllProblems() {
		for (EProblem next : problems.getProblems()) {
			next.eAdapters().clear();
		}
		problems.getProblems().clear();
	}

	/**
	 * Disposes me. I remove any adapters I may have attached to any notifiers
	 * and purge my problems model. After invocation of this method, I can no
	 * longer be used.
	 */
	public void dispose() {
		if (problems != null) {
			problems.eAdapters().clear();
			for (Iterator<EObject> iter = problems.eAllContents(); iter.hasNext();) {
				iter.next().eAdapters().clear();
			}

			problems = null;
		}

		Notifier target = adapter.getTarget();
		if (target != null) {
			target.eAdapters().remove(adapter);
		}

		listeners.clear();
	}

	protected EProblem createProblem() {
		return ProblemsFactory.eINSTANCE.createEProblem();
	}

	void setCrossReferenceAdapter(ECrossReferenceAdapter adapter) {
		if (adapter != xrefs) {
			if (xrefs != null && problems != null) {
				problems.eAdapters().remove(xrefs);
			}

			xrefs = adapter;

			if (adapter != null && problems != null) {
				problems.eAdapters().add(adapter);
			}
		}
	}

	private void purgeProblems(Iterator<? extends EObject> contents) {
		List<EProblem> toRemove = new java.util.ArrayList<EProblem>();

		while (contents.hasNext()) {
			Iterator<EProblem> problems = getAllProblems(contents.next());
			while (problems.hasNext()) {
				toRemove.add(problems.next());
			}
		}

		for (EProblem next : toRemove) {
			next.eAdapters().clear();
		}
		problems.getProblems().removeAll(toRemove);
	}

	public static void delete(EProblem problem) {
		EcoreUtil.remove(problem);
		problem.setElement(null);
		problem.eAdapters().clear();
	}

	public void addProblemsListener(ProblemsListener listener) {
		listeners.addIfAbsent(listener);
	}

	public void removeProblemsListener(ProblemsListener listener) {
		listeners.remove(listener);
	}

	protected void fireAdded(EProblem problem) {
		if (!listeners.isEmpty()) {
			ProblemsEvent event = new ProblemsEvent(this, ProblemsEvent.ADDED, problem);
			for (ProblemsListener next : listeners) {
				try {
					next.problemAdded(event);
				} catch (Exception e) {
					ProblemsPlugin.INSTANCE.log(e);
				}
			}
		}
	}

	protected void fireRemoved(EProblem problem) {
		if (!listeners.isEmpty()) {
			ProblemsEvent event = new ProblemsEvent(this, ProblemsEvent.REMOVED, problem);
			for (ProblemsListener next : listeners) {
				try {
					next.problemRemoved(event);
				} catch (Exception e) {
					ProblemsPlugin.INSTANCE.log(e);
				}
			}
		}
	}

	//
	// Nested types
	//

	static class Custom extends ProblemsManager {

		private final EClass customProblemClass;

		public Custom(Notifier notifier, EClass customProblemClass) {
			super(notifier);

			if (!ProblemsPackage.Literals.EPROBLEM.isSuperTypeOf(customProblemClass)) {
				throw new IllegalArgumentException("customProblemClass does not conform to EProblem"); //$NON-NLS-1$
			}

			this.customProblemClass = customProblemClass;
		}

		@Override
		protected EProblem createProblem() {
			return (EProblem) EcoreUtil.create(customProblemClass);
		}
	}

	private class ManagerAdapter extends AdapterImpl implements EObservableAdapterList.Listener {

		ProblemsManager getManager() {
			return ProblemsManager.this;
		}

		@Override
		public void setTarget(Notifier newTarget) {
			super.setTarget(newTarget);

			if (newTarget == null) {
				// we've been unloaded. Unload the problems model
				dispose();
			}
		}

		@Override
		public void added(Notifier notifier, Adapter adapter) {
			if (adapter instanceof ECrossReferenceAdapter) {
				setCrossReferenceAdapter((ECrossReferenceAdapter) adapter);
			}
		}

		@Override
		public void removed(Notifier notifier, Adapter adapter) {
			if (adapter instanceof ECrossReferenceAdapter) {
				setCrossReferenceAdapter(null);
			}
		}
	}

	private class ProblemsAdapter extends AdapterImpl {

		@Override
		public void notifyChanged(Notification msg) {
			if (msg.getFeature() == ProblemsPackage.Literals.EPROBLEMS_CONTAINER__PROBLEMS) {
				switch (msg.getEventType()) {
				case Notification.ADD:
					fireAdded((EProblem) msg.getNewValue());
					break;
				case Notification.ADD_MANY:
					for (Object next : (Collection<?>) msg.getNewValue()) {
						fireAdded((EProblem) next);
					}
					break;
				case Notification.REMOVE:
					fireRemoved((EProblem) msg.getOldValue());
					break;
				case Notification.REMOVE_MANY:
					for (Object next : (Collection<?>) msg.getOldValue()) {
						fireRemoved((EProblem) next);
					}
					break;
				}
			}
		}
	}

	private static abstract class EProblemsIterator<E> implements Iterator<EProblem> {

		private final Iterator<? extends E> delegate;

		private EProblem preparedNext;

		public EProblemsIterator(Iterator<? extends E> delegate) {
			this.delegate = delegate;
		}

		@Override
		public boolean hasNext() {
			if (preparedNext == null) {
				while (delegate.hasNext()) {
					EProblem problem = convert(delegate.next());
					if (problem != null) {
						preparedNext = problem;
						break;
					}
				}
			}

			return preparedNext != null;
		}

		protected abstract EProblem convert(E object);

		@Override
		public EProblem next() {
			if (!hasNext()) {
				throw new NoSuchElementException();
			}

			EProblem result = preparedNext;
			preparedNext = null;
			return result;
		}

		@Override
		public void remove() {
			throw new UnsupportedOperationException("remove"); //$NON-NLS-1$
		}
	}

	private static class StatusWrapper implements IStatus {

		static final IStatus[] NO_STATUSES = new IStatus[0];

		private final EProblem problem;

		StatusWrapper(EProblem problem) {
			this.problem = problem;
		}

		@Override
		public IStatus[] getChildren() {
			return NO_STATUSES;
		}

		@Override
		public int getCode() {
			return problem.getCode();
		}

		@Override
		public Throwable getException() {
			return null;
		}

		@Override
		public String getMessage() {
			return problem.getMessage();
		}

		@Override
		public String getPlugin() {
			return problem.getSource();
		}

		@Override
		public int getSeverity() {
			return problem.getSeverity().getValue();
		}

		@Override
		public boolean isMultiStatus() {
			return false;
		}

		@Override
		public boolean isOK() {
			return getSeverity() == IStatus.OK;
		}

		@Override
		public boolean matches(int severityMask) {
			return (getSeverity() & severityMask) != 0;
		}
	}
}
