package be.kuleuven.cs.distrinet.jnome.core.type;

import java.util.List;

import org.aikodi.chameleon.core.element.Element;
import org.aikodi.chameleon.core.lookup.LookupException;
import org.aikodi.chameleon.core.validation.Valid;
import org.aikodi.chameleon.core.validation.Verification;
import org.aikodi.chameleon.oo.language.ObjectOrientedLanguage;
import org.aikodi.chameleon.oo.type.Type;
import org.aikodi.chameleon.oo.type.generics.TypeArgument;
import org.aikodi.chameleon.oo.type.generics.CapturedTypeParameter;
import org.aikodi.chameleon.oo.type.generics.FormalTypeParameter;
import org.aikodi.chameleon.oo.type.generics.TypeConstraint;
import org.aikodi.chameleon.oo.type.generics.TypeParameter;
import org.aikodi.chameleon.workspace.View;

public class PureWildcard extends TypeArgument {

	public PureWildcard() {
		
	}
	
	public TypeParameter capture(FormalTypeParameter formal, List<TypeConstraint> accumulator) {
		CapturedTypeParameter newParameter = new CapturedTypeParameter(formal.name());
		for(TypeConstraint constraint: formal.constraints()) {
			TypeConstraint clone = cloneAndResetTypeReference(constraint,constraint);
			newParameter.addConstraint(clone);
			accumulator.add(clone);
		}
   return newParameter;
	}

	@Override
	protected PureWildcard cloneSelf() {
		return new PureWildcard();
	}

	// TypeVariable concept invoeren, en lowerbound,... verplaatsen naar daar? Deze is context sensitive. Hoewel, dat
	// wordt toch nooit direct vergeleken. Er moet volgens mij altijd eerst gecaptured worden, dus dan moet dit inderdaad
	// verplaatst worden. NOPE, niet altijd eerst capturen.
	@Override
	public Type lowerBound() throws LookupException {
		View view = view();
		ObjectOrientedLanguage l = view.language(ObjectOrientedLanguage.class);
		return l.getNullType(view.namespace());
	}

	@Override
	public Type type() throws LookupException {
		PureWildCardType pureWildCardType = new PureWildCardType(parameterBound());
		pureWildCardType.setUniParent(this);
		return pureWildCardType;
	}
	
	public Type parameterBound() throws LookupException {
		BasicJavaTypeReference nearestAncestor = nearestAncestor(BasicJavaTypeReference.class);
		List<TypeArgument> args = nearestAncestor.typeArguments();
		int index = args.indexOf(this);
		Type base = nearestAncestor.typeConstructor();
		TypeParameter parameter = base.parameter(TypeParameter.class,index);
		Type result = parameter.upperBound();
		return result;
	}

	@Override
	public boolean uniSameAs(Element other) throws LookupException {
		return other instanceof PureWildcard;
	}
	
	@Override
	public Type upperBound() throws LookupException {
		//return language(ObjectOrientedLanguage.class).getDefaultSuperClass();
		return parameterBound();
	}

	@Override
	public Verification verifySelf() {
		return Valid.create();
	}

	public String toString(java.util.Set<Element> visited) {
		return "?";
	}
	
	@Override
	public boolean isWildCardBound() {
		return true;
	}

}

@@ -430,29 +430,21 @@
 ype.
-generics.TypeArgument
+TypeReference
 ;%0Aim
@@ -501,32 +501,96 @@
 dTypeParameter;%0A
+import org.aikodi.chameleon.oo.type.generics.ExtendsConstraint;%0A
 import org.aikod
@@ -631,32 +631,91 @@
 lTypeParameter;%0A
+import org.aikodi.chameleon.oo.type.generics.TypeArgument;%0A
 import org.aikod
@@ -864,16 +864,76 @@
 .View;%0A%0A
+import be.kuleuven.cs.distrinet.jnome.core.language.Java7;%0A%0A
 public c
@@ -1003,16 +1003,13 @@
 ) %7B%0A
-%09%09
 %0A
+
 %09%7D%0A
-%09
 %0A
+
 %09pub
@@ -1386,11 +1386,447 @@
 %09%09%7D%0A
-   
+%09%09%0A%09%09//FIXME This should actually be determined by the type parameter itself.%0A%09%09//      perhaps it should compute its own upper bound reference.%0A%09%09Java7 java = language(Java7.class);%0A%09%09BasicJavaTypeReference objectRef = java.createTypeReference(java.getDefaultSuperClassFQN());%0A%09%09TypeReference tref = java.createNonLocalTypeReference(objectRef,namespace().defaultNamespace());%0A%09%09newParameter.addConstraint(new ExtendsConstraint(tref));%0A%0A%09%09
 retu
@@ -2626,18 +2626,17 @@
 ype;%0A%09%7D%0A
-%09
 %0A
+
 %09public 
@@ -3164,26 +3164,25 @@
 ildcard;%0A%09%7D%0A
-%09
 %0A
+
 %09@Override%0A%09
@@ -3487,17 +3487,16 @@
 %22?%22;%0A%09%7D%0A
-%09
 %0A%09@Overr

add Object as the default upper bound