package de.dhbwstuttgart.typeinference.assumptions;

import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.syntaxtree.ClassOrInterface;
import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.TypeScope;
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.typeinference.constraints.GenericsResolver;

import java.util.ArrayList;
import java.util.List;

public class FieldAssumption extends Assumption{
    private ClassOrInterface receiverClass;
    private RefTypeOrTPHOrWildcardOrGeneric type;
    private String name;

    public FieldAssumption(String fieldName, ClassOrInterface receiverType,
                           RefTypeOrTPHOrWildcardOrGeneric type, TypeScope scope){
        super(scope);
        this.type = type;
        this.receiverClass = receiverType;
        this.name = fieldName;
    }

    public ClassOrInterface getReceiverClass() {
        return receiverClass;
    }

    public RefTypeOrTPHOrWildcardOrGeneric getType(GenericsResolver resolver) {
        return resolver.resolve(type);
    }

    public RefTypeOrTPHOrWildcardOrGeneric getReceiverType(GenericsResolver resolver) {
        List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
        for(GenericTypeVar gtv : receiverClass.getGenerics()){
            //Hier wird ein GenericRefType gebildet, welcher einen für dieses Feld eindeutigen Namen hat
            GenericRefType genericRefType =
                    new GenericRefType(gtv.getName()
                            , new NullToken());
            //Dieser wird dann korrekt aufgelöst vom Resolver:
            params.add(resolver.resolve(genericRefType));
        }
        return new RefType(receiverClass.getClassName(), params, new NullToken());
    }
}
