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.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<? extends Event<?>>> sequencesCovered;
	Set<List<? extends 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<? extends Event<?>>> sequences = new LinkedList<List<? extends Event<?>>>();
		List<Event<?>> sequence1 = new ArrayList<Event<?>>();
		sequence1.add(new Event<String>("a"));
		sequence1.add(new Event<String>("b"));
		sequence1.add(new Event<String>("r"));
		sequence1.add(new Event<String>("a"));
		List<Event<?>> sequence2 = new ArrayList<Event<?>>();
		sequence2.add(new Event<String>("c"));
		sequence2.add(new Event<String>("a"));
		sequence2.add(new Event<String>("d"));
		sequence2.add(new Event<String>("a"));
		sequence2.add(new Event<String>("b"));
		sequence2.add(new Event<String>("r"));
		sequence2.add(new Event<String>("a"));
		sequences.add(sequence1);
		sequences.add(sequence2);

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

		sequencesCovered2 = new LinkedHashSet<List<? extends Event<?>>>();
		tmpList = new ArrayList<Event<?>>();
		tmpList.add(new Event<String>("a"));
		tmpList.add(new Event<String>("b"));
		tmpList.add(new Event<String>("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);
	}
}