package de.dhbwstuttgart.typedeployment;

import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.statement.JavaInternalExpression;
import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression;
import de.dhbwstuttgart.syntaxtree.type.TypePlaceholder;
import de.dhbwstuttgart.typeinference.result.ResultSet;

import java.util.HashSet;
import java.util.Set;

public class TypeInsertPlacer extends AbstractASTWalker{
    Set<TypeInsert> inserts = new HashSet<>();
    private ResultSet withResults;

    public Set<TypeInsert> getTypeInserts(SourceFile forSourceFile, ResultSet withResults){
        this.withResults = withResults;
        forSourceFile.accept(this);
        return inserts;
    }

    @Override
    public void visit(ClassOrInterface classOrInterface) {
        TypeInsertPlacerClass cl = new TypeInsertPlacerClass(classOrInterface, withResults);
        this.inserts.addAll(cl.inserts);
    }
}

class TypeInsertPlacerClass extends AbstractASTWalker{
    protected final ResultSet results;
    protected final ClassOrInterface cl;
    public final Set<TypeInsert> inserts = new HashSet<>();
    private Method method;

    TypeInsertPlacerClass(ClassOrInterface forClass, ResultSet withResults){
        this.cl = forClass;
        this.method = null;
        this.results = withResults;
        forClass.accept(this);
    }

    @Override
    public void visit(Method method) {
        this.method = method;
        if(method.getReturnType() instanceof TypePlaceholder)
            inserts.add(TypeInsertFactory.createInsertPoints(
                    method.getReturnType(), method.getReturnType().getOffset(), cl, method, results));
        super.visit(method);
    }

    @Override
    public void visit(Field field) {
        if(field.getType() instanceof TypePlaceholder){
                inserts.add(TypeInsertFactory.createInsertPoints(
                        field.getType(), field.getType().getOffset(), cl, method, results));
        }
        super.visit(field);
    }

    @Override
    public void visit(FormalParameter param) {
            if(param.getType() instanceof TypePlaceholder)
                inserts.add(TypeInsertFactory.createInsertPoints(
                        param.getType(), param.getType().getOffset(), cl, method, results));
        super.visit(param);
    }

    @Override
    public void visit(LambdaExpression lambdaExpression) {
        //Lambda-Ausdrücke brauchen keine Typeinsetzungen
    }
}
