package org.etsi.mts.tdl;

import java.net.URISyntaxException;
import java.net.URL;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.DiagnosticChain;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EValidator;
import org.eclipse.emf.ecore.resource.Resource.Diagnostic;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal;
import org.eclipse.ocl.pivot.resource.CSResource;
import org.eclipse.ocl.pivot.utilities.PivotUtil;
import org.eclipse.ocl.xtext.completeocl.validation.CompleteOCLEObjectValidator;
import org.etsi.mts.tdl.extendedconfigurations.ExtendedConfigurationsPackage;
import org.etsi.mts.tdl.structuredobjectives.StructuredObjectivesPackage;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;

public class Activator implements BundleActivator {

	@Override
	public void start(BundleContext context) throws Exception {

//		registerValidator("model/tdl-structured-constraints.ocl", StructuredObjectivesPackage.eINSTANCE, context);
//		registerValidator("model/tdl-configurations-constraints.ocl", ExtendedConfigurationsPackage.eINSTANCE, context);
		registerValidator("model/tdl-constraints.ocl", tdlPackage.eINSTANCE, context);

	}

	void registerValidator(String path, EPackage ePakcage, BundleContext context) {

		Path oclPath = new Path(path);
		URL oclURL = FileLocator.find(context.getBundle(), oclPath);

		URI oclURI;
		try {
			oclURI = URI.createURI(oclURL.toURI().toString());
			CompleteOCLEObjectValidator validator = new CompleteOCLEObjectValidator(ePakcage, oclURI) {
				@Override
				public boolean initialize(@NonNull EnvironmentFactoryInternal environmentFactory) {
					boolean success = super.initialize(environmentFactory);
					if (success) {
						// This should happen in super.initialize(..) but under certain conditions it returns early
						ResourceSet resourceSet = environmentFactory.getResourceSet();
						CSResource xtextResource = (CSResource) resourceSet.getResource(oclURI, true);
						EList<Diagnostic> errors = xtextResource.getErrors();
						assert errors != null;
						String message = PivotUtil.formatResourceDiagnostics(errors, "", "\n");
						if (message != null) {
							System.err.println("Failed to load '" + oclURI + message);
							return false;
						}
					}
					return success;
				}
				@Override
				protected boolean validatePivot(@NonNull EClassifier eClassifier, @Nullable Object object,
						@Nullable DiagnosticChain diagnostics, Map<Object, Object> validationContext) {
					// Don't validate derived files
					if (object instanceof EObject) {
						URI uri = ((EObject) object).eResource().getURI();
						IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(uri.toPlatformString(true)));
						if (file != null && file.isDerived())
							return true;
					}
					return super.validatePivot(eClassifier, object, diagnostics, validationContext);
				}
			};
			EValidator.Registry.INSTANCE.put(tdlPackage.eINSTANCE, validator);
		} catch (URISyntaxException e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public void stop(BundleContext context) throws Exception {
		EValidator.Registry.INSTANCE.remove(StructuredObjectivesPackage.eINSTANCE);
		EValidator.Registry.INSTANCE.remove(ExtendedConfigurationsPackage.eINSTANCE);
		EValidator.Registry.INSTANCE.remove(tdlPackage.eINSTANCE);
	}

}
