package de.ugoe.cs.util.console;

import java.util.logging.Level;

import org.junit.*;
import de.ugoe.cs.util.console.mock.MockCommandListener;
import de.ugoe.cs.util.console.mock.MockErrorListener;
import de.ugoe.cs.util.console.mock.MockExceptionListener;
import de.ugoe.cs.util.console.mock.MockObserver;
import de.ugoe.cs.util.console.mock.MockOutputListener;
import de.ugoe.cs.util.console.mock.MockTraceListener;
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");
	
	@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));
	}

	@SuppressWarnings("deprecation")
    @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(Level.INFO, mockTraceListener1.getLastLevel());
		assertEquals(traceMsg, mockTraceListener2.getLastTrace());
		assertEquals(Level.INFO, mockTraceListener2.getLastLevel());
	}
	
	       @Test
	        public void testTrace_2()
	                throws Exception {
	                String traceMsg = "test";
	                Level traceLevel = Level.SEVERE;
	                
	                MockTraceListener mockTraceListener1 = new MockTraceListener();
	                MockTraceListener mockTraceListener2 = new MockTraceListener();
	                
	                Console.getInstance().registerTraceListener(mockTraceListener1);
	                Console.getInstance().registerTraceListener(mockTraceListener2);

	                Console.trace(traceLevel, traceMsg);

	                assertEquals(traceMsg, mockTraceListener1.getLastTrace());
	                assertEquals(traceLevel, mockTraceListener1.getLastLevel());
	                assertEquals(traceMsg, mockTraceListener2.getLastTrace());
	                assertEquals(traceLevel, mockTraceListener2.getLastLevel());
	        }
	
	@SuppressWarnings("deprecation")
    @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(Level.INFO, mockTraceListener1.getLastLevel());
		assertEquals(traceMsg+ENDLINE, mockTraceListener2.getLastTrace());
		assertEquals(Level.INFO, mockTraceListener1.getLastLevel());
	}
	
	@Test
        public void testTraceln_2()
                throws Exception {
                String traceMsg = "test";
                Level traceLevel = Level.SEVERE;

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

                Console.traceln(traceLevel, traceMsg);

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

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

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