package de.dhbwstuttgart.typeinference.constraints;

import de.dhbwstuttgart.syntaxtree.GenericTypeVar;
import de.dhbwstuttgart.syntaxtree.type.GenericRefType;
import de.dhbwstuttgart.syntaxtree.type.RefType;
import de.dhbwstuttgart.syntaxtree.type.RefTypeOrTPHOrWildcardOrGeneric;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.assumptions.TypeInferenceBlockInformation;
import de.dhbwstuttgart.typeinference.unify.model.PairOperator;

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

public class ConstraintsFactory {
    public static Pair createPair(RefTypeOrTPHOrWildcardOrGeneric t1, RefTypeOrTPHOrWildcardOrGeneric t2, PairOperator equalsdot, TypeInferenceBlockInformation info){
        //Check whether Generics are in the same class:
        return new Pair(checkGeneric(t1, info), checkGeneric(t2, info));
    }
    public static Pair createPair(RefTypeOrTPHOrWildcardOrGeneric t1,
                                  RefTypeOrTPHOrWildcardOrGeneric t2, TypeInferenceBlockInformation info){
        return createPair(t1,t2,PairOperator.SMALLERDOT, info);
    }

    private static RefTypeOrTPHOrWildcardOrGeneric checkGeneric(RefTypeOrTPHOrWildcardOrGeneric type, TypeInferenceBlockInformation info){
        if(type instanceof GenericRefType){
            List<GenericTypeVar> genericsInContext = new ArrayList<>();
            for(GenericTypeVar genericTypeVar : info.getCurrentClass().getGenerics()){
                genericsInContext.add(genericTypeVar);
            }
            if(info.getCurrentMethod() != null)for(GenericTypeVar genericTypeVar : info.getCurrentMethod().getGenerics()){
                genericsInContext.add(genericTypeVar);
            }

            for(GenericTypeVar genericTypeVar : genericsInContext){
                if(genericTypeVar.getName().equals(((GenericRefType)type).getName())){
                    return new RefType(((GenericRefType)type).getName(),type.getOffset());
                }
            }
            //Nicht in den Generics in diesem Kontext enthalten:
            return TypePlaceholder.fresh(type.getOffset());
        }else{
            return type;
        }
    }

}
