package de.dhbwstuttgart.bytecode;

import java.util.List;

import de.dhbwstuttgart.parser.SyntaxTreeGenerator.AssignToLocal;
import de.dhbwstuttgart.syntaxtree.StatementVisitor;
import de.dhbwstuttgart.syntaxtree.statement.ArgumentList;
import de.dhbwstuttgart.syntaxtree.statement.Assign;
import de.dhbwstuttgart.syntaxtree.statement.AssignToField;
import de.dhbwstuttgart.syntaxtree.statement.BinaryExpr;
import de.dhbwstuttgart.syntaxtree.statement.Block;
import de.dhbwstuttgart.syntaxtree.statement.CastExpr;
import de.dhbwstuttgart.syntaxtree.statement.DoStmt;
import de.dhbwstuttgart.syntaxtree.statement.EmptyStmt;
import de.dhbwstuttgart.syntaxtree.statement.ExpressionReceiver;
import de.dhbwstuttgart.syntaxtree.statement.FieldVar;
import de.dhbwstuttgart.syntaxtree.statement.ForStmt;
import de.dhbwstuttgart.syntaxtree.statement.IfStmt;
import de.dhbwstuttgart.syntaxtree.statement.InstanceOf;
import de.dhbwstuttgart.syntaxtree.statement.LambdaExpression;
import de.dhbwstuttgart.syntaxtree.statement.Literal;
import de.dhbwstuttgart.syntaxtree.statement.LocalVar;
import de.dhbwstuttgart.syntaxtree.statement.LocalVarDecl;
import de.dhbwstuttgart.syntaxtree.statement.MethodCall;
import de.dhbwstuttgart.syntaxtree.statement.NewArray;
import de.dhbwstuttgart.syntaxtree.statement.NewClass;
import de.dhbwstuttgart.syntaxtree.statement.Return;
import de.dhbwstuttgart.syntaxtree.statement.ReturnVoid;
import de.dhbwstuttgart.syntaxtree.statement.StaticClassName;
import de.dhbwstuttgart.syntaxtree.statement.Super;
import de.dhbwstuttgart.syntaxtree.statement.SuperCall;
import de.dhbwstuttgart.syntaxtree.statement.This;
import de.dhbwstuttgart.syntaxtree.statement.UnaryExpr;
import de.dhbwstuttgart.syntaxtree.statement.WhileStmt;

public class ArgumentVisitor implements StatementVisitor {
	private List<Boolean> argListMethCall;
	private BytecodeGenMethod bytecodeGenMethod;
	
	public ArgumentVisitor(List<Boolean> argListMethCall, BytecodeGenMethod bytecodeGenMethod) {
		this.argListMethCall = argListMethCall;
		this.bytecodeGenMethod = bytecodeGenMethod;
	}

	@Override
	public void visit(ArgumentList argumentList) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(LambdaExpression lambdaExpression) {
		lambdaExpression.accept(bytecodeGenMethod);
		// Zieltype des Lambas ist Funktionale Interface
		// kann nie primitiv sein => un-/boxing wird hier nicht gebraucht
		argListMethCall.remove(0);
	}

	@Override
	public void visit(Assign assign) {
		assign.accept(bytecodeGenMethod);
		
		if(argListMethCall.get(0))
			bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(assign.getType()));
		argListMethCall.remove(0);
	}

	@Override
	public void visit(BinaryExpr binary) {
		binary.accept(bytecodeGenMethod);
		
		if(argListMethCall.get(0)) {
			bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(binary.getType()));
		} else {
			bytecodeGenMethod.doBoxing(bytecodeGenMethod.getResolver().getResolvedType(binary.getType()));
		}
		argListMethCall.remove(0);
	}

	@Override
	public void visit(Block block) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(CastExpr castExpr) {
		castExpr.accept(bytecodeGenMethod);
		
		if(argListMethCall.get(0))
			bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(castExpr.getType()));
		argListMethCall.remove(0);
	}

	@Override
	public void visit(EmptyStmt emptyStmt) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(FieldVar fieldVar) {
		fieldVar.accept(bytecodeGenMethod);
		
		if(argListMethCall.get(0))
			bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(fieldVar.getType()));
		argListMethCall.remove(0);
	}

	@Override
	public void visit(ForStmt forStmt) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(IfStmt ifStmt) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(InstanceOf instanceOf) {
		instanceOf.accept(bytecodeGenMethod);
		
		if(argListMethCall.get(0))
			bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(instanceOf.getType()));
		argListMethCall.remove(0);
	}

	@Override
	public void visit(LocalVar localVar) {
		localVar.accept(bytecodeGenMethod);
		if(!bytecodeGenMethod.isBinaryExp) {
			if(argListMethCall.get(0))
				bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(localVar.getType()));
		}
		argListMethCall.remove(0);
	}

	@Override
	public void visit(LocalVarDecl localVarDecl) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(MethodCall methodCall) {
		methodCall.accept(bytecodeGenMethod);
		
		if(argListMethCall.get(0))
			bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(methodCall.getType()));
		argListMethCall.remove(0);
	}

	@Override
	public void visit(NewClass methodCall) {
		methodCall.accept(bytecodeGenMethod);
		
		if(argListMethCall.get(0))
			bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(methodCall.getType()));
		argListMethCall.remove(0);
	}

	@Override
	public void visit(NewArray newArray) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(Return aReturn) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(ReturnVoid aReturn) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(StaticClassName staticClassName) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(Super aSuper) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(This aThis) {
		aThis.accept(bytecodeGenMethod);
		
		if(argListMethCall.get(0))
			bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(aThis.getType()));
		argListMethCall.remove(0);
	}

	@Override
	public void visit(WhileStmt whileStmt) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(DoStmt whileStmt) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(AssignToField assignLeftSide) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(AssignToLocal assignLeftSide) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(SuperCall superCall) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(ExpressionReceiver expressionReceiver) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void visit(UnaryExpr unaryExpr) {
		unaryExpr.accept(bytecodeGenMethod);
		
		if(argListMethCall.get(0))
			bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(unaryExpr.getType()));
		argListMethCall.remove(0);
	}

	@Override
	public void visit(Literal literal) {
		literal.accept(bytecodeGenMethod);
		
		if(argListMethCall.get(0))
			bytecodeGenMethod.doUnboxing(bytecodeGenMethod.getResolver().getResolvedType(literal.getType()));
		argListMethCall.remove(0);
	}

}
