package interpreter;

import static function.builtin.EVAL.eval;

import environment.RuntimeEnvironment;
import error.LispException;
import parser.LispParser;
import sexpression.SExpression;

public class LispInterpreter {

    protected RuntimeEnvironment environment;
    private LispParser parser;

    public LispInterpreter() {
        this.environment = RuntimeEnvironment.getInstance();
    }

    public void interpret() {
        createParser();
        printGreeting();

        for (displayPrompt(); !parser.isEof(); displayPrompt())
            printValueOfNextSExpression();

        printFarewell();
    }

    private void createParser() {
        parser = new LispParser(environment.getInput(), environment.getInputName());
    }

    protected void printGreeting() {}

    protected void displayPrompt() {}

    private void printValueOfNextSExpression() {
        try {
            printValueOfNextSExpressionWithException();
        } catch (LispException e) {
            erasePrompt();
            environment.getErrorManager().handle(e);
        }
    }

    private void printValueOfNextSExpressionWithException() {
        SExpression sExpression = parser.getNextSExpression();
        String result = environment.decorateValueOutput(String.valueOf(eval(sExpression)));

        erasePrompt();
        environment.getOutput().println(result);
    }

    protected void erasePrompt() {}

    protected void printFarewell() {
        environment.getOutput().println();
    }

}
