package oving6.logger;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.ByteArrayOutputStream;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

public class FilteringLoggerTest {

	private ByteArrayOutputStream stream;
	private StreamLogger subLogger;

	@BeforeEach
	public void setUp() {
		stream = new ByteArrayOutputStream();
		subLogger = new StreamLogger(stream);
	}

	@Test
	@DisplayName("Create logger without severities")
	public void testFilteringLoggerNoSeverities() {
		FilteringLogger logger = new FilteringLogger(subLogger);
		assertFalse(logger.isLogging(ILogger.INFO),
				"Test logger without severity for info-logging");
		assertFalse(logger.isLogging(ILogger.WARNING),
				"Test logger without severity for warning-logging");
		assertFalse(logger.isLogging(ILogger.ERROR),
				"Test logger without severity for error-logging");
	}

	@Test
	@DisplayName("Create logger with error and info")
	public void testFilteringLoggerErrorAndInfo() {
		FilteringLogger logger = new FilteringLogger(subLogger, ILogger.ERROR, ILogger.INFO);
		assertTrue(logger.isLogging(ILogger.INFO), "Test error and info logger for info-logging");
		assertFalse(logger.isLogging(ILogger.WARNING),
				"Test error and info logger for warning-logging");
		assertTrue(logger.isLogging(ILogger.ERROR), "Test error and info logger for error-logging");
	}

	@Test
	@DisplayName("Create logger with warning, set error")
	public void testFilteringLoggerWarningSetIsLoggingError() {
		FilteringLogger logger = new FilteringLogger(subLogger, ILogger.WARNING);
		assertFalse(logger.isLogging(ILogger.INFO), "Test warning logger for info-logging");
		assertTrue(logger.isLogging(ILogger.WARNING), "Test warning logger for warning-logging");
		assertFalse(logger.isLogging(ILogger.ERROR), "Test warning logger for error-logging");

		logger.setIsLogging(ILogger.ERROR, true);
		assertFalse(logger.isLogging(ILogger.INFO),
				"Set error-logging for warning logger and test for info-logging");
		assertTrue(logger.isLogging(ILogger.WARNING),
				"Set error-logging for warning logger and test for warning-logging");
		assertTrue(logger.isLogging(ILogger.ERROR),
				"Set error-logging for warning logger and test for error-logging");
	}

	@Test
	@DisplayName("Logger with severity ERROR")
	public void testErrorLogging() {
		IllegalStateException exception = new IllegalStateException();
		FilteringLogger logger = new FilteringLogger(subLogger, ILogger.ERROR);
		String formatString = "%s: %s (%s)";

		subLogger.setFormatString(formatString);
		logger.log(ILogger.ERROR, "Noe er feil!", exception);
		assertEquals(String.format(formatString, ILogger.ERROR, "Noe er feil!", exception),
				stream.toString().trim(), "Test the format of error message after logging");
	}

	@Test
	@DisplayName("Logger with severity INFO in ERROR logger")
	public void testInfoToErrorLogger() {
		IllegalStateException exception = new IllegalStateException();
		FilteringLogger logger = new FilteringLogger(subLogger, ILogger.ERROR);
		String formatString = "%s: %s (%s)";

		subLogger.setFormatString(formatString);
		logger.log(ILogger.INFO, "Noe er feil!", exception);
		assertEquals("", stream.toString(),
				"Test the stream after logging info message in error logger");
	}
}
