package interpreter;

import static org.junit.Assert.*;

import java.io.*;

import org.junit.*;

import interpreter.LispInterpreterBuilderImpl.InterpreterAlreadyBuiltException;

public class LispInterpreterBuilderTester {

    private LispInterpreterBuilder builder = new LispInterpreterBuilderImpl() {

        public void reset() {
            this.isBuilt = false;
        }
    };

    private void setCommonFeatures() {
        builder.setOutput(new PrintStream(new ByteArrayOutputStream()));
        builder.setErrorOutput(new PrintStream(new ByteArrayOutputStream()));
        builder.setTerminationFunction(() -> {});
        builder.setErrorTerminationFunction(() -> {});
    }

    @Before
    public void setUp() throws Exception {
        builder.reset();
    }

    @After
    public void tearDown() throws Exception {
        builder.reset();
    }

    @Test
    public void buildInteractiveInterpreter() {
        setCommonFeatures();
        builder.setInput(System.in, "stdin");
        LispInterpreter interpreter = builder.build();

        assertTrue(interpreter instanceof InteractiveLispInterpreter);
    }

    @Test
    public void buildNonInteractiveInterpreter() {
        setCommonFeatures();
        builder.setInput(System.in, "stdin");
        builder.setNotInteractive();
        LispInterpreter interpreter = builder.build();

        assertFalse(interpreter instanceof InteractiveLispInterpreter);
    }

    @Test
    public void buildFileBasedInterpreter() {
        setCommonFeatures();
        builder.useFile("test/interpreter/test-files/file.lisp");
        LispInterpreter interpreter = builder.build();

        assertFalse(interpreter instanceof InteractiveLispInterpreter);
    }

    @Test(expected = InterpreterAlreadyBuiltException.class)
    public void cannotBuildMoreThanOneInterpreter() {
        builder.build();
        builder.build();
    }

    @Test
    public void interpreterAlreadyBuiltException_HasMessage() {
        InterpreterAlreadyBuiltException e = new InterpreterAlreadyBuiltException();

        assertNotNull(e.getMessage());
        assertTrue(e.getMessage().length() > 0);
    }

    @Test(expected = InterpreterAlreadyBuiltException.class)
    public void resetNormallyDoesNothing() {
        builder = new LispInterpreterBuilderImpl();

        builder.build();
        builder.reset();
        builder.build();
    }

}
