package unify;

import java.util.HashSet;
import java.util.Set;

import junit.framework.Assert;

import org.junit.Test;

import de.dhbwstuttgart.typeinference.unify.interfaces.IUnify;
import de.dhbwstuttgart.typeinference.unify.model.MPair;
import de.dhbwstuttgart.typeinference.unify.model.Type;
import de.dhbwstuttgart.typeinference.unify.model.MPair.PairOperator;
import de.dhbwstuttgart.typeinference.unifynew.MartelliMontanariUnify;
import de.dhbwstuttgart.typeinference.unifynew.TypeFactory;

public class StandardUnifyTest {
	
	@Test
	public void testUnify() {
		IUnify unify = new MartelliMontanariUnify();
		TypeFactory tf = new TypeFactory();
		
		/*
		 * Positive Tests
		 */
		
		Type x = tf.getPlaceholderType("x");
		Type y = tf.getPlaceholderType("y");
		Type f = tf.getSimpleType("f", x);
		
		// {f<x> = y}
		Set<MPair> terms = new HashSet<MPair>();

		System.out.println(unify.unify(f, y).get());
		
		// TODO ist das ergebnis { (x -> ? extends a), (y -> g<x>) } in der richtigen form oder
		// muss es { (x -> ? extends a), (y -> g<? extends a>) } sein?
		// {f<g<x>,x> = f<y, ? extends a>}
		Type g = tf.getSimpleType("g", "x");
		Type f1 = tf.getSimpleType("f", g, x);
		Type a = tf.getExtendsType(tf.getPlaceholderType("a"));
		Type f2 = tf.getSimpleType("f", y, a);
		
		terms = new HashSet<>();

		System.out.println(unify.unify(f1, f2).get());
		
		/*
		 * Negative Tests
		 */
		
		// {f(x) =. x}
		f = tf.getSimpleType("f", x);
		Assert.assertFalse(unify.unify(f, x).isPresent());
		
		// {f(x) =. f(x,y)}
		f1 = tf.getSimpleType("f", "x");
		f2 = tf.getSimpleType("f", "x", "y");
		Assert.assertFalse(unify.unify(f1, f2).isPresent());
		
		// {f(x) =. g(x)}
		f1 = tf.getSimpleType("f", "x");
		f2 = tf.getSimpleType("g", "x");
		Assert.assertFalse(unify.unify(f1, f2).isPresent());
	}
}