//   Copyright 2012 Georg-August-Universität Göttingen, Germany
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.

package de.ugoe.cs.autoquest.coverage;

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

import de.ugoe.cs.autoquest.coverage.CoverageCalculatorObserved;
import de.ugoe.cs.autoquest.eventcore.Event;
import de.ugoe.cs.autoquest.eventcore.StringEventType;
import de.ugoe.cs.autoquest.usageprofiles.MockTrieBasedModel;

import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Set;

import org.junit.*;

import static org.junit.Assert.*;

/**
 * The class <code>CoverageCalculatorObservedTest</code> contains tests for the
 * class <code>{@link CoverageCalculatorObserved}</code>.
 * 
 * @author Steffen Herbold
 * @version 1.0
 */
public class CoverageCalculatorObservedTest {
	
	Collection<List<Event>> sequencesObserved;
	
	Set<List<Event>> sequencesCovered;
	Set<List<Event>> sequencesCovered2;
	Set<List<Event>> sequencesNewPossible;
	
	MockTrieBasedModel mockProcess;
	
	@Test
	public void testCoverageCalculatorObserved_1() throws Exception {
		int length = 2;

		CoverageCalculatorObserved result = new CoverageCalculatorObserved(
				sequencesObserved, sequencesCovered, length);
		assertNotNull(result);
	}

	@Test(expected = java.lang.IllegalArgumentException.class)
	public void testCoverageCalculatorObserved_2() throws Exception {
		int length = 2;

		new CoverageCalculatorObserved(null,sequencesCovered, length);
	}

	@Test(expected = java.lang.IllegalArgumentException.class)
	public void testCoverageCalculatorObserved_3() throws Exception {
		int length = 2;

		new CoverageCalculatorObserved(sequencesObserved, null, length);
	}

	@Test(expected = java.lang.IllegalArgumentException.class)
	public void testCoverageCalculatorObserved_4() throws Exception {
		int length = 0;

		new CoverageCalculatorObserved(sequencesObserved, sequencesCovered, length);
	}

	@Test(expected = java.lang.IllegalArgumentException.class)
	public void testCoverageCalculatorObserved_5() throws Exception {
		int length = -1;

		new CoverageCalculatorObserved(sequencesObserved, sequencesCovered, length);
	}
	
	@Test
	public void testCoverageObserved_1() throws Exception {
		int length = 2;
		CoverageCalculatorObserved fixture = new CoverageCalculatorObserved(
				sequencesObserved, sequencesCovered, length);
		
		double result = fixture.getCoverageObserved();
		
		assertEquals(3.0/6.0, result, 0.0001);
	}
	
	@Test
	public void testCoverageObserved_2() throws Exception {
		int length = 2;
		CoverageCalculatorObserved fixture = new CoverageCalculatorObserved(
				sequencesObserved, sequencesCovered2, length);
		
		double result = fixture.getCoverageObserved();
		
		assertEquals(2.0/6.0, result, 0.0001);
	}
	
	@Test
	public void testCoverageObservedWeigth_1() throws Exception {
		int length = 2;
		CoverageCalculatorObserved fixture = new CoverageCalculatorObserved(
				sequencesObserved, sequencesCovered, length);
		
		double result = fixture.getCoverageObservedWeigth(mockProcess);
		
		assertEquals(6.0, result, 0.0001);
	}
	
	@Test
	public void testCoverageObservedWeigth_2() throws Exception {
		int length = 2;
		CoverageCalculatorObserved fixture = new CoverageCalculatorObserved(
				sequencesObserved, sequencesCovered2, length);
		
		double result = fixture.getCoverageObservedWeigth(mockProcess);
		
		assertEquals(4.0, result, 0.0001);
	}
	
	@Test
	public void testGetNewPercentage_1() throws Exception {
		int length = 2;
		CoverageCalculatorObserved fixture = new CoverageCalculatorObserved(
				sequencesObserved, sequencesCovered, length);
		
		double result = fixture.getNewPercentage();
		
		assertEquals(1.0/4.0, result, 0.0001);
	}
	
	@Test
	public void testGetNewPercentage_2() throws Exception {
		int length = 2;
		CoverageCalculatorObserved fixture = new CoverageCalculatorObserved(
				sequencesObserved, sequencesCovered2, length);
		
		double result = fixture.getNewPercentage();
		
		assertEquals(0.0, result, 0.0001);
	}
	
	@Test
	public void testCoveragePossibleNew_1() throws Exception {
		int length = 3;
		CoverageCalculatorObserved fixture = new CoverageCalculatorObserved(
				sequencesObserved, sequencesNewPossible, length);
		
		double result = fixture.getCoveragePossibleNew(mockProcess);
		
		assertEquals(1.0/11.0, result, 0.0001);
	}
	
	@Test
	public void testCoveragePossibleNew_2() throws Exception {
		int length = 2;
		CoverageCalculatorObserved fixture = new CoverageCalculatorObserved(
				sequencesObserved, sequencesCovered, length);
		
		double result = fixture.getCoveragePossibleNew(mockProcess);
		
		assertEquals(0.0, result, 0.0001);
	}
	
	@Test(expected = java.lang.IllegalArgumentException.class ) 
	public void testCoveragePossibleNew_3() throws Exception {
		int length = 3;
		CoverageCalculatorObserved fixture = new CoverageCalculatorObserved(
				sequencesObserved, sequencesCovered, length);
		
		fixture.getCoveragePossibleNew(null);
	}
	
	@Test
	public void testCoveragePossibleNewWeight_1() throws Exception {
		int length = 3;
		CoverageCalculatorObserved fixture = new CoverageCalculatorObserved(
				sequencesObserved, sequencesNewPossible, length);
		
		double result = fixture.getCoveragePossibleNewWeight(mockProcess);
		
		assertEquals(2.0, result, 0.0001);
	}
	
	@Test
	public void testCoveragePossibleNewWeight_2() throws Exception {
		int length = 2;
		CoverageCalculatorObserved fixture = new CoverageCalculatorObserved(
				sequencesObserved, sequencesCovered, length);
		
		double result = fixture.getCoveragePossibleNewWeight(mockProcess);
		
		assertEquals(0.0, result, 0.0001);
	}
	
	@Test(expected = java.lang.IllegalArgumentException.class ) 
	public void testCoveragePossibleNewWeight_3() throws Exception {
		int length = 3;
		CoverageCalculatorObserved fixture = new CoverageCalculatorObserved(
				sequencesObserved, sequencesCovered, length);
		
		fixture.getCoveragePossibleNewWeight(null);
	}	
	
	
	@Test
	public void testGetNumObserved_1() throws Exception {
		int length = 2;
		CoverageCalculatorObserved fixture = new CoverageCalculatorObserved(
				sequencesObserved, sequencesCovered, length);
		
		int result = fixture.getNumObserved();
		
		assertEquals(6, result);
	}
	
	@Test
	public void testGetNumCovered_1() throws Exception {
		int length = 2;
		CoverageCalculatorObserved fixture = new CoverageCalculatorObserved(
				sequencesObserved, sequencesCovered, length);
		
		int result = fixture.getNumCovered();
		
		assertEquals(4, result);
	}
	
	@Test
	public void testGetNumCovered_2() throws Exception {
		int length = 2;
		CoverageCalculatorObserved fixture = new CoverageCalculatorObserved(
				sequencesObserved, sequencesCovered2, length);
		
		int result = fixture.getNumCovered();
		
		assertEquals(2, result);
	}
	
	@Test
	public void testGetNumNew_1() throws Exception {
		int length = 2;
		CoverageCalculatorObserved fixture = new CoverageCalculatorObserved(
				sequencesObserved, sequencesCovered, length);
		
		int result = fixture.getNumNew();
		
		assertEquals(1, result);
	}
	
	@Test
	public void testGetNumNew_2() throws Exception {
		int length = 2;
		CoverageCalculatorObserved fixture = new CoverageCalculatorObserved(
				sequencesObserved, sequencesCovered2, length);
		
		int result = fixture.getNumNew();
		
		assertEquals(0, result);
	}
	
	@Before
	public void setUp() throws Exception {
		sequencesObserved = 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")));
		sequencesObserved.add(sequence1);
		sequencesObserved.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")));
		tmpList.add(new Event(new StringEventType("e")));
		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);
		
		sequencesNewPossible = new LinkedHashSet<List<Event>>();
		tmpList = new ArrayList<Event>();
		tmpList.add(new Event(new StringEventType("r")));
		tmpList.add(new Event(new StringEventType("a")));
		tmpList.add(new Event(new StringEventType("b")));
		sequencesNewPossible.add(tmpList);
		
		int markovOrder = 2;
		mockProcess = new MockTrieBasedModel(markovOrder, new Random());
		mockProcess.train(sequencesObserved);
	}

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

}
