package de.ugoe.cs.quest.plugin.jfc;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import junit.framework.TestCase;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import de.ugoe.cs.quest.eventcore.Event;
import de.ugoe.cs.quest.eventcore.IEventTarget;
import de.ugoe.cs.quest.plugin.jfc.eventcore.JFCEventId;
import de.ugoe.cs.quest.plugin.jfc.guimodel.JFCGUIElement;
import de.ugoe.cs.quest.plugin.jfc.guimodel.JFCGUIElementSpec;
import de.ugoe.cs.util.console.TextConsole;

/**
 * The class <code>EFGReplayIDCalculatorTest</code> contains tests for the class
 * {@link <code>EFGReplayIDCalculator</code>}
 *
 * @pattern JUnit Test Case
 *
 * @generatedBy CodePro at 7/30/12 4:50 PM
 *
 * @author fabian.glaser
 *
 * @version $Revision$
 */
public class JFCReplayIDCalculatorTest extends TestCase {

	/**
	 * Construct new test instance
	 *
	 * @param name the test name
	 */
	public JFCReplayIDCalculatorTest(String name) {
		super(name);
	}

	/**
	 * Run the String calculateReplayID(JFCEvent) method test.
	 *
	 * @throws Exception
	 *
	 * @generatedBy CodePro at 7/30/12 4:58 PM
	 */
	@Test
	public void testCalculateReplayIDwithEvent()
		throws Exception {
		Collection<JFCEventId> ignoredEvents = new HashSet<JFCEventId>();
		ignoredEvents.add(JFCEventId.FOCUS_GAINED);
		JFCLogParser parser = new JFCLogParser(ignoredEvents);
		parser.parseFile(new File(ClassLoader.getSystemResource("freemind_trace.xml").getFile()));
		
		Collection<List<Event>> sequences = parser.getSequences();
		Event event = sequences.iterator().next().get(0);
		
		String result = new JFCReplayIDCalculator().calculateReplayID(event);
		assertEquals("e3561778462", result);
	}
	
	/**
	 * Run the String calculateReplayID(List<JFCGUIElementSpec>) method test.
	 *
	 * @throws Exception
	 */
	@Test
	public void testCalculateReplayIDwithGuiElementPath()
		throws Exception {
		Collection<JFCEventId> ignoredEvents = new HashSet<JFCEventId>();
		ignoredEvents.add(JFCEventId.FOCUS_GAINED);
		JFCLogParser parser = new JFCLogParser(ignoredEvents);
		parser.parseFile(new File(ClassLoader.getSystemResource("freemind_trace.xml").getFile()));
		
		Collection<List<Event>> sequences = parser.getSequences();
		Event event = sequences.iterator().next().get(0);
		
		List<JFCGUIElementSpec> guiElementPath = new ArrayList<JFCGUIElementSpec>();
		
		IEventTarget target = event.getTarget();
		JFCGUIElement jfcTarget = (JFCGUIElement) target;
		
		// extract element path
		JFCGUIElement currentTarget = jfcTarget;
		while (currentTarget != null){
			JFCGUIElementSpec currentSpec = (JFCGUIElementSpec) currentTarget.getSpecification();
			guiElementPath.add(0, currentSpec);
			currentTarget = (JFCGUIElement) currentTarget.getParent();
		}
		
		String result = new JFCReplayIDCalculator().calculateReplayID(guiElementPath);
		assertEquals("e3561778462", result);
	}
	
	/**
	 * Run the String calculateReplayID(List<JFCGUIElementSpec>) method test.
	 *
	 * @throws Exception
	 */
	@Test
	public void testCalculateReplayIDAllEvents()
		throws Exception {
		// generate list of known replayIDs from guitar efg file
		File guiFile = new File(ClassLoader.getSystemResource("freemind.efg").getFile());
		
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document freemindGUI = builder.parse(guiFile);
		
		Node currentNode = freemindGUI.getFirstChild().getFirstChild();
		NodeList eventNodes = null;
		List<String> knownIDs = new ArrayList<String>();
		
		while ((currentNode = currentNode.getNextSibling()) != null){
			if (currentNode.getNodeName().equals("Events"))
				eventNodes = currentNode.getChildNodes();
		}
		
		for (int i = 0; i < eventNodes.getLength(); i++){
			if (eventNodes.item(i).getNodeName().equals("Event")){
				NodeList attributes = eventNodes.item(i).getChildNodes();
				for (int j = 0; j < attributes.getLength(); j++){
					if (attributes.item(j).getNodeName().equals("EventId")){
						knownIDs.add(attributes.item(j).getTextContent());
					}
				}
			}
		}
		
		// calculate replayIDs from trace file
		Collection<JFCEventId> ignoredEvents = new HashSet<JFCEventId>();
		ignoredEvents.add(JFCEventId.FOCUS_GAINED);
		JFCLogParser parser = new JFCLogParser(ignoredEvents);
		parser.parseFile(new File(ClassLoader.getSystemResource("freemind_trace2.xml").getFile()));
		JFCReplayIDCalculator calculator = new JFCReplayIDCalculator();
		
		Set<String> generatedIDs = new HashSet<String>(); 
		
		Collection<List<Event>> sequences = parser.getSequences();
		
		assertTrue(sequences.size() > 0);
		
		
		for (List<Event> currentSequence: sequences){
			for (Event currentEvent: currentSequence){
				String replayID = calculator.calculateReplayID(currentEvent);
				generatedIDs.add(replayID);
				System.out.println("Generated ID: " + replayID);
			}
		}
		
		System.out.println();
		
		// check if generatedIDs are known
		int known = 0;
		for (String replayID: generatedIDs){
			if (knownIDs.contains(replayID)){
				System.out.println(replayID + "\t is known.");
				known++;
			}
			else
				System.out.println(replayID + "\t is unknown.");
		}
		System.out.println();
		
		float percentage = (float) known/generatedIDs.size()*100;
		System.out.println(percentage + "% of the generated IDs are known.");
		
		assertTrue(percentage > 75);
		
		
	}

	/**
	 * Perform pre-test initialization.
	 *
	 * @throws Exception
	 *         if the initialization fails for some reason
	 *
	 * @generatedBy CodePro at 7/30/12 4:58 PM
	 */
	@Before
	public void setUp()
		throws Exception {
		    new TextConsole(Level.FINEST);
	}

	/**
	 * Perform post-test clean-up.
	 *
	 * @throws Exception
	 *         if the clean-up fails for some reason
	 *
	 * @generatedBy CodePro at 7/30/12 4:58 PM
	 */
	@After
	public void tearDown()
		throws Exception {
		// Add additional tear down code here
	}

	/**
	 * Launch the test.
	 *
	 * @param args the command line arguments
	 *
	 * @generatedBy CodePro at 7/30/12 4:58 PM
	 */
	public static void main(String[] args) {
		new org.junit.runner.JUnitCore().run(JFCReplayIDCalculatorTest.class);
	}
}

/*$CPS$ This comment was generated by CodePro. Do not edit it.
 * patternId = com.instantiations.assist.eclipse.pattern.testCasePattern
 * strategyId = com.instantiations.assist.eclipse.pattern.testCasePattern.junitTestCase
 * additionalTestNames = 
 * assertTrue = false
 * callTestMethod = true
 * createMain = false
 * createSetUp = false
 * createTearDown = false
 * createTestFixture = false
 * createTestStubs = false
 * methods = 
 * package = de.ugoe.cs.eventbench.efg
 * package.sourceFolder = EventBenchConsoleTest/src
 * superclassType = junit.framework.TestCase
 * testCase = EFGEventIDCalculatorTest
 * testClassType = de.ugoe.cs.eventbench.efg.EFGEventIDCalculator
 */