package de.ugoe.cs.util.console;

import org.junit.*;
import de.ugoe.cs.util.console.listener.ITraceListener;
import de.ugoe.cs.util.console.listener.IOutputListener;
import de.ugoe.cs.util.console.listener.IExceptionListener;
import de.ugoe.cs.util.console.listener.IErrorListener;
import de.ugoe.cs.util.console.listener.ICommandListener;
import static org.junit.Assert.*;

/**
 * The class <code>ConsoleTest</code> contains tests for the class <code>{@link Console}</code>.
 *
 * @author Steffen Herbold
 * @version 1.0
 */
public class ConsoleTest {
	
	private static final String ENDLINE = System.getProperty("line.separator");
	
	private class MockCommandListener implements ICommandListener {
		private String lastCommand = null;

		public String getLastCommand() {
			return lastCommand;
		}

		@Override
		public void commandNotification(String command) {
			lastCommand = command;
		}
	}
	
	private class MockErrorListener implements IErrorListener {
		private String lastError = null;
		public String getLastError() {
			return lastError;
		}
		@Override
		public void errorMsg(String errMessage) {
			lastError = errMessage;
		}
	}
	
	private class MockExceptionListener implements IExceptionListener {
		
		private Exception lastException = null;
		public Exception getLastException() {
			return lastException;
		}
		
		@Override
		public void logException(Exception e) {
			lastException = e;
		}
	}
	
	private class MockOutputListener implements IOutputListener {
		private String lastOutput = null;
		public String getLastOutput() {
			return lastOutput;
		}
		@Override
		public void outputMsg(String newMessage) {
			lastOutput = newMessage;	
		}
	}
	
	private class MockTraceListener implements ITraceListener {
		private String lastTrace = null;
		public String getLastTrace() {
			return lastTrace;
		}
		@Override
		public void traceMsg(String traceMessage) {
			lastTrace = traceMessage;
		}
	}
	
	@SuppressWarnings("deprecation")
	private class MockObserver implements ConsoleObserver {
		
		@Override
		public void commandNotification(String command) {
		}
		@Override
		public void errorMsg(String errMessage) {
		}
		@Override
		public void logException(Exception e) {
		}
		@Override
		public void outputMsg(String newMessage) {	
		}
		@Override
		public void traceMsg(String traceMessage) {
		}
	}
	
	@Test
	public void testCommandNotification_1()
		throws Exception {
		String command = "test";
		
		MockCommandListener commandListener1 = new MockCommandListener();
		MockCommandListener commandListener2 = new MockCommandListener();
		
		Console.getInstance().registerCommandListener(commandListener1);
		Console.getInstance().registerCommandListener(commandListener2);
		Console.commandNotification(command);
		
		assertEquals(command, commandListener1.getLastCommand());
		assertEquals(command, commandListener2.getLastCommand());
	}

	@SuppressWarnings("deprecation")
	@Test
	public void testDeleteObserver_1()
		throws Exception {
		Console fixture = Console.getInstance();
		
		MockObserver mockObserver1 = new MockObserver();
		MockObserver mockObserver2 = new MockObserver();
		fixture.registerObserver(mockObserver1);
		fixture.registerObserver(mockObserver2);

		fixture.deleteObserver(mockObserver1);
		
		assertFalse(fixture.hasCommandListener(mockObserver1));
		assertFalse(fixture.hasErrorListener(mockObserver1));
		assertFalse(fixture.hasExceptionListener(mockObserver1));
		assertFalse(fixture.hasOutputListener(mockObserver1));
		assertFalse(fixture.hasTraceListener(mockObserver1));
		
		assertTrue(fixture.hasCommandListener(mockObserver2));
		assertTrue(fixture.hasErrorListener(mockObserver2));
		assertTrue(fixture.hasExceptionListener(mockObserver2));
		assertTrue(fixture.hasOutputListener(mockObserver2));
		assertTrue(fixture.hasTraceListener(mockObserver2));

		// add additional test code here
	}

	@Test
	public void testGetInstance()
		throws Exception {

		Console result = Console.getInstance();
		assertNotNull(result);
	}

	@Test
	public void testLogException()
		throws Exception {
		Exception e = new Exception();
		MockExceptionListener mockExceptionListener1 = new MockExceptionListener();
		MockExceptionListener mockExceptionListener2 = new MockExceptionListener();
		
		Console.getInstance().registerExceptionListener(mockExceptionListener1);
		Console.getInstance().registerExceptionListener(mockExceptionListener2);
		
		Console.logException(e);
		
		assertEquals(e, mockExceptionListener1.getLastException());
		assertEquals(e, mockExceptionListener2.getLastException());
	}

	@Test
	public void testPrint_1()
		throws Exception {
		String msg = "test";
		
		MockOutputListener mockOutputListener1 = new MockOutputListener();
		MockOutputListener mockOutputListener2 = new MockOutputListener();
		
		Console.getInstance().registerOutputListener(mockOutputListener1);
		Console.getInstance().registerOutputListener(mockOutputListener2);

		Console.print(msg);
		
		assertEquals(msg, mockOutputListener1.getLastOutput());
		assertEquals(msg, mockOutputListener2.getLastOutput());
	}

	@Test
	public void testPrinterr_1()
		throws Exception {
		String errMsg = "test";
		
		MockErrorListener mockErrorListener1 = new MockErrorListener();
		MockErrorListener mockErrorListener2 = new MockErrorListener();
		
		Console.getInstance().registerErrorListener(mockErrorListener1);
		Console.getInstance().registerErrorListener(mockErrorListener2);		

		Console.printerr(errMsg);
		
		assertEquals(errMsg, mockErrorListener1.getLastError());
		assertEquals(errMsg, mockErrorListener2.getLastError());
	}

	@Test
	public void testPrinterrln_1()
		throws Exception {
		String errMsg = "test";
		
		MockErrorListener mockErrorListener1 = new MockErrorListener();
		MockErrorListener mockErrorListener2 = new MockErrorListener();
		
		Console.getInstance().registerErrorListener(mockErrorListener1);
		Console.getInstance().registerErrorListener(mockErrorListener2);		

		Console.printerrln(errMsg);
		
		assertEquals(errMsg+ENDLINE, mockErrorListener1.getLastError());
		assertEquals(errMsg+ENDLINE, mockErrorListener2.getLastError());
	}


	@Test
	public void testPrintln_1()
		throws Exception {
		String msg = "test";
		
		MockOutputListener mockOutputListener1 = new MockOutputListener();
		MockOutputListener mockOutputListener2 = new MockOutputListener();
		
		Console.getInstance().registerOutputListener(mockOutputListener1);
		Console.getInstance().registerOutputListener(mockOutputListener2);

		Console.println(msg);
		
		assertEquals(msg+ENDLINE, mockOutputListener1.getLastOutput());
		assertEquals(msg+ENDLINE, mockOutputListener2.getLastOutput());
	}


	@Test
	public void testRegisterCommandListener_1()
		throws Exception {
		Console fixture = Console.getInstance();
		MockCommandListener mockCommandListener = new MockCommandListener();

		fixture.registerCommandListener(mockCommandListener);
		
		assertTrue(fixture.hasCommandListener(mockCommandListener));
	}

	@Test
	public void testRegisterErrorListener_1()
		throws Exception {
		Console fixture = Console.getInstance();
		
		MockErrorListener mockErrorListener = new MockErrorListener();

		fixture.registerErrorListener(mockErrorListener);
		
		assertTrue(fixture.hasErrorListener(mockErrorListener));
	}

	@Test
	public void testRegisterExceptionListener_1()
		throws Exception {
		Console fixture = Console.getInstance();
		
		MockExceptionListener mockExceptionListener = new MockExceptionListener();

		fixture.registerExceptionListener(mockExceptionListener);

		assertTrue(fixture.hasExceptionListener(mockExceptionListener));
	}

	@SuppressWarnings("deprecation")
	@Test
	public void testRegisterObserver_1()
		throws Exception {
		Console fixture = Console.getInstance();
		
		MockObserver mockObserver = new MockObserver();

		fixture.registerObserver(mockObserver);
		
		assertTrue(fixture.hasCommandListener(mockObserver));
		assertTrue(fixture.hasErrorListener(mockObserver));
		assertTrue(fixture.hasExceptionListener(mockObserver));
		assertTrue(fixture.hasOutputListener(mockObserver));
		assertTrue(fixture.hasTraceListener(mockObserver));
	}

	@Test
	public void testRegisterOutputListener_1()
		throws Exception {
		Console fixture = Console.getInstance();
		
		MockOutputListener mockOutputListener = new MockOutputListener();

		fixture.registerOutputListener(mockOutputListener);
		
		assertTrue(fixture.hasOutputListener(mockOutputListener));
	}

	@Test
	public void testRegisterTraceListener_1()
		throws Exception {
		Console fixture = Console.getInstance();
		
		MockTraceListener mockTraceListener = new MockTraceListener();

		fixture.registerTraceListener(mockTraceListener);
		
		assertTrue(fixture.hasTraceListener(mockTraceListener));
	}

	@Test
	public void testRemoveCommandListener_1()
		throws Exception {
		Console fixture = Console.getInstance();
		
		MockCommandListener mockCommandListener1 = new MockCommandListener();
		MockCommandListener mockCommandListener2 = new MockCommandListener();
		fixture.registerCommandListener(mockCommandListener1);
		fixture.registerCommandListener(mockCommandListener2);
		
		fixture.removeCommandListener(mockCommandListener1);
		
		assertFalse(fixture.hasCommandListener(mockCommandListener1));
		assertTrue(fixture.hasCommandListener(mockCommandListener2));
	}

	@Test
	public void testRemoveErrorListener_1()
		throws Exception {
		Console fixture = Console.getInstance();
		
		MockErrorListener mockErrorListener1 = new MockErrorListener();
		MockErrorListener mockErrorListener2 = new MockErrorListener();
		fixture.registerErrorListener(mockErrorListener1);
		fixture.registerErrorListener(mockErrorListener2);

		fixture.removeErrorListener(mockErrorListener1);
		
		assertFalse(fixture.hasErrorListener(mockErrorListener1));
		assertTrue(fixture.hasErrorListener(mockErrorListener2));
	}

	@Test
	public void testRemoveExceptionListener_1()
		throws Exception {
		Console fixture = Console.getInstance();
		
		MockExceptionListener mockExceptionListener1 = new MockExceptionListener();
		MockExceptionListener mockExceptionListener2 = new MockExceptionListener();
		
		fixture.registerExceptionListener(mockExceptionListener1);
		fixture.registerExceptionListener(mockExceptionListener2);
		
		fixture.removeExceptionListener(mockExceptionListener1);
		
		assertFalse(fixture.hasExceptionListener(mockExceptionListener1));
		assertTrue(fixture.hasExceptionListener(mockExceptionListener2));
	}

	@Test
	public void testRemoveOutputListener_1()
		throws Exception {
		Console fixture = Console.getInstance();
		
		MockOutputListener mockOutputListener1 = new MockOutputListener();
		MockOutputListener mockOutputListener2 = new MockOutputListener();
		
		fixture.registerOutputListener(mockOutputListener1);
		fixture.registerOutputListener(mockOutputListener2);
		
		fixture.removeOutputListener(mockOutputListener1);
		
		assertFalse(fixture.hasOutputListener(mockOutputListener1));
		assertTrue(fixture.hasOutputListener(mockOutputListener2));
	}

	@Test
	public void testRemoveTraceListener_1()
		throws Exception {
		Console fixture = Console.getInstance();
		
		MockTraceListener mockTraceListener1 = new MockTraceListener();
		MockTraceListener mockTraceListener2 = new MockTraceListener();
		
		fixture.registerTraceListener(mockTraceListener1);
		fixture.registerTraceListener(mockTraceListener2);
		
		fixture.removeTraceListener(mockTraceListener1);
		
		assertFalse(fixture.hasTraceListener(mockTraceListener1));
		assertTrue(fixture.hasTraceListener(mockTraceListener2));
	}

	@Test
	public void testTrace_1()
		throws Exception {
		String traceMsg = "test";
		
		MockTraceListener mockTraceListener1 = new MockTraceListener();
		MockTraceListener mockTraceListener2 = new MockTraceListener();
		
		Console.getInstance().registerTraceListener(mockTraceListener1);
		Console.getInstance().registerTraceListener(mockTraceListener2);

		Console.trace(traceMsg);

		assertEquals(traceMsg, mockTraceListener1.getLastTrace());
		assertEquals(traceMsg, mockTraceListener2.getLastTrace());
	}
	
	@Test
	public void testTraceln_1()
		throws Exception {
		String traceMsg = "test";

		MockTraceListener mockTraceListener1 = new MockTraceListener();
		MockTraceListener mockTraceListener2 = new MockTraceListener();
		
		Console.getInstance().registerTraceListener(mockTraceListener1);
		Console.getInstance().registerTraceListener(mockTraceListener2);

		Console.traceln(traceMsg);

		assertEquals(traceMsg+ENDLINE, mockTraceListener1.getLastTrace());
		assertEquals(traceMsg+ENDLINE, mockTraceListener2.getLastTrace());

		// add additional test code here
	}

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

	public static void main(String[] args) {
		new org.junit.runner.JUnitCore().run(ConsoleTest.class);
	}
}