package org.grobid.core.annotations;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventFactory;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.StartElement;

import org.grobid.core.utilities.TeiValues;
import org.junit.Test;

/**
 * Test the class TeiStAXParsedInfo.
 * 
 * @author Damien
 * 
 */
public class TeiStAXParsedInfoTest {

	@Test
	public void testConstructor() {
		final TeiStAXParsedInfo infos = new TeiStAXParsedInfo(false);
		assertNotNull("should not be null", infos.gorn);
		assertNotNull("should not be null", infos.tags);
		assertNotNull("should not be null", infos.description);
	}

	@Test
	public void testReset() {
		final TeiStAXParsedInfo infos = new TeiStAXParsedInfo(false);
		infos.tags.add("some tag");
		infos.reset();
		assertTrue("tags should be empty", infos.tags.isEmpty());
	}

	@Test
	public void testResetDexcription() {
		final TeiStAXParsedInfo infos = new TeiStAXParsedInfo(false);
		infos.description.rawDescription.append("raw description");
		infos.resetDescription();
		assertEquals("rawDescription of description should be empty", "", infos.description.rawDescription.toString());
	}

	@Test
	public void testAppendRemoveTagName() {
		final TeiStAXParsedInfo infos = new TeiStAXParsedInfo(false);
		infos.appendTagName("TAG");
		assertEquals("tags should have 1 element: TAG", "TAG", infos.tags.get(0));
		infos.removeTagName("TAG");
		assertTrue("tags should be empty", infos.tags.isEmpty());
	}

	@Test
	public void testCheckIfDescriptionTrue() {
		final TeiStAXParsedInfo infos = new TeiStAXParsedInfo(false);
		final QName qName = getQName("", TeiValues.TAG_DIV, "");
		final Iterator<Attribute> attributes = getAttributes(createAttribute("type", "description"));
		final StartElement start = createStartElement(qName, attributes, null);
		assertTrue("checkIfDescription should return true", infos.checkIfDescription(start));
	}

	@Test
	public void testCheckIfDescriptionFalse() {
		final TeiStAXParsedInfo infos = new TeiStAXParsedInfo(false);
		final QName qName = getQName("", TeiValues.TAG_DIV, "");
		final Iterator<Attribute> attributes = getAttributes(createAttribute("noType", "description"));
		final StartElement start = createStartElement(qName, attributes, null);
		assertFalse("checkIfDescription should return false", infos.checkIfDescription(start));
	}

	@Test
	public void testCheckIfDescriptionFalse2() {
		final TeiStAXParsedInfo infos = new TeiStAXParsedInfo(false);
		final QName qName = getQName("", "SOME_TAG", "");
		final Iterator<Attribute> attributes = getAttributes(createAttribute("type", "description"));
		final StartElement start = createStartElement(qName, attributes, null);
		assertFalse("checkIfDescription should return false", infos.checkIfDescription(start));
	}

	@Test
	public void testProcessParagraphStartTagTrue() {
		final TeiStAXParsedInfo infos = new TeiStAXParsedInfo(false);
		final QName qName = getQName("", TeiValues.TAG_P, "");
		final StartElement start = createStartElement(qName, null, null);
		assertTrue("processParagraphStartTag should return true", infos.processParagraphStartTag(start));
	}

	@Test
	public void testProcessParagraphStartTagFalse() {
		final TeiStAXParsedInfo infos = new TeiStAXParsedInfo(false);
		final QName qName = getQName("", "SOME_TAG", "");
		final StartElement start = createStartElement(qName, null, null);
		assertFalse("processParagraphStartTag should return false", infos.processParagraphStartTag(start));
	}

	@Test
	public void testProcessParagraphEndTagTrue() {
		final TeiStAXParsedInfo infos = new TeiStAXParsedInfo(false);
		infos.tags.add(TeiValues.TAG_P);
		final QName qName = getQName("", TeiValues.TAG_P, "");
		final StartElement start = createStartElement(qName, null, null);
		// Add paragraph to avoid NullPointerException.
		infos.description.appendParagraphStartTag(start);
		assertTrue("processParagraphEndTag should return true", infos.processParagraphEndTag(TeiValues.TAG_P));
	}

	@Test
	public void testProcessParagraphEndTagFalse() {
		final TeiStAXParsedInfo infos = new TeiStAXParsedInfo(false);
		assertFalse("processParagraphEndTag should return flase", infos.processParagraphEndTag("SOME_TAG"));
	}

	@Test
	public void testAppendDescriptionContent() {
		final TeiStAXParsedInfo infos = new TeiStAXParsedInfo(false);
		infos.appendDescriptionContent("some description");
		assertEquals("rawDescription value should be \"some description\"", "some description",
				infos.getDescription().rawDescription.toString());
	}

	@Test
	public void testGornIndex() {
		final TeiStAXParsedInfo infos = new TeiStAXParsedInfo(false);
		infos.incrementGornIndex();
		infos.incrementGornIndex();
		infos.incrementGornIndex();
		infos.decrementGornIndex();
		infos.decrementGornIndex();
		infos.incrementGornIndex();
		infos.incrementGornIndex();
		infos.decrementGornIndex();
		infos.incrementGornIndex();
		infos.decrementGornIndex();
		infos.incrementGornIndex();
		assertEquals("The gorn index value should be 1.2.3.", "1.2.3.", infos.getCurrentGornIndex());
	}

	private static QName getQName(final String namespaceURI, final String localPart, final String prefix) {
		return new QName(namespaceURI, localPart, prefix);
	}

	private static StartElement createStartElement(final QName name, final Iterator<?> attributes, final Iterator<?> namespaces) {
		final XMLEventFactory eventFactory = XMLEventFactory.newInstance();
		return eventFactory.createStartElement(name, attributes, namespaces);
	}

	private static Attribute createAttribute(final String localName, final String value) {
		final XMLEventFactory eventFactory = XMLEventFactory.newInstance();
		return eventFactory.createAttribute(localName, value);
	}

	private static Iterator<Attribute> getAttributes(final Attribute... pAttr) {
		Set<Attribute> attributes = new TreeSet<Attribute>();
		for (final Attribute attr : pAttr) {
			attributes.add(attr);
		}
		return attributes.iterator();
	}
}

@@ -829,279 +829,19 @@
 fos.
-tags);%0A%09%09assertNotNull(%22should not be null%22, infos.description);%0A%09%7D%0A%0A%09@Test%0A%09public void testReset() %7B%0A%09%09final TeiStAXParsedInfo infos = new TeiStAXParsedInfo(false);%0A%09%09infos.tags.add(%22some tag%22);%0A%09%09infos.reset();%0A%09%09assertTrue(%22tags should be empty%22, infos.tags.isEmpty()
+description
 );%0A%09
@@ -1164,321 +1164,8 @@
 %09%7D%0A%0A
-%09@Test%0A%09public void testAppendRemoveTagName() %7B%0A%09%09final TeiStAXParsedInfo infos = new TeiStAXParsedInfo(false);%0A%09%09infos.appendTagName(%22TAG%22);%0A%09%09assertEquals(%22tags should have 1 element: TAG%22, %22TAG%22, infos.tags.get(0));%0A%09%09infos.removeTagName(%22TAG%22);%0A%09%09assertTrue(%22tags should be empty%22, infos.tags.isEmpty());%0A%09%7D%0A%0A
 %09@Te
@@ -3291,43 +3291,8 @@
 e);%0A
-%09%09infos.tags.add(TeiValues.TAG_P);%0A
 %09%09fi

Removing unuseful code.