package Models.Statements;

import java.io.BufferedReader;
import java.io.FileReader;

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 OpenReadFileStatement implements IStatement {
    private IExpression expression;

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

    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("OpenReadFileStatement: Expression is not of type StringType");
        }
        var stringValue = (StringValue)value;
        if(programState.getFileTable().contains(stringValue)){
            throw new BaseException("OpenReadFileStatement: File is already open");
        }
        BufferedReader bufferedReader;
        try{
            bufferedReader = new BufferedReader(new FileReader(stringValue.getValue()));
        }
        catch(Exception exception){
            throw new BaseException("OpenReadFileStatement: File does not exist");
        }
        programState.getFileTable().add(stringValue, bufferedReader);
        return null;
    }

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

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

    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("OpenReadFileStatement: Expression is not of type StringType");
        }
        return typeTable;
    }

}
