package de.dhbwstuttgart.typeinference.typeAlgo;

import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.type.*;
import de.dhbwstuttgart.typeinference.constraints.GenericsResolver;

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

/**
 * Ein GenericsResolver, welcher Generics mit dem selben Namen den selben TPH zuordnet
 */
public class GenericsResolverSameName implements GenericsResolver, TypeVisitor<RefTypeOrTPHOrWildcardOrGeneric>{

    HashMap<String, TypePlaceholder> map = new HashMap<>();

    @Override
    public RefTypeOrTPHOrWildcardOrGeneric resolve(RefTypeOrTPHOrWildcardOrGeneric generic) {
            return generic.acceptTV(this);
    }

    @Override
    public RefTypeOrTPHOrWildcardOrGeneric visit(RefType refType) {
        List<RefTypeOrTPHOrWildcardOrGeneric> params = new ArrayList<>();
        for(RefTypeOrTPHOrWildcardOrGeneric param : refType.getParaList()){
            params.add(param.acceptTV(this));
        }
        RefType ret = new RefType(refType.getName(), params, refType.getOffset());
        return ret;
    }

    @Override
    public RefTypeOrTPHOrWildcardOrGeneric visit(SuperWildcardType superWildcardType) {
        return new SuperWildcardType(superWildcardType.getInnerType().acceptTV(this), superWildcardType.getOffset());
    }

    @Override
    public RefTypeOrTPHOrWildcardOrGeneric visit(TypePlaceholder typePlaceholder) {
        return typePlaceholder;
    }

    @Override
    public RefTypeOrTPHOrWildcardOrGeneric visit(ExtendsWildcardType extendsWildcardType) {
        return new ExtendsWildcardType(extendsWildcardType.getInnerType().acceptTV(this), extendsWildcardType.getOffset());
    }

    @Override
    public RefTypeOrTPHOrWildcardOrGeneric visit(GenericRefType genericRefType) {
        String name = genericRefType.getParsedName();
        if(!map.containsKey(name)){
            map.put(name, TypePlaceholder.fresh(genericRefType.getOffset()));
        }
        return map.get(name);
    }
}
