package eu.dnetlib.data.information.citation;

import java.util.Map;
import java.util.ResourceBundle;

import org.apache.log4j.Logger;
import org.junit.Before;
import org.junit.Test;

import pl.edu.icm.driver.factories.ICMBeansFactory;
import pl.edu.icm.driver.tester.TestDescription;
import pl.edu.icm.driver.tester.runner.Parameterized4TestCase;
import pl.edu.icm.driver.tester.runner.TestJobContext;
import pl.edu.icm.driver.utils.PropertiesKeys;

/**
 * Citation service test class.
 * 
 * @author mhorst
 *
 */
@TestDescription(
		name="Citation Service test suite",
		description="Performs all required functionality tests of Citation service.\n" +
				"Expected properties:\n" +
				"icm.cite.service.location - localisation of citation service\n" +
				"cite.doc.id - citation document identifier\n" +
				"cite.refs.count - number of references found for given document identifier\n" +
				"cite.ref.text - bibliographic reference text\n" +
				"cite.docs.count - number of documents matched for given bibref text"
)
public class CitationServiceTest extends Parameterized4TestCase {

	protected static final Logger log = Logger.getLogger(CitationServiceTest.class);
	
	ICitationService citationService;
	
	String citationServiceLocation;
	
	String citationDocumentId;
	
	String citationRefsCount;
	
	String citationReferenceText;
	
	String citationDocsCount;
	
	
	/* (non-Javadoc)
	 * @see pl.edu.icm.driver.tester.ParameterizedTest#setParameters(java.util.Map)
	 */
	@Override
	public void setParameters(Map<Object, Object> parameters) {
		citationServiceLocation = (String) parameters.get(PropertiesKeys.SERVICE_LOCATION_CITATION);
		log.info("TestCase citationServiceLocation: " + citationServiceLocation);
	}

	@Before
	public void setUp() throws Exception {
		ResourceBundle bundle = ResourceBundle.getBundle(
				"eu.dnetlib.data.information.citation.auxiliary");
		citationDocumentId = bundle.getString(PropertiesKeys.CITE_DOC_ID);
		citationRefsCount = bundle.getString(PropertiesKeys.CITE_REFS_COUNT);
		
		ICMBeansFactory factory = new ICMBeansFactory();
		citationService = factory.getCitationService(citationServiceLocation);
	}
	
	@Test
	@TestDescription(
			planId="cit.functionality",
			description="Retrieves version number from identity call in Citation Service. " +
					"Stores it in the result with description ''"
			)
	public void testIdentify() throws Exception {
		String identify = citationService.identify();
		assertNotNull(identify);
		assertTrue(identify.length()>0);
		System.out.println("service version: "+identify);
		TestJobContext.storeResult(identify, "service version");
	}
	
	@Test
	@TestDescription(
			planId="cit.functionality",
			description="Verifies whether exception is thrown when " +
					"fetching references for null id."
			)
	public void testFetchingReferencesForNullId() throws Exception {
		try {
			citationService.fetchReferences(null);
			fail("Exception should be thrown!");
		} catch(CitationServiceException e) {
//			ok
		}
	}
	
	@Test
	@TestDescription(
			planId="cit.functionality",
			description="Verifies whether null is returned when " +
					"fetching references for non existing document."
			)
	public void testFetchingReferencesForNonExistingId() throws Exception {
		DNetReference[] result =  citationService.fetchReferences("nonExistingId");
		assertNull(result);
	}
	
	@Test
	@TestDescription(
			planId="cit.functionality",
			description="Verifies if references are succesfully fetched " +
					"for given document identifier."
			)
	public void testFetchingReferences() throws Exception {
		DNetReference[] result =  citationService.fetchReferences(citationDocumentId);
		assertNotNull(result);
		assertEquals(Integer.valueOf(citationRefsCount).intValue(), result.length);
//		TODO we should dig into details, but it might be too complicated to define
//		all constraints in property files.
	}
	
	@Test
	@TestDescription(
			planId="cit.functionality",
			description="Verifies whether exception is thrown when " +
					"matching reference for null text."
			)
	public void testMatchingReferenceForNullText() throws Exception {
		try {
			citationService.matchReference(null);
			fail("Exception should be thrown!");
		} catch(CitationServiceException e) {
//			ok
		}
	}
	
	@Test
	@TestDescription(
			planId="cit.functionality",
			description="Verifies if documents are succesfully matched " +
					"for given bibliographic reference."
			)
	public void testMatchingReference() throws Exception {
		String[] results = citationService.matchReference(citationReferenceText);
		assertNotNull(results);
		assertEquals(Integer.valueOf(citationDocsCount).intValue(), results.length);
	}
	
}
