package Models.Statements;

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

public class AssignmentStatement implements IStatement {
    private String variableName;
    private IExpression expression;

    public AssignmentStatement(String variableName, IExpression expression) {
        this.variableName = variableName;
        this.expression = expression;
    }

    public String toString() {
        return variableName + " = " + expression.toString();
    }

    public IStatement copy() {
        return new AssignmentStatement(variableName, expression.copy());
    }

    public ProgramState execute(ProgramState state) throws BaseException {
        IDictionary<String, IValue> symbolTable = state.getSymbolTable();
        IHeap heap = state.getHeap();
        if(symbolTable.contains(variableName)) {
            IValue value = expression.evaluate(symbolTable, heap);
            IType variableType = (symbolTable.get(variableName)).getType();
            if(value.getType().equals(variableType)) {
                symbolTable.update(variableName, value);
            } else {
                throw new BaseException("Declared type of variable " + variableName + " and type of the assigned expression do not match!");
            }
        } else {
            throw new BaseException("Variable " + variableName + " is not defined!");
        }
        return null;
    }

    public IDictionary<String, IType> typeCheck(IDictionary<String, IType> typeTable) throws BaseException {
        IType variableType = typeTable.get(variableName);
        IType expressionType = expression.typeCheck(typeTable);
        if(variableType.equals(expressionType)) {
            return typeTable;
        } else {
            throw new BaseException("Declared type of variable " + variableName + " and type of the assigned expression do not match!");
        }
    }
}
