package tests.terms.meta;

import static org.junit.jupiter.api.Assertions.*;
import static tests.Utils.*;

import org.junit.jupiter.api.Test;

import models.algebra.Constant;
import models.algebra.Variable;
import models.terms.Dependency;
import models.terms.DependencyTerm;
import models.terms.ResourceVariable;
import models.terms.meta.MetaDependencyTermVariable;
import models.terms.meta.MetaRDLTerm;
import models.terms.meta.MetaResourceVariable;

public class MetaRDLTermTest {

	@Test
	void MetaDependencyMatchingWithoutOrderTest() {
		ResourceVariable a = new ResourceVariable("a", INT, 1);
		ResourceVariable b = new ResourceVariable("b", INT, 1);
		ResourceVariable c = new ResourceVariable("c", INT, 1);
		Dependency dep1 = new Dependency(a, b);
		DependencyTerm te1 = new DependencyTerm(a, b, c);
		Dependency dep2 = new Dependency(te1, b);
		
		MetaResourceVariable v1 = new MetaResourceVariable(new Variable("v1"));
		MetaResourceVariable v2 = new MetaResourceVariable(new Variable("v2"));
		MetaResourceVariable v3 = new MetaResourceVariable(new Variable("v3"));
		MetaDependencyTermVariable vte = new MetaDependencyTermVariable(new Variable("vte"));
		MetaRDLTerm metaDep = new MetaRDLTerm(v1, v2);
		MetaRDLTerm metaDep2 = new MetaRDLTerm(vte, v2);
		MetaRDLTerm metaTe = new MetaRDLTerm(v1, v2, v3);
		MetaRDLTerm metaDep3 = new MetaRDLTerm(metaTe, v2);
		MetaRDLTerm metaDep4 = new MetaRDLTerm(metaTe, v3);
		
		//[a : b] matches [v1 : v2]
		assertTrue(metaDep.isMatchedBy(dep1));
		//[[a : b -> c] : b] does not match [v1 : v2]
		assertFalse(metaDep.isMatchedBy(dep2));
		//[[a : b -> c] : b] matches [vte : v2]
		assertTrue(metaDep2.isMatchedBy(dep2));
		//[[a : b -> c] : b] matches [[v1 : v2 -> v3] : v2]
		assertTrue(metaDep3.isMatchedBy(dep2));
		//[[a : b -> c] : b] does not match [[v1 : v2 -> v3] : v3]
		assertFalse(metaDep4.isMatchedBy(dep2));
	}
	
	@Test
	void MetaDependencyMatchingWithConstantOrderTest() {
		MetaResourceVariable v1 = new MetaResourceVariable(new Variable("v1"), new Constant("1"));
		MetaResourceVariable v2 = new MetaResourceVariable(new Variable("v2"), new Constant("2"));
		MetaRDLTerm vd1 = new MetaRDLTerm(v1, v2);
		
		ResourceVariable a1 = new ResourceVariable("a1", INT, 1);
		ResourceVariable a2 = new ResourceVariable("a2", INT, 2);
		Dependency d1 = new Dependency(a1, a2);
		//[1 : 2] matches [1 : 2]
		assertTrue(vd1.isMatchedBy(d1));
		
		ResourceVariable b1 = new ResourceVariable("b1", INT, 1);
		Dependency d2 = new Dependency(a1, b1);
		//[1 : 1] does not match [1 : 2]
		assertFalse(vd1.isMatchedBy(d2));
	}
	
	@Test
	void MetaDependencyMatchingWithVariableOrderTest() {
		MetaResourceVariable v1 = new MetaResourceVariable(new Variable("v1"), parse("x"));
		MetaResourceVariable v2 = new MetaResourceVariable(new Variable("v2"), parse("x"));
		MetaResourceVariable v3 = new MetaResourceVariable(new Variable("v3"), parse("y"));
		MetaRDLTerm vd1 = new MetaRDLTerm(v1, v2);
		MetaRDLTerm vd2 = new MetaRDLTerm(v1, v3);
		MetaRDLTerm vd3 = new MetaRDLTerm(new MetaRDLTerm(v3, v1), v2);
		
		ResourceVariable a1 = new ResourceVariable("a1", INT, 1);
		ResourceVariable a2 = new ResourceVariable("a2", INT, 2);
		ResourceVariable b1 = new ResourceVariable("b1", INT, 1);
		ResourceVariable b2 = new ResourceVariable("b2", INT, 2);
		Dependency d1 = new Dependency(a1, a2);
		Dependency d2 = new Dependency(a1, b1);
		Dependency d3 = new Dependency(new Dependency(a1, b1), a2);
		Dependency d4 = new Dependency(new Dependency(a1, a2), b2);
		//[1 : 2] does not match [x : x]
		assertFalse(vd1.isMatchedBy(d1));
		//[1 : 1] matches [x : x]
		assertTrue(vd1.isMatchedBy(d2));
		//[1 : 2] matches [x : y]
		assertTrue(vd2.isMatchedBy(d1));
		//[1 : 1] matches [x : y]
		assertTrue(vd2.isMatchedBy(d2));
		//[[1 : 1] : 2] does not match [[y : x] : x]
		assertFalse(vd3.isMatchedBy(d3));
		//[[1 : 2] : 2] matches [[y : x] : x]
		assertTrue(vd3.isMatchedBy(d4));
	}
	
}
