/*
 * Copyright (c) 2012, 2018 CEA and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v20.html
 *
 * Contributors:
 *   Christian W. Damus (CEA) - initial API and implementation
 *   Kenn Hussey (CEA) - 509329
 *   Kenn Hussey - 535301
 */
package org.eclipse.uml2.uml.validation;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.DiagnosticChain;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EValidator;
import org.eclipse.emf.validation.IValidationContext;
import org.eclipse.emf.validation.model.ConstraintStatus;
import org.eclipse.emf.validation.model.IConstraintStatus;
import org.eclipse.emf.validation.model.IModelConstraint;
import org.eclipse.emf.validation.service.IConstraintDescriptor;
import org.eclipse.uml2.uml.UMLPlugin;

/**
 * Implementation of a constraint that delegates to an {@link EPackage}'s
 * constraints via its generated {@link EValidator}.
 */
class DelegatingModelConstraint
		implements IModelConstraint {

	private final IConstraintDescriptor descriptor;

	private final EValidator delegate;

	private final EValidator.SubstitutionLabelProvider labelProvider;

	private final Method constraintMethod;

	/**
	 * Initializes me.
	 */
	DelegatingModelConstraint(String namespace, EValidator delegate,
			EValidator.SubstitutionLabelProvider labelProvider, EClass target,
			Method constraintMethod) {
		// strip the type-qualifying part off of the validator method name
		String name = constraintMethod.getName();
		String expectedPrefix = String.format("validate%s_validate", //$NON-NLS-1$
			target.getName());
		if (name.startsWith(expectedPrefix)) {
			name = name.substring(expectedPrefix.length());
		}

		this.descriptor = new DelegatingConstraintDescriptor(namespace, target,
			name);
		this.delegate = delegate;
		this.labelProvider = labelProvider;
		this.constraintMethod = constraintMethod;
	}

	public final IConstraintDescriptor getDescriptor() {
		return descriptor;
	}

	public IStatus validate(IValidationContext ctx) {
		IStatus result;

		final ContextAdapter ctxAdapter = ContextAdapter.getInstance(ctx);
		final BasicDiagnostic diagnostics = ctxAdapter.getDiagnostics();
		final Map<Object, Object> contextMap = ctxAdapter.getContextMap();

		try {
			// pass the label provider (if any) to the validator
			contextMap.put(EValidator.SubstitutionLabelProvider.class,
				labelProvider);

			boolean isOK = (Boolean) constraintMethod.invoke(delegate,
				ctx.getTarget(), diagnostics, contextMap);

			if (isOK) {
				result = ctx.createSuccessStatus();
			} else {
				final int count = diagnostics.getChildren().size();

				switch (count) {
					case 0 :
						result = ctx.createFailureStatus(getDescriptor()
							.getName());
						break;
					case 1 :
						result = toConstraintStatus(ctx, diagnostics
							.getChildren().get(0));
						break;
					default :
						List<IStatus> statuses = new java.util.ArrayList<IStatus>(
							diagnostics.getChildren().size());
						for (Diagnostic next : diagnostics.getChildren()) {
							statuses.add(toConstraintStatus(ctx, next));
						}
						result = ConstraintStatus.createMultiStatus(ctx,
							statuses);
						break;
				}
			}
		} catch (InvocationTargetException e) {
			// disable this constraint in future validation operations
			ctx.disableCurrentConstraint(e.getTargetException());

			result = ConstraintStatus.createStatus(ctx, ctx.getTarget(), ctx
				.getResultLocus(), IStatus.WARNING, getDescriptor()
				.getStatusCode(), UMLPlugin.INSTANCE
				.getString("_UI_Validation_runtimeError"), //$NON-NLS-1$
				getDescriptor().getException().getMessage());
		} catch (Exception e) {
			// disable this constraint in future validation operations
			ctx.disableCurrentConstraint(e);

			result = ConstraintStatus.createStatus(ctx, ctx.getTarget(), ctx
				.getResultLocus(), IStatus.WARNING, getDescriptor()
				.getStatusCode(), UMLPlugin.INSTANCE
				.getString("_UI_Validation_linkageError"), //$NON-NLS-1$
				e.getMessage());
		}

		return result;
	}

	private static IConstraintStatus toConstraintStatus(IValidationContext ctx,
			Diagnostic diagnostic) {
		final EObject target = ctx.getTarget();

		// collect the "result locus" on which to create problem markers, or
		// whatever
		List<EObject> resultLocus = new java.util.ArrayList<EObject>(3);
		for (Object next : diagnostic.getData()) {
			if ((next != target) && (next instanceof EObject)) {
				resultLocus.add((EObject) next);
			}
		}

		return ConstraintStatus.createStatus(ctx, target, resultLocus,
			diagnostic.getSeverity(), diagnostic.getCode(), "{0}", //$NON-NLS-1$
			diagnostic.getMessage());
	}

	//
	// Nested types
	//

	/**
	 * A translation from the EMF Validation Framework's
	 * {@link IValidationContext}-based API to EMF's {@link DiagnosticChain}-
	 * and map-based API. A weak mapping ensures that the same adapters are
	 * reused as appropriate for any given instance of the validation context.
	 */
	private static final class ContextAdapter {

		private static final Map<IValidationContext, ContextAdapter> contextAdapters = new java.util.WeakHashMap<IValidationContext, ContextAdapter>();

		private Map<Object, Object> contextMap = new java.util.HashMap<Object, Object>();

		private BasicDiagnostic diagnostics;

		ContextAdapter() {
			super();
		}

		static ContextAdapter getInstance(IValidationContext ctx) {
			ContextAdapter result = contextAdapters.get(ctx);

			if (result == null) {
				result = new ContextAdapter();
				contextAdapters.put(ctx, result);
			}

			return result;
		}

		Map<Object, Object> getContextMap() {
			return contextMap;
		}

		BasicDiagnostic getDiagnostics() {
			if ((diagnostics != null) && !diagnostics.getChildren().isEmpty()) {
				// self-destruct a diagnostic that previously had problems added
				// to it
				diagnostics = null;
			}

			if (diagnostics == null) {
				diagnostics = new BasicDiagnostic();
			}

			return diagnostics;
		}
	}
}
