package de.ugoe.cs.quest.coverage;

import java.util.ArrayList;
import java.util.Collection;

import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Set;
import de.ugoe.cs.quest.coverage.CoverageCalculatorProcess;
import de.ugoe.cs.quest.eventcore.Event;
import de.ugoe.cs.quest.eventcore.StringEventType;
import de.ugoe.cs.quest.usageprofiles.MockTrieBasedModel;

import org.junit.*;

import static org.junit.Assert.*;

/**
 * The class <code>CoverageCalculatorProcessTest</code> contains tests for the
 * class <code>{@link CoverageCalculatorProcess}</code>.
 * 
 * @author Steffen Herbold
 * @version 1.0
 */
public class CoverageCalculatorProcessTest {

	Set<List<Event>> sequencesCovered;
	Set<List<Event>> sequencesCovered2;
	MockTrieBasedModel mockProcess;

	@Test
	public void testCoverageCalculatorProcess_1() throws Exception {
		int length = 2;

		CoverageCalculatorProcess result = new CoverageCalculatorProcess(
				mockProcess, sequencesCovered, length);
		assertNotNull(result);
	}

	@Test(expected = java.security.InvalidParameterException.class)
	public void testCoverageCalculatorProcess_2() throws Exception {
		int length = 2;

		new CoverageCalculatorProcess(null,sequencesCovered, length);
	}

	@Test(expected = java.security.InvalidParameterException.class)
	public void testCoverageCalculatorProcess_3() throws Exception {
		int length = 2;

		new CoverageCalculatorProcess(mockProcess, null, length);
	}

	@Test(expected = java.security.InvalidParameterException.class)
	public void testCoverageCalculatorProcess_4() throws Exception {
		int length = 0;

		new CoverageCalculatorProcess(mockProcess, sequencesCovered, length);
	}

	@Test(expected = java.security.InvalidParameterException.class)
	public void testCoverageCalculatorProcess_5() throws Exception {
		int length = -1;

		new CoverageCalculatorProcess(mockProcess, sequencesCovered, length);
	}

	@Test
	public void testGetCoverageAllNoWeight_1() throws Exception {
		int length = 2;
		CoverageCalculatorProcess fixture = new CoverageCalculatorProcess(
				mockProcess, sequencesCovered, length);

		double result = fixture.getCoverageAllNoWeight();

		assertEquals(3.0 / 49.0, result, 0.0001);
	}

	@Test
	public void testGetCoverageAllNoWeight_2() throws Exception {
		int length = 2;
		CoverageCalculatorProcess fixture = new CoverageCalculatorProcess(
				mockProcess, sequencesCovered2, length);

		double result = fixture.getCoverageAllNoWeight();

		assertEquals(2.0 / 49.0, result, 0.0001);
	}

	@Test
	public void testGetCoveragePossibleNoWeight_1() throws Exception {
		int length = 2;
		CoverageCalculatorProcess fixture = new CoverageCalculatorProcess(
				mockProcess, sequencesCovered, length);

		double result = fixture.getCoveragePossibleNoWeight();

		assertEquals(3.0 / 9.0, result, 0.0001);
	}

	@Test
	public void testGetCoveragePossibleNoWeight_2() throws Exception {
		int length = 2;
		CoverageCalculatorProcess fixture = new CoverageCalculatorProcess(
				mockProcess, sequencesCovered2, length);

		double result = fixture.getCoveragePossibleNoWeight();

		assertEquals(2.0 / 9.0, result, 0.0001);
	}

	@Test
	public void testGetCoveragePossibleWeight_1() throws Exception {
		int length = 2;
		CoverageCalculatorProcess fixture = new CoverageCalculatorProcess(
				mockProcess, sequencesCovered, length);

		double result = fixture.getCoveragePossibleWeight();

		assertEquals(6.0, result, 0.0001);
	}

	@Test
	public void testGetCoveragePossibleWeight_2() throws Exception {
		int length = 2;
		CoverageCalculatorProcess fixture = new CoverageCalculatorProcess(
				mockProcess, sequencesCovered2, length);

		double result = fixture.getCoveragePossibleWeight();

		assertEquals(4.0, result, 0.0001);
	}

	@Test
	public void testGetNumCovered_1() throws Exception {
		int length = 2;
		CoverageCalculatorProcess fixture = new CoverageCalculatorProcess(
				mockProcess, sequencesCovered, length);

		int result = fixture.getNumCovered();

		assertEquals(3, result);
	}

	@Test
	public void testGetNumCovered_2() throws Exception {
		int length = 2;
		CoverageCalculatorProcess fixture = new CoverageCalculatorProcess(
				mockProcess, sequencesCovered2, length);

		int result = fixture.getNumCovered();

		assertEquals(2, result);
	}

	@Test
	public void testGetNumPossible_1() throws Exception {
		int length = 2;
		CoverageCalculatorProcess fixture = new CoverageCalculatorProcess(
				mockProcess, sequencesCovered, length);

		int result = fixture.getNumPossible();

		assertEquals(9, result);
	}

	@Test
	public void testSetSequences_1() throws Exception {
		int length = 2;
		CoverageCalculatorProcess fixture = new CoverageCalculatorProcess(
				mockProcess, sequencesCovered, length);

		fixture.setSequences(sequencesCovered2);

		// testing indirectly if sequences were changed
		assertEquals(2, fixture.getNumCovered());
	}

	@Test(expected = java.security.InvalidParameterException.class)
	public void testSetSequences_2() throws Exception {
		int length = 2;
		CoverageCalculatorProcess fixture = new CoverageCalculatorProcess(
				mockProcess, sequencesCovered, length);

		fixture.setSequences(null);
	}

	@Before
	public void setUp() throws Exception {
		Collection<List<Event>> sequences = new LinkedList<List<Event>>();
		List<Event> sequence1 = new ArrayList<Event>();
		sequence1.add(new Event(new StringEventType("a")));
		sequence1.add(new Event(new StringEventType("b")));
		sequence1.add(new Event(new StringEventType("r")));
		sequence1.add(new Event(new StringEventType("a")));
		List<Event> sequence2 = new ArrayList<Event>();
		sequence2.add(new Event(new StringEventType("c")));
		sequence2.add(new Event(new StringEventType("a")));
		sequence2.add(new Event(new StringEventType("d")));
		sequence2.add(new Event(new StringEventType("a")));
		sequence2.add(new Event(new StringEventType("b")));
		sequence2.add(new Event(new StringEventType("r")));
		sequence2.add(new Event(new StringEventType("a")));
		sequences.add(sequence1);
		sequences.add(sequence2);

		sequencesCovered = new LinkedHashSet<List<Event>>();
		List<Event> tmpList = new ArrayList<Event>();
		tmpList.add(new Event(new StringEventType("a")));
		tmpList.add(new Event(new StringEventType("b")));
		tmpList.add(new Event(new StringEventType("r")));
		sequencesCovered.add(tmpList);
		tmpList = new ArrayList<Event>();
		tmpList.add(new Event(new StringEventType("b")));
		tmpList.add(new Event(new StringEventType("r")));
		tmpList.add(new Event(new StringEventType("a")));
		sequencesCovered.add(tmpList);

		sequencesCovered2 = new LinkedHashSet<List<Event>>();
		tmpList = new ArrayList<Event>();
		tmpList.add(new Event(new StringEventType("a")));
		tmpList.add(new Event(new StringEventType("b")));
		tmpList.add(new Event(new StringEventType("r")));
		sequencesCovered2.add(tmpList);

		int markovOrder = 2;
		mockProcess = new MockTrieBasedModel(markovOrder, new Random());
		mockProcess.train(sequences);
	}

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