package com.example.Models.Statements;

import com.example.Exceptions.BaseException;
import com.example.Models.Expressions.IExpression;
import com.example.Models.Program.IDictionary;
import com.example.Models.Program.IHeap;
import com.example.Models.Program.ProgramState;
import com.example.Models.Types.BooleanType;
import com.example.Models.Types.IType;
import com.example.Models.Values.BooleanValue;
import com.example.Models.Values.IValue;


public class IfStatement implements IStatement {
    private IStatement thenStatement;
    private IStatement elseStatement;
    private IExpression condition;

    public IfStatement(IExpression condition, IStatement thenStatement, IStatement elseStatement) {
        this.condition = condition;
        this.thenStatement = thenStatement;
        this.elseStatement = elseStatement;
    }

    public String toString() {
        return "(if(" + condition.toString() + ") then(" + thenStatement.toString() + ") else(" + elseStatement.toString() + "))";
    }

    public IStatement copy() {
        return new IfStatement(condition.copy(), thenStatement.copy(), elseStatement.copy());
    }

    public ProgramState execute(ProgramState state) throws BaseException {
        IDictionary<String, IValue> symbolTable = state.getSymbolTable();
        IHeap heap = state.getHeap();
        IValue conditionValue = condition.evaluate(symbolTable, heap);
        if (conditionValue.getType().equals(new BooleanType())) {
            boolean conditionBool = ((BooleanValue)conditionValue).getValue();
            if (conditionBool) {
                thenStatement.execute(state);
            } else {
                elseStatement.execute(state);
            }
        } else {
            throw new BaseException("Condition is not a boolean!");
        }
        return null;
    }

    public IDictionary<String, IType> typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
        IType conditionType = condition.typeCheck(typeTable);
        if (conditionType.equals(new BooleanType())) {
            thenStatement.typeCheck(typeTable.copy());
            elseStatement.typeCheck(typeTable.copy());
            return typeTable;
        } else {
            throw new BaseException("Condition is not a boolean!");
        }
    }
}
