package KomplexeMenge;

import static org.junit.Assert.*;

import java.util.Vector;

import org.junit.Test;

import de.dhbwstuttgart.typeinference.EinzelElement;
import de.dhbwstuttgart.typeinference.KomplexeMenge;
import de.dhbwstuttgart.typeinference.Menge;
import de.dhbwstuttgart.typeinference.OderMenge;
import de.dhbwstuttgart.typeinference.UndMenge;

class TestKlasse {
	static int identifier = 0;
	public String name;
	int id;

	TestKlasse(String name){
		this.name = name;
		id = 0;
	}
	
	public String toString(){
		return name+" #"+id;
	}
}

class TestKlasseOderMenge extends OderMenge<TestKlasse>{
	Menge<TestKlasseUndMenge> set = new Menge<>();
	
	@Override
	public Menge<? extends KomplexeMenge<TestKlasse>> getSet() {
		return set;
	}

	public void addItem(TestKlasse string) {
		TestUndMenge toAdd = new TestKlasseUndMenge();
		toAdd.addItem(string);
		set.add(toAdd);
	}
	public void addItems(TestKlasseUndMenge undMenge) {
		set.add(undMenge);
	}
}

class TestKlasseUndMenge extends UndMenge<TestKlasse>{
	Menge<KomplexeMenge<TestKlasse>> set = new Menge<>();
	
	@Override
	public Menge<? extends KomplexeMenge<TestKlasse>> getSet() {
		return set;
	}	
	public void addItem(TestKlasse string) {
		set.add(new EinzelElement<TestKlasse>(string));
	}
	
	public void addItems(KomplexeMenge<TestKlasse> oderMenge) {
		set.add(oderMenge);
	}
}

public class KeineDoppeltenVerweise {
	
	@Test
	public void test() {
		OderMenge<TestKlasse> oM1 = new TestOderMenge();
		OderMenge<TestKlasse> oM2 = new OderMenge<>();
		UndMenge<TestKlasse> oM3 = new UndMenge<>();
		oM1.addItem(new TestKlasse("Menge 1, Item 1"));
		oM1.addItem(new TestKlasse("Menge 1, Item 2"));
		oM2.addItem(new TestKlasse("Menge 2, Item 1"));
		oM2.addItem(new TestKlasse("Menge 2, Item 2"));
		oM3.addItems(oM1);
		oM3.addItems(oM2);
		Menge<Menge<TestKlasse>> cP = oM3.cartesianProduct();
		System.out.println(cP);
		cP.firstElement().firstElement().name="neu";
		System.out.println(cP);
		check(cP);
	}

	private <A> void check(Menge<Menge<A>> cP){
		Menge<A> allElements = new Menge<>();
		for(Vector<A> v : cP)for(A i : v){
			Object o = containsRef(allElements, i);
			if(o!=null){
				fail("Ein Verweis ist im Karthesischen Produkt doppelt vorhanden: "+o+" == "+i);
			}else{
				allElements.add(i);
			}
		}
	}
	
	private Object containsRef(Menge v, Object i){
		for(Object o : v){
			if(i == o)return o;
		}
		return null;
	}
}