/*******************************************************************************
 * Copyright (c) 2009, 2018 SAP AG 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:
 *     SAP AG - initial API and implementation
 ******************************************************************************/
package org.eclipse.ocl.examples.impactanalyzer.tests.instanceScope;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.impl.AdapterImpl;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.impl.DynamicEObjectImpl;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.ocl.ecore.OCL;
import org.eclipse.ocl.ecore.OCLExpression;
import org.eclipse.ocl.examples.impactanalyzer.ImpactAnalyzer;
import org.eclipse.ocl.examples.impactanalyzer.ImpactAnalyzerFactory;
import org.eclipse.ocl.examples.impactanalyzer.benchmark.preparation.model.ModelCloner;
import org.eclipse.ocl.examples.impactanalyzer.benchmark.preparation.notifications.NotificationResourceLoader;
import org.eclipse.ocl.examples.impactanalyzer.benchmark.preparation.notifications.RawNotification;
import org.eclipse.ocl.examples.impactanalyzer.benchmark.preparation.ocl.OCLExpressionFromClassTcsPicker;
import org.eclipse.ocl.examples.impactanalyzer.benchmark.preparation.ocl.OCLExpressionWithContext;
import org.eclipse.ocl.examples.impactanalyzer.configuration.OptimizationActivation;
import org.eclipse.ocl.examples.impactanalyzer.instanceScope.traceback.AbstractTracebackStep;
import org.eclipse.ocl.examples.impactanalyzer.util.OCLFactory;
import org.eclipse.ocl.examples.testutils.BaseTest;
import org.junit.Test;

import data.classes.ClassTypeDefinition;
import data.classes.ClassesFactory;
import data.classes.ClassesPackage;
import data.classes.MethodSignature;
import data.classes.SapClass;
import dataaccess.expressions.ExpressionsPackage;
import dataaccess.expressions.MethodCallExpression;

public class NgpmModelBasedOclIaTest extends BaseTest {
	Resource ngpmModel = null;
	List<RawNotification> modifyElementaryTypesTrace = null;

	@Override
	public void setUp(){
		ngpmModel = NotificationResourceLoader.loadModel("NgpmModel.xmi");
		modifyElementaryTypesTrace = NotificationResourceLoader.loadTrace("modifyElementaryTypesEventTrace.trace");
	}

	@Test
	public void testRenameStringAppendToAppend2() {
		final OCLExpression exp = (OCLExpression) OclIaTest
				.parse("context dataaccess::expressions::MethodCallExpression inv: "
						+ "self.object.getType().getInnermost().oclAsType(classes::ClassTypeDefinition).clazz.allSignatures()->select(s : MethodSignature | s.name='.'.concat('xxx'))",
						ClassesPackage.eINSTANCE).iterator().next().getSpecification().getBodyExpression();
		final MethodSignature append = (MethodSignature) ngpmModel.getEObject("E01F04667A9220905D0911DFA13BFF380A1CE22F");
		assertEquals("append", append.getName());
		final ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(
				exp, /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
		final boolean[] result = new boolean[1];
		append.eAdapters().add(new AdapterImpl() {
			@Override
			public void notifyChanged(Notification msg) {
				Collection<EObject> impact = ia.getContextObjects(msg);
				if (OptimizationActivation.getOption().isOperationCallSelectionActive()) {
					result[0] = impact.size() > 5 && impact.size() < 10;
					if (!result[0]) {
						System.err
						.println("Expected between 5 and 10 impacted MethodCallExpressions only for calls on string but found "
								+ impact.size());
					}
				} else {
					result[0] = impact.size() > 50 && impact.size() < 100;
					if (!result[0]) {
						System.err.println("Expected between 50 and 100 impacted MethodCallExpressions but found only "
								+ impact.size());
					}
				}
			}
		});
		append.setName("append2");
		assertTrue(result[0]);
	}

	@Test
	public void testVariableExpressionWithCollectionType() {
		OCLExpression exp = (OCLExpression) OclIaTest.parse("context NestedTypeDefinition inv: self.getNamedValuesInScope()", ClassesPackage.eINSTANCE).iterator().next().getSpecification().getBodyExpression();

		RawNotification rawNotification = modifyElementaryTypesTrace.get(1);
		Notification notification = rawNotification.convertToNotification(ModelCloner.cloneResource(ngpmModel,"1"));

		ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp,
				data.classes.ClassesPackage.eINSTANCE.getNestedTypeDefinition(),
				/* notifyOnNewContextElements */ false, OCLFactory.getInstance());
		Collection<EObject> impact = ia.getContextObjects(notification);
		assertEquals(impact.size(), 0);
	}

	public void testExpressionWithLargeNavigationStepGraph(){
		OCLExpressionWithContext expr = new OCLExpressionFromClassTcsPicker().pickUpExpression(44);

		Notification notification = getNotification(10, ngpmModel);

		ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(expr.getExpression(), expr.getContext(),/* notifyOnNewContextElements */ false, OCLFactory.getInstance());
		Collection<EObject> impact = ia.getContextObjects(notification);
		assertNotNull(impact);
	}

	@Test
	public void testSuperExpensiveChange() {
		final OCLExpression exp = (OCLExpression) OclIaTest
				.parse("context dataaccess::expressions::MethodCallExpression inv: "
						+ "self.object.getType().getInnermost().oclAsType(classes::ClassTypeDefinition).clazz.allSignatures()->select(s : MethodSignature | s.name='.'.concat('xxx'))",
						ClassesPackage.eINSTANCE).iterator().next().getSpecification().getBodyExpression();
		final SapClass string = (SapClass) ngpmModel.getEObject("E0B91841F0303550560511DECC310019D29902CC");
		final MethodSignature append = (MethodSignature) ngpmModel.getEObject("E01F04667A9220905D0911DFA13BFF380A1CE22F");
		final ClassTypeDefinition appendParamCTD = (ClassTypeDefinition) append.getInput().get(0).getOwnedTypeDefinition();
		assertEquals(string, appendParamCTD.getClazz());
		assertEquals("append", append.getName());
		final ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
		final boolean[] result = new boolean[1];
		appendParamCTD.setClazz(null);
		appendParamCTD.eAdapters().add(new AdapterImpl() {
			@Override
			public void notifyChanged(Notification msg) {
				Collection<EObject> impact = ia.getContextObjects(msg);
				result[0] = impact.size() == 0;
				if (!result[0]) {
					System.err.println("Expected unused check to find out that change has no impact but IA said " + impact.size()
					+ " objects were impacted");
				}
			}
		});
		appendParamCTD.setClazz(null);
		assertTrue(result[0]);
	}

	@Test
	public void testAllSignaturesDependencyOnChangingSomethingOnStringClass() {
		final OCLExpression exp = (OCLExpression) OclIaTest
				.parse("context SapClass inv: " + "self.allSignatures()",
						ClassesPackage.eINSTANCE).iterator().next().getSpecification().getBodyExpression();
		final SapClass string = (SapClass) ngpmModel.getEObject("E0B91841F0303550560511DECC310019D29902CC");
		final ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, data.classes.ClassesPackage.eINSTANCE.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
		final boolean[] result = new boolean[1];
		string.eAdapters().add(new AdapterImpl() {
			@Override
			public void notifyChanged(Notification msg) {
				Collection<EObject> impact = ia.getContextObjects(msg);
				result[0] = impact.size() == 2 && impact.contains(string);
			}
		});
		string.getOwnedSignatures().add(ClassesFactory.eINSTANCE.createMethodSignature());
		assertTrue(result[0]);
	}

	@Test
	public void testExpensiveAllSignaturesExpressionAddingMethodSignatureToString() {
		final OCLExpression exp = (OCLExpression) OclIaTest
				.parse("context MethodCallExpression inv: " +
						"self.object.getType().getInnermost().oclAsType(data::classes::ClassTypeDefinition).clazz.allSignatures()",
						ExpressionsPackage.eINSTANCE).iterator().next().getSpecification().getBodyExpression();
		final SapClass string = (SapClass) ngpmModel.getEObject("E0B91841F0303550560511DECC310019D29902CC");
		final MethodCallExpression callOnStringTypedExpression = (MethodCallExpression) ngpmModel.getEObject("E02C978BFD3F74805D0811DF8A6AFF380A1CE22F");
		final EList<MethodSignature> oldValue = ((ClassTypeDefinition) callOnStringTypedExpression.getObject().getType().getInnermost()).getClazz().allSignatures();
		final ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
		final boolean[] result = new boolean[1];
		string.eAdapters().add(new AdapterImpl() {
			@Override
			public void notifyChanged(Notification msg) {
				Collection<EObject> impact = ia.getContextObjects(msg);
				result[0] = impact.contains(callOnStringTypedExpression);
				if (!result[0]) {
					System.err
					.println("Expecting a method call on a string-typed expression to be impacted by adding a signature to String");
				} else {
					if (OptimizationActivation.getOption().isOperationCallSelectionActive()) {
						result[0] = impact.size() > 5 && impact.size() < 10;
						if (!result[0]) {
							System.err
							.println("Expected between 5 and 10 impacted MethodCallExpressions only for calls on string but found "
									+ impact.size());
						}
					} else {
						result[0] = impact.size() > 50 && impact.size() < 100;
						if (!result[0]) {
							System.err.println("Expected between 50 and 100 impacted MethodCallExpressions but found only "
									+ impact.size());
						}
					}
					Iterator<EObject> ii = impact.iterator();
					while (result[0] && ii.hasNext()) {
						EObject n = ii.next();
						result[0] = result[0] && (n instanceof MethodCallExpression);
						if (!result[0]) {
							System.err
							.println("Found an impacted object that was not, as expected, a MethodCallExpression: " + n);
						}
						if (OptimizationActivation.getOption().isOperationCallSelectionActive()) {
							// can enforce result type only if selective operation call traceback is active
							// because traceback visits OperationCallExp of getType() that are
							// not actually used and therefore returns a true superset; activate the following check if crisp
							// operation call
							// checking is performed
							result[0] = result[0]
									&& (((ClassTypeDefinition) (((MethodCallExpression) n).getObject().getType().getInnermost()))
											.getClazz().conformsTo(string));
							if (!result[0]) {
								System.err
								.println("Found an impacted MethodCallExpression that is not called on an object of type String but on "
										+ (((ClassTypeDefinition) (((MethodCallExpression) n).getObject().getType()
												.getInnermost())).getClazz().getName())
										+ ": "
										+ ((MethodCallExpression) n).getMethodSignature().getName());
							}
						}
					}
				}
			}
		});
		string.getOwnedSignatures().add(ClassesFactory.eINSTANCE.createMethodSignature());
		EList<MethodSignature> newValue = ((ClassTypeDefinition) callOnStringTypedExpression.getObject().getType().getInnermost()).getClazz().allSignatures();
		assertFalse("Expecting a method call on a string-typed expression to be impacted by adding a signature to String",
				newValue.equals(oldValue));
		assertTrue(result[0]);
	}

	@Test
	public void testUnusedForAdaptedSignaturesExpressionNullingClazzReferenceOnCTD() {
		final OCLExpression exp = (OCLExpression) OclIaTest
				.parse("context SapClass inv: " +
						"self.adaptedSignatures()",
						ClassesPackage.eINSTANCE).iterator().next().getSpecification().getBodyExpression();
		final SapClass string = (SapClass) ngpmModel.getEObject("E0B91841F0303550560511DECC310019D29902CC");
		final MethodSignature append = (MethodSignature) ngpmModel.getEObject("E01F04667A9220905D0911DFA13BFF380A1CE22F");
		final ClassTypeDefinition appendOutputCTD = (ClassTypeDefinition) append.getOutput();
		assertEquals(string, appendOutputCTD.getClazz());
		assertEquals("append", append.getName());
		final ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, data.classes.ClassesPackage.eINSTANCE.getSapClass(), /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
		final boolean[] result = new boolean[1];
		appendOutputCTD.eAdapters().add(new AdapterImpl() {
			@Override
			public void notifyChanged(Notification msg) {
				Collection<EObject> impact = ia.getContextObjects(msg);
				if (OptimizationActivation.getOption().isTracebackStepISAActive() && OptimizationActivation.getOption().isUnusedDetectionActive()) {
					result[0] = impact.size() == 0;
					if (!result[0]) {
						System.err.println("Expected unused check to find out that change has no impact but IA said "+impact.size()+
								" objects were impacted");
					}
				} else {
					result[0] = impact.size() == 2; // String and the formal type parameter "T extends String" in the generics test
					if (!result[0]) {
						System.err.println("Expected two impacted classes (String and T) but found "+impact.size());
					}
				}
			}
		});
		appendOutputCTD.setClazz(null);
		assertTrue(result[0]);
	}

	@Test
	public void testUnusedForAllSignaturesExpressionNullingClazzReferenceOnCTD() {
		final OCLExpression exp = (OCLExpression) OclIaTest
				.parse("context MethodCallExpression inv: " +
						"self.object.getType().getInnermost().oclAsType(data::classes::ClassTypeDefinition).clazz.allSignatures()",
						ExpressionsPackage.eINSTANCE).iterator().next().getSpecification().getBodyExpression();
		final SapClass string = (SapClass) ngpmModel.getEObject("E0B91841F0303550560511DECC310019D29902CC");
		// would have to be a call on the output of append()
		final MethodCallExpression callOnAppendCallResult = (MethodCallExpression) ngpmModel.getEObject("E012BF1E3D01FCF05D0E11DF9483DFF10A1CE22F");
		callOnAppendCallResult.getObject().setOwnedTypeDefinition(null); // force append's output type definition to be used in call's getType()
		final Object oldValue = org.eclipse.ocl.examples.impactanalyzer.util.OCL.newInstance().evaluate(callOnAppendCallResult, exp);
		final MethodSignature append = (MethodSignature) ngpmModel.getEObject("E01F04667A9220905D0911DFA13BFF380A1CE22F");
		final ClassTypeDefinition appendOutputCTD = (ClassTypeDefinition) append.getOutput();
		assertEquals(string, appendOutputCTD.getClazz());
		assertEquals("append", append.getName());
		final ImpactAnalyzer ia = ImpactAnalyzerFactory.INSTANCE.createImpactAnalyzer(exp, /* notifyOnNewContextElements */ false, OCLFactory.getInstance());
		final boolean[] result = new boolean[1];
		appendOutputCTD.eAdapters().add(new AdapterImpl() {
			@Override
			public void notifyChanged(Notification msg) {
				Collection<EObject> impact = ia.getContextObjects(msg);
				if (!impact.contains(callOnAppendCallResult)) {
					System.err.println("Expecting a method call on a string-typed expression to be impacted by adding a signature to String");
					result[0] = false;
				} else {
					if (OptimizationActivation.getOption().isTracebackStepISAActive()) {
						result[0] = impact.size() > 5 && impact.size() < 10;
						if (!result[0]) {
							System.err.println("Expected unused check to find between 5 and 10 changed but IA said "
									+ impact.size() + " objects were impacted");
						}
					} else {
						result[0] = impact.size() > 50;
						if (!result[0]) {
							System.err
							.println("Expected more than 50 method calls to be impacted without unused check but found only "
									+ impact.size());
						}
					}
				}
			}
		});
		appendOutputCTD.setClazz(null);
		assertFalse(oldValue instanceof DynamicEObjectImpl);
		assertNull("Expecting a method call on the result of String.append() with no ownedTypeDefinition on that call to me impacted "+
				"by setting String.append()'s output type definition's clazz to null",
				((ClassTypeDefinition) callOnAppendCallResult.getObject().getType().getInnermost()).getClazz());
		Object invalid = OCL.newInstance().evaluate(callOnAppendCallResult, exp);
		assertFalse(invalid.equals(oldValue));
		assertTrue(result[0]);
	}

	@Test
	public void testPrintNumberOfTracebackExecutions() {
		debugPrintln("Number of traceback evaluations: "+AbstractTracebackStep.tracebackExecutions);
		debugPrintln("Number of unused proven: "+AbstractTracebackStep.provenUnused);
	}

	private Notification getNotification(int id, Resource model){
		Resource clonedModel = ModelCloner.cloneResource(model, String.valueOf(Math.random()));

		for(int i = 0; i < (id - 1); i++) {
			changeModel(i, clonedModel);
		}
		return changeModel(id - 1, clonedModel);
	}

	private Notification changeModel(int id, Resource clonedModel) {
		RawNotification raw = modifyElementaryTypesTrace.get(id);

		debugPrintln(raw.getEventType());
		if(raw.isSplitCandidate()){
			debugPrintln("candidate");
			raw.split().get(0).convertToNotification(clonedModel);
			return raw.split().get(1).convertToNotification(clonedModel);
		} else
			return raw.convertToNotification(clonedModel);
	}

}
