package terms.meta;

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

import org.junit.jupiter.api.Test;

import java.util.HashMap;
import java.util.Map;

import models.algebra.Variable;
import models.terms.DependencyTerm;
import models.terms.RDLTerm;
import models.terms.Resource;
import models.terms.meta.MetaRDLTerm;
import models.terms.meta.MetaResource;
import models.terms.meta.OrderVariableConstraint;
import utils.Utils;

public class DependencyTermTest {

	Resource a = new Resource("a", Utils.INT, 1);
	Resource b = new Resource("b", Utils.INT, 1);
	Resource c = new Resource("c", Utils.INT, 1);
	Resource d = new Resource("d", Utils.INT, 1);
	Resource e = new Resource("e", Utils.INT, 1);
	
	@Test
	void EqualsTest() {
		DependencyTerm t1 = new DependencyTerm(a, b, c);
		DependencyTerm t2 = new DependencyTerm(a, b, c);
		assertEquals(t1, t2);
		
		DependencyTerm t3 = new DependencyTerm(a, b, c, b, c);
		assertEquals(t1, t3);
		
		DependencyTerm t4 = new DependencyTerm(a, c, b);
		assertFalse(t1.equals(t4));
		
		DependencyTerm t5 = new DependencyTerm(a, b, c, d, e);
		DependencyTerm t6 = new DependencyTerm(a, d, e, b, c);
		DependencyTerm t7 = new DependencyTerm(a, b, e, d, c);
		assertEquals(t5, t6);
		assertFalse(t5.equals(t7));
		
		DependencyTerm t8 = new DependencyTerm(t1, t5, t6);
		DependencyTerm t9 = new DependencyTerm(t1, t6, t5);
		assertEquals(t8, t9);
		
	}
	
	@Test
	void MatchTest() {
		DependencyTerm t1 = new DependencyTerm(a, b, c, d, e);
		MetaResource x = new MetaResource(new Variable("x"));
		MetaResource y = new MetaResource(new Variable("y"));
		MetaResource z = new MetaResource(new Variable("z"));
		MetaResource w = new MetaResource(new Variable("w"));
		MetaResource p = new MetaResource(new Variable("p"));
		MetaRDLTerm mt1 = new MetaRDLTerm(x, y, z, w, p);
		MetaRDLTerm mt2 = new MetaRDLTerm(x, w, p, y, z);
		MetaRDLTerm mt3 = new MetaRDLTerm(x, p, w, y, z);
		Map<Variable, RDLTerm> binding = new HashMap<>();
		Map<Variable, OrderVariableConstraint> orderConstraint = new HashMap<>();
		assertTrue(mt1.isMatchedBy(t1, binding, orderConstraint));
		assertTrue(mt2.isMatchedBy(t1, binding, orderConstraint));
		assertFalse(mt3.isMatchedBy(t1, binding, orderConstraint));
		RDLTerm t = mt1.substitute(binding);
		assertEquals(t, t1);
	}
}
