package de.dhbwstuttgart.target.generate;

import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.statement.*;

// This visitor walks the entire tree, individual methods may be overridden
public abstract class TracingStatementVisitor implements StatementVisitor {

    @Override
    public void visit(ThisCall thisCall) {
        visit((MethodCall) thisCall);
    }

    @Override
    public void visit(MethodCall methodCall) {
        methodCall.receiver.accept(this);
        methodCall.getArgumentList().accept(this);
    }

    @Override
    public void visit(ArgumentList argumentList) {
        argumentList.getArguments().forEach(expr -> expr.accept(this));
    }

    @Override
    public void visit(LambdaExpression lambdaExpression) {
        lambdaExpression.methodBody.accept(this);
    }

    @Override
    public void visit(Assign assign) {
        assign.rightSide.accept(this);
    }

    @Override
    public void visit(BinaryExpr binary) {
        binary.lexpr.accept(this);
        binary.rexpr.accept(this);
    }

    @Override
    public void visit(BoolExpression bool) {
        bool.lexpr.accept(this);
        bool.rexpr.accept(this);
    }

    @Override
    public void visit(Block block) {
        for (var expr : block.statements)
            expr.accept(this);
    }

    @Override
    public void visit(CastExpr castExpr) {

    }

    @Override
    public void visit(EmptyStmt emptyStmt) {

    }

    @Override
    public void visit(FieldVar fieldVar) {

    }

    @Override
    public void visit(ForStmt forStmt) {
        forStmt.block.accept(this);
    }

    @Override
    public void visit(ForEachStmt forEachStmt) {
        forEachStmt.block.accept(this);
    }

    @Override
    public void visit(IfStmt ifStmt) {
        ifStmt.then_block.accept(this);
        if (ifStmt.else_block != null)
            ifStmt.else_block.accept(this);
    }

    @Override
    public void visit(InstanceOf instanceOf) {

    }

    @Override
    public void visit(LocalVar localVar) {

    }

    @Override
    public void visit(LocalVarDecl localVarDecl) {

    }

    @Override
    public void visit(NewClass newClass) {
        this.visit((MethodCall) newClass);
    }

    @Override
    public void visit(NewArray newArray) {
        newArray.expr.forEach(expr -> expr.accept(this));
    }

    @Override
    public void visit(Return aReturn) {
        aReturn.retexpr.accept(this);
    }

    @Override
    public void visit(ReturnVoid aReturn) {

    }

    @Override
    public void visit(Break aBreak) {

    }

    @Override
    public void visit(Continue aContinue) {

    }

    @Override
    public void visit(StaticClassName staticClassName) {

    }

    @Override
    public void visit(Super aSuper) {

    }

    @Override
    public void visit(This aThis) {

    }

    @Override
    public void visit(WhileStmt whileStmt) {
        whileStmt.loopBlock.accept(this);
    }

    @Override
    public void visit(DoStmt whileStmt) {
        whileStmt.loopBlock.accept(this);
    }

    @Override
    public void visit(AssignToField assignLeftSide) {

    }

    @Override
    public void visit(AssignToLocal assignLeftSide) {

    }

    @Override
    public void visit(SuperCall superCall) {
        visit((MethodCall) superCall);
    }

    @Override
    public void visit(ExpressionReceiver expressionReceiver) {
        expressionReceiver.expr.accept(this);
    }

    @Override
    public void visit(UnaryExpr unaryExpr) {
        unaryExpr.expr.accept(this);
    }

    @Override
    public void visit(Literal literal) {

    }

    @Override
    public void visit(Throw aThrow) {

    }

    @Override
    public void visit(Switch switchStmt) {

    }

    @Override
    public void visit(SwitchBlock switchBlock) {

    }

    @Override
    public void visit(SwitchLabel switchLabel) {

    }

    @Override
    public void visit(Yield aYield) {

    }

    @Override
    public void visit(Ternary ternary) {
        ternary.cond.accept(this);
        ternary.iftrue.accept(this);
        ternary.iffalse.accept(this);
    }
}
