package es.uniovi.reflection.patternmining.debug;

import com.sun.source.tree.AnnotatedTypeTree;
import com.sun.source.tree.AnnotationTree;
import com.sun.source.tree.ArrayAccessTree;
import com.sun.source.tree.ArrayTypeTree;
import com.sun.source.tree.AssertTree;
import com.sun.source.tree.AssignmentTree;
import com.sun.source.tree.BinaryTree;
import com.sun.source.tree.BlockTree;
import com.sun.source.tree.BreakTree;
import com.sun.source.tree.CaseTree;
import com.sun.source.tree.CatchTree;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.CompilationUnitTree;
import com.sun.source.tree.CompoundAssignmentTree;
import com.sun.source.tree.ConditionalExpressionTree;
import com.sun.source.tree.ContinueTree;
import com.sun.source.tree.DoWhileLoopTree;
import com.sun.source.tree.EmptyStatementTree;
import com.sun.source.tree.EnhancedForLoopTree;
import com.sun.source.tree.ErroneousTree;
import com.sun.source.tree.ExpressionStatementTree;
import com.sun.source.tree.ForLoopTree;
import com.sun.source.tree.IdentifierTree;
import com.sun.source.tree.IfTree;
import com.sun.source.tree.ImportTree;
import com.sun.source.tree.InstanceOfTree;
import com.sun.source.tree.IntersectionTypeTree;
import com.sun.source.tree.LabeledStatementTree;
import com.sun.source.tree.LambdaExpressionTree;
import com.sun.source.tree.LiteralTree;
import com.sun.source.tree.MemberReferenceTree;
import com.sun.source.tree.MemberSelectTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.ModifiersTree;
import com.sun.source.tree.NewArrayTree;
import com.sun.source.tree.NewClassTree;
import com.sun.source.tree.ParameterizedTypeTree;
import com.sun.source.tree.ParenthesizedTree;
import com.sun.source.tree.PrimitiveTypeTree;
import com.sun.source.tree.ReturnTree;
import com.sun.source.tree.SwitchTree;
import com.sun.source.tree.SynchronizedTree;
import com.sun.source.tree.ThrowTree;
import com.sun.source.tree.Tree;
import com.sun.source.tree.TryTree;
import com.sun.source.tree.TypeCastTree;
import com.sun.source.tree.TypeParameterTree;
import com.sun.source.tree.UnaryTree;
import com.sun.source.tree.UnionTypeTree;
import com.sun.source.tree.VariableTree;
import com.sun.source.tree.WhileLoopTree;
import com.sun.source.tree.WildcardTree;
import com.sun.source.util.TreeScanner;

public class DebugPrinter extends TreeScanner<Object, Object> {
    private void PrintIndentation(int length)
    {
        for (int i = 0; i < length * 2; i++)
        {
            System.out.print(" ");
        }
        System.out.print("|_ ");
    }

    @Override
    public Object visitCompilationUnit(CompilationUnitTree compilationUnitTree, Object o) {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("CompilationUnitTree");
        return super.visitCompilationUnit(compilationUnitTree, indent + 1);
    }

    @Override
    public Object visitImport(ImportTree importTree, Object o) {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("ImportTree");
        return super.visitImport(importTree, indent + 1);
    }

    @Override
    public Object visitClass(ClassTree classTree, Object o) {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("ClassTree");
        return super.visitClass(classTree, indent + 1);
    }

    @Override
    public Object visitMethod(MethodTree methodTree, Object o) {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("MethodTree");
        super.visitMethod(methodTree, indent + 1);
        return 0;
    }

    @Override
    public Object visitVariable(VariableTree variableTree, Object o) {

        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("VariableTree");
        return super.visitVariable(variableTree, indent + 1);
    }

    @Override
    public Object visitEmptyStatement(EmptyStatementTree emptyStatementTree, Object o) {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("EmptyStatementTree");
        return super.visitEmptyStatement(emptyStatementTree, indent + 1);
    }

    @Override
    public Object visitBlock(BlockTree blockTree, Object o) {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("BlockTree");
        return super.visitBlock(blockTree, indent + 1);
    }

    @Override
    public Object visitDoWhileLoop(DoWhileLoopTree doWhileLoopTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("DoWhileLoopTree");
        return super.visitDoWhileLoop(doWhileLoopTree, indent + 1);
    }

    @Override
    public Object visitWhileLoop(WhileLoopTree whileLoopTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("WhileLoopTree");
        return super.visitWhileLoop(whileLoopTree, indent + 1);
    }

    @Override
    public Object visitForLoop(ForLoopTree forLoopTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("forLoopTree");
        return super.visitForLoop(forLoopTree, indent + 1);
    }

    @Override
    public Object visitEnhancedForLoop(EnhancedForLoopTree enhancedForLoopTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("EnhancedForLoopTree");
        return super.visitEnhancedForLoop(enhancedForLoopTree, indent + 1);
    }

    @Override
    public Object visitLabeledStatement(LabeledStatementTree labeledStatementTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("LabeledStatementTree");
        return super.visitLabeledStatement(labeledStatementTree, indent + 1);
    }

    @Override
    public Object visitSwitch(SwitchTree switchTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("SwitchTree");
        return super.visitSwitch(switchTree, indent + 1);
    }

    @Override
    public Object visitCase(CaseTree caseTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("CaseTree");
        return super.visitCase(caseTree, indent + 1);
    }

    @Override
    public Object visitSynchronized(SynchronizedTree synchronizedTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("SynchronizedTree");
        return super.visitSynchronized(synchronizedTree, indent + 1);
    }

    @Override
    public Object visitTry(TryTree tryTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("TryTree");
        return super.visitTry(tryTree, indent + 1);
    }

    @Override
    public Object visitCatch(CatchTree catchTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("CatchTree");
        return super.visitCatch(catchTree, indent + 1);
    }

    @Override
    public Object visitConditionalExpression(ConditionalExpressionTree conditionalExpressionTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("CatchTree");
        return super.visitConditionalExpression(conditionalExpressionTree, indent + 1);
    }

    @Override
    public Object visitIf(IfTree ifTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("IfTree");
        return super.visitIf(ifTree, indent + 1);
    }

    @Override
    public Object visitExpressionStatement(ExpressionStatementTree expressionStatementTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("ExpressionStatementTree");
        return super.visitExpressionStatement(expressionStatementTree, indent + 1);
    }

    @Override
    public Object visitBreak(BreakTree breakTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("BreakTree");
        return super.visitBreak(breakTree, indent + 1);
    }

    @Override
    public Object visitContinue(ContinueTree continueTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("ContinueTree");
        return super.visitContinue(continueTree, indent + 1);
    }

    @Override
    public Object visitReturn(ReturnTree returnTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("ReturnTree");
        return super.visitReturn(returnTree, indent + 1);
    }

    @Override
    public Object visitThrow(ThrowTree throwTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("ThrowTree");
        return super.visitThrow(throwTree, indent + 1);
    }

    @Override
    public Object visitAssert(AssertTree assertTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("AssertTree");
        return super.visitAssert(assertTree, indent + 1);
    }

    @Override
    public Object visitMethodInvocation(MethodInvocationTree methodInvocationTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("MethodInvocationTree");
        return super.visitMethodInvocation(methodInvocationTree, indent + 1);
    }

    @Override
    public Object visitNewClass(NewClassTree newClassTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("NewClassTree");
        return super.visitNewClass(newClassTree, indent + 1);
    }

    @Override
    public Object visitNewArray(NewArrayTree newArrayTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("NewArrayTree");
        return super.visitNewArray(newArrayTree, indent + 1);
    }

    @Override
    public Object visitLambdaExpression(LambdaExpressionTree lambdaExpressionTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("LambdaExpressionTree");
        return super.visitLambdaExpression(lambdaExpressionTree, indent + 1);
    }

    @Override
    public Object visitParenthesized(ParenthesizedTree parenthesizedTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("ParenthesizedTree");
        return super.visitParenthesized(parenthesizedTree, indent + 1);
    }

    @Override
    public Object visitAssignment(AssignmentTree assignmentTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("AssignmentTree");
        return super.visitAssignment(assignmentTree, indent + 1);
    }

    @Override
    public Object visitCompoundAssignment(CompoundAssignmentTree compoundAssignmentTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("CompoundAssignmentTree");
        return super.visitCompoundAssignment(compoundAssignmentTree, indent + 1);
    }

    @Override
    public Object visitUnary(UnaryTree unaryTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("UnaryTree");
        return super.visitUnary(unaryTree, indent + 1);
    }

    @Override
    public Object visitBinary(BinaryTree binaryTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("BinaryTree");
        return super.visitBinary(binaryTree, indent + 1);
    }

    @Override
    public Object visitTypeCast(TypeCastTree typeCastTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("TypeCastTree");
        return super.visitTypeCast(typeCastTree, indent + 1);
    }

    @Override
    public Object visitInstanceOf(InstanceOfTree instanceOfTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("InstanceOfTree");
        return super.visitInstanceOf(instanceOfTree, indent + 1);
    }

    @Override
    public Object visitArrayAccess(ArrayAccessTree arrayAccessTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("ArrayAccessTree");
        return super.visitArrayAccess(arrayAccessTree, indent + 1);
    }

    @Override
    public Object visitMemberSelect(MemberSelectTree memberSelectTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("MemberSelectTree");
        return super.visitMemberSelect(memberSelectTree, indent + 1);
    }

    @Override
    public Object visitMemberReference(MemberReferenceTree memberReferenceTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("MemberReferenceTree");
        return super.visitMemberReference(memberReferenceTree, indent + 1);
    }

    @Override
    public Object visitIdentifier(IdentifierTree identifierTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("IdentifierTree");
        return super.visitIdentifier(identifierTree, indent + 1);
    }

    @Override
    public Object visitLiteral(LiteralTree literalTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("LiteralTree");
        return super.visitLiteral(literalTree, indent + 1);
    }

    @Override
    public Object visitPrimitiveType(PrimitiveTypeTree primitiveTypeTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("PrimitiveTypeTree");
        return super.visitPrimitiveType(primitiveTypeTree, indent + 1);
    }

    @Override
    public Object visitArrayType(ArrayTypeTree arrayTypeTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("ArrayTypeTree");
        return super.visitArrayType(arrayTypeTree, indent + 1);
    }

    @Override
    public Object visitParameterizedType(ParameterizedTypeTree parameterizedTypeTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("ParameterizedTypeTree!");
        return super.visitParameterizedType(parameterizedTypeTree, indent + 1);
    }

    @Override
    public Object visitUnionType(UnionTypeTree unionTypeTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("UnionTypeTree");
        return super.visitUnionType(unionTypeTree, indent + 1);
    }

    @Override
    public Object visitIntersectionType(IntersectionTypeTree intersectionTypeTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("IntersectionTypeTree");
        return super.visitIntersectionType(intersectionTypeTree, indent + 1);
    }

    @Override
    public Object visitTypeParameter(TypeParameterTree typeParameterTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("TypeParameterTree");
        return super.visitTypeParameter(typeParameterTree, indent + 1);
    }

    @Override
    public Object visitWildcard(WildcardTree wildcardTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("WildcardTree");
        return super.visitWildcard(wildcardTree, indent + 1);
    }

    @Override
    public Object visitModifiers(ModifiersTree modifiersTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("ModifiersTree");
        return super.visitModifiers(modifiersTree, indent + 1);
    }

    @Override
    public Object visitAnnotation(AnnotationTree annotationTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("AnnotationTree");
        return super.visitAnnotation(annotationTree, indent + 1);
    }

    @Override
    public Object visitAnnotatedType(AnnotatedTypeTree annotatedTypeTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("AnnotatedTypeTree");
        return super.visitAnnotatedType(annotatedTypeTree, indent + 1);
    }

    @Override
    public Object visitErroneous(ErroneousTree erroneousTree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("ErroneousTree");
        return super.visitErroneous(erroneousTree, indent + 1);
    }

    @Override
    public Object visitOther(Tree tree, Object o)  {
        int indent = (Integer) o;
        this.PrintIndentation(indent);
        System.out.println("Tree");
        return super.visitOther(tree, indent + 1);
    }
}
