package environment;

import static org.junit.Assert.*;

import java.util.*;

import org.junit.*;

import error.ErrorManager;

public class RuntimeEnvironmentTester {

    private static final String TERMINATED_SUCCESSFULLY = "TERMINATED_SUCCESSFULLY";
    private static final String TERMINATED_EXCEPTIONALLY = "TERMINATED_EXCEPTIONALLY";

    private RuntimeEnvironment environment;
    private Set<String> indicatorSet;

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

    @Before
    public void setUp() {
        indicatorSet = new HashSet<>();
    }

    @Test
    public void assignInputName() {
        environment.setInputName("test");

        assertEquals("test", environment.getInputName());
    }

    @Test
    public void assignInput() {
        environment.setInput(System.in);

        assertEquals(System.in, environment.getInput());
    }

    @Test
    public void assignOutput() {
        environment.setOutput(System.out);

        assertEquals(System.out, environment.getOutput());
    }

    @Test
    public void assignErrorOutput() {
        environment.setErrorOutput(System.err);

        assertEquals(System.err, environment.getErrorOutput());
    }

    @Test
    public void assignTerminationFunction() {
        environment.setTerminationFunction(() -> indicatorSet.add(TERMINATED_SUCCESSFULLY));
        environment.terminateSuccessfully();

        assertTrue(indicatorSet.contains(TERMINATED_SUCCESSFULLY));
    }

    @Test
    public void assignErrorTerminationFunction() {
        environment.setErrorTerminationFunction(() -> indicatorSet.add(TERMINATED_EXCEPTIONALLY));
        environment.terminateExceptionally();

        assertTrue(indicatorSet.contains(TERMINATED_EXCEPTIONALLY));
    }

    @Test
    public void assignErrorManager() {
        ErrorManager errorManager = new ErrorManager();
        environment.setErrorManager(errorManager);

        assertEquals(errorManager, environment.getErrorManager());
    }

    @Test
    public void assignOutputDecorator() {
        environment.setOutputDecorator(s -> "[" + s + "]");

        assertEquals("[test]", environment.decorateOutput("test"));
    }

    @Test
    public void assignValueOutputDecorator() {
        environment.setValueOutputDecorator(s -> "(" + s + ")");

        assertEquals("(test)", environment.decorateValueOutput("test"));
    }

    @Test
    public void assignWarningOutputDecorator() {
        environment.setWarningOutputDecorator(s -> "|" + s + "|");

        assertEquals("|test|", environment.decorateWarningOutput("test"));
    }

    @Test
    public void assignErrorOutputDecorator() {
        environment.setErrorOutputDecorator(s -> "{" + s + "}");

        assertEquals("{test}", environment.decorateErrorOutput("test"));
    }

    @Test
    public void assignCriticalOutputDecorator() {
        environment.setCriticalOutputDecorator(s -> "/" + s + "/");

        assertEquals("/test/", environment.decorateCriticalOutput("test"));
    }

}
