package Models.Statements;

import Exceptions.BaseException;
import Models.Expressions.IExpression;
import Models.Program.IDictionary;
import Models.Program.ProgramState;
import Models.Types.IType;
import Models.Types.StringType;
import Models.Values.StringValue;

public class CloseReadFileStatement implements IStatement{
    private IExpression expression;

    public CloseReadFileStatement(IExpression expression){
        this.expression = expression;
    }

    public IStatement copy(){
        return new CloseReadFileStatement(this.expression.copy());
    }

    public String toString(){
        return "closeRFile(" + this.expression.toString() + ")";
    }

    public ProgramState execute(ProgramState programState) throws BaseException{
        var value = this.expression.evaluate(programState.getSymbolTable(), programState.getHeap());
        if(!value.getType().equals(new StringType())){
            throw new BaseException("CloseReadFileStatement: Expression is not of type StringType");
        }
        if(!programState.getFileTable().contains((StringValue)value)){
            throw new BaseException("CloseReadFileStatement: File is not open");
        }
        var bufferedReader = programState.getFileTable().get((StringValue)value);
        try{
            bufferedReader.close();
        }
        catch(Exception exception){
            throw new BaseException("CloseReadFileStatement: File could not be closed");
        }
        programState.getFileTable().remove((StringValue)value);
        return null;
    }

    public IDictionary<String, IType> typeCheck(IDictionary<String, IType> typeTable) throws BaseException{
        var expressionType = this.expression.typeCheck(typeTable);
        if(!expressionType.equals(new StringType())){
            throw new BaseException("CloseReadFileStatement: Expression is not of type StringType");
        }
        return typeTable;
    }
}
