package eu.dnetlib.api.client;

import java.net.URI;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import eu.dnetlib.api.utils.OpenAireDocumentPage;
import eu.dnetlib.api.utils.ResponseHeader;
import org.apache.http.client.utils.URIBuilder;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

import static org.junit.Assert.*;

@Ignore
public class OpenairePublicationsApiClientTest extends OpenaireApiClientTest {

	String today = "";

	@Before
	public void setUp() {
		Date d = new Date();
		SimpleDateFormat format = new SimpleDateFormat("YYYY-MM-dd");
		today = format.format(d);
	}

	@Test
	public void testPublications() throws URISyntaxException, DocumentException {
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath);
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		ResponseHeader pageHeader = page.getResponseHeader();
		assertEquals("unexpected query",publicationsQuery, pageHeader.getQuery());
		assertEquals("unexpected page number", 1, pageHeader.getPage());
		assertEquals("unexpected page size", defaultPageSize, pageHeader.getPageSize());
	}

	@Test
	public void testPublicationParameters() throws URISyntaxException, DocumentException {
		for (String param : commonParameters) {
			if (!param.equals("model") && !param.equals("format") && !param.equals("page") && !param.equals("size") && !param.equals("sortBy")) {
				URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath).addParameter(param, "test");
				URI uri = builder.build();
				System.out.println(uri);
				String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
				checkNotException(results);
			}
		}
		for (String param : publicationParameters) {
			if (!param.equals("fromDateAccepted") && !param.equals("toDateAccepted")) {
				URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath).addParameter(param, "test");
				URI uri = builder.build();
				System.out.println(uri);
				String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
				checkNotException(results);
			}
		}
	}

	@Test
	public void testPublicationsUnexistingParameter() throws URISyntaxException, DocumentException {
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath);
		builder.addParameter("pippo", "hello");
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		checkException(results, "java.lang.IllegalArgumentException");
	}

	@Test
	public void testSortByPublicationsParameters() throws URISyntaxException, DocumentException {
		checkSortByParamaters(EntityType.publication);
	}

	@Test
	public void testPublicationsPage() throws URISyntaxException, DocumentException {
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath);
		builder.addParameter("page", "4");
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		ResponseHeader pageHeader = page.getResponseHeader();
		assertEquals("unexpected page number", 4, pageHeader.getPage());
	}

	@Test
	public void testPublicationsPageSize() throws URISyntaxException, DocumentException {
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath);
		builder.addParameter("size", "100");
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		ResponseHeader pageHeader = page.getResponseHeader();
		assertEquals("unexpected query",publicationsQuery, pageHeader.getQuery());
		assertEquals("unexpected page size", 100, pageHeader.getPageSize());
	}

	//Ignored just because it takes long time...
	@Ignore
	@Test
	public void testMaxPageSizePublication() throws URISyntaxException, DocumentException {
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath).addParameter("size", "" + MAX_PAGE_SIZE + 1);
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		checkException(results, "java.lang.IllegalArgumentException");

		builder = new URIBuilder(requestBaseURL).setPath(publicationsPath).addParameter("size", "" + MAX_PAGE_SIZE);
		uri = builder.build();
		System.out.println(uri);
		results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		checkNotException(results);

		assertTrue(MAX_NUM_RESULTS >= MAX_PAGE_SIZE);
	}

	@Test
	public void testPublicationsFormatXML() throws URISyntaxException, DocumentException {
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath);
		builder.addParameter("format", "xml");
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		Document doc = DocumentHelper.parseText(results);
		assertNotNull(doc);
	}

	@Test
	public void testPublicationsFormatWrong() throws URISyntaxException, DocumentException {
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath);
		builder.addParameter("format", "hello");
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		checkException(results, "java.lang.IllegalArgumentException");
	}

	@Test
	public void testPublicationsECFunding() throws URISyntaxException, DocumentException {
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath);
		builder.addParameter("hasECFunding", "true");
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertTrue("not all entities with EC funding", page.allWithECFunding());
	}

	@Test
	public void testPublicationsWTFunding() throws URISyntaxException, DocumentException {
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath);
		builder.addParameter("hasWTFunding", "true");
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertTrue("not all entities with WT funding", page.allWithWTFunding());
	}

	@Test
	public void testPublicationsWTFunder() throws URISyntaxException, DocumentException {
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath);
		builder.addParameter("funder", "wt");
		URI uri1 = builder.build();
		System.out.println(uri1);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri1);
		OpenAireDocumentPage pageWT = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertTrue("not all entities with WT funding",pageWT.allWithWTFunding());
	}

	@Test
	public void testPublicationsSingleOpenaireID() throws URISyntaxException, DocumentException {
		String testRecordId = "od________18::f055e1a3188aa57b454b1bfc0b882ed2";
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath);
		builder.addParameter("openairePublicationID", testRecordId);
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertEquals("unexpected number of results",1, page.getResponseHeader().getTotal());
		List<String> objIds = page.getObjIdentifiers();
		assertTrue("unexpected objidentifier", objIds.contains(testRecordId));
	}

	@Test
	public void testPublicationsMultipleOpenaireIDs1() throws URISyntaxException, DocumentException {
		String testRecordId1 = "od________18::f055e1a3188aa57b454b1bfc0b882ed2";
		String testRecordId2 = "od________18::5ea480618e9ab9e7db827fa498422075";
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath);
		builder.addParameter("openairePublicationID", testRecordId1 + "," + testRecordId2);
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertEquals("unexpected number of results",2, page.getResponseHeader().getTotal());
		List<String> objIds = page.getObjIdentifiers();
		assertEquals("unexpected number of objidentifiers",2, objIds.size());
		assertTrue("objidentifier missing",objIds.contains(testRecordId1));
		assertTrue("objidentifier missing",objIds.contains(testRecordId2));
	}

	@Test
	public void testPublicationsMultipleOpenaireIDs2() throws URISyntaxException, DocumentException {
		String testRecordId1 = "od________18::f055e1a3188aa57b454b1bfc0b882ed2";
		String testRecordId2 = "od________18::5ea480618e9ab9e7db827fa498422075";
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath);
		builder.addParameter("openairePublicationID", testRecordId1);
		builder.addParameter("openairePublicationID", testRecordId2);
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertEquals("unexpected number of results",2, page.getResponseHeader().getTotal());
		List<String> objIds = page.getObjIdentifiers();
		assertEquals("unexpected number of objidentifiers",2, objIds.size());
		assertTrue("objidentifier missing",objIds.contains(testRecordId1));
		assertTrue("objidentifier missing",objIds.contains(testRecordId2));
	}

	@Test
	public void testPublicationsUnexistingOpenaireID() throws URISyntaxException, DocumentException {
		String testRecordId = "foo::d1bb389d90e0a4393f7ea00c457a62b5";
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath);
		builder.addParameter("openairePublicationID", testRecordId);
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertEquals("unexpected number of results", 0, page.getResponseHeader().getTotal());
	}

	//TODO: Unignore the test when the path to the pid is fixed on the index side
	@Ignore
	@Test
	public void testPublicationsSingleDOI() throws URISyntaxException, DocumentException {
		String testRecordId = "dedup_wf_001::fc4c3a6c233f478586f5fb3259b25bc4";
		String doi = "10.1143/JPSJ.74.1954";
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath);
		builder.addParameter("doi", doi);
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertEquals("unexpected number of results",1, page.getResponseHeader().getTotal());
		List<String> objIds = page.getObjIdentifiers();
		assertEquals("unexpected number of objidentifiers",1, objIds.size());
		assertTrue("missing expected objidentifier", objIds.contains(testRecordId));
	}

	@Test
	public void testPublicationsMultipleDOIs1() throws URISyntaxException, DocumentException {
		String testRecordId1 = "dedup_wf_001::fc4c3a6c233f478586f5fb3259b25bc4";
		String testRecordId2 = "dedup_wf_001::eb22f16c808595b58c277ba95bc96275";
		String doi1 = "10.1143/JPSJ.74.1954";
		String doi2 = "10.1103/physrevlett.116.116401";
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath);
		builder.addParameter("doi", doi1 + "," + doi2);
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertTrue("unexpected number of results",page.getResponseHeader().getTotal() >= 2);
		List<String> objIds = page.getObjIdentifiers();
		assertEquals("unexpected number of objidentifiers",page.getResponseHeader().getTotal(), objIds.size());
		assertTrue("missing expected objidentifier",objIds.contains(testRecordId1));
		assertTrue("missing expected objidentifier",objIds.contains(testRecordId2));
	}

	@Test
	public void testPublicationsFromDate() throws URISyntaxException, DocumentException {
		String date = "2012-03-15";
		String expectedQuery = publicationsQuery + " and (resultdateofacceptance within \"2012-03-15 "+today+"\")";

		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath).addParameter("fromDateAccepted", date);
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertNotNull("null page",page);
		assertEquals("unexpected query", expectedQuery, page.getResponseHeader().getQuery());
	}

	@Test
	public void testPublicationsToDate() throws URISyntaxException, DocumentException {
		String date = "2013-03-15";
		String expectedQuery = publicationsQuery + " and (resultdateofacceptance within \"* 2013-03-15\")";

		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath).addParameter("toDateAccepted", date);
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		System.out.println(results.substring(0, 500));
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertNotNull("null page",page);
		assertEquals("unexpected query", expectedQuery, page.getResponseHeader().getQuery());
	}

	@Test
	public void testPublicationsByTitle() throws URISyntaxException, DocumentException {
		String title = "Enhanced Publications";
		String expectedQuery = publicationsQuery + " and (resulttitle = \"Enhanced\") and (resulttitle = \"Publications\")";
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath).addParameter("title", title);
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertNotNull("null page",page);
		assertEquals("unexpected query", expectedQuery, page.getResponseHeader().getQuery());
	}

	@Test
	public void testPublicationsByAuthor() throws URISyntaxException, DocumentException {
		String author = "bardi alessia manghi";
		String expectedQuery = publicationsQuery + " and (relperson = \"bardi\") and (relperson = \"alessia\") and (relperson = \"manghi\")";
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath).addParameter("author", author);
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertNotNull("null page",page);
		assertEquals("unexpected query", expectedQuery, page.getResponseHeader().getQuery());
	}


	@Test
	public void testPublicationsByAuthorId() throws URISyntaxException, DocumentException{
		String authorId = "od______2367::3fbd0b3533bd0e6089c1fe68b115f772";
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath).addParameter("openaireAuthorID", authorId);
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertNotNull("null page",page);
		checkException(results, "java.lang.IllegalArgumentException");
	}

	@Test
	public void testPublicationsByProviderId() throws URISyntaxException, DocumentException {
		// this is PUMA
		String providerId = "opendoar____::300891a62162b960cf02ce3827bb363c";
		String expectedQuery = publicationsQuery + " and (resulthostingdatasourceid exact \"opendoar____::300891a62162b960cf02ce3827bb363c\")";
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath).addParameter("openaireProviderID", providerId);
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertNotNull("null page",page);
		assertEquals("unexpected query", expectedQuery, page.getResponseHeader().getQuery());
	}

	@Test
	public void testPublicationsByMultipleProviderIds() throws URISyntaxException, DocumentException {
		// this is PUMA
		String providerId1 = "opendoar____::300891a62162b960cf02ce3827bb363c";
		String providerId2 = "opendoar____::300891a62162b960cf02ce3827bb363c";
		String expectedQuery = publicationsQuery + " and (resulthostingdatasourceid exact \"opendoar____::300891a62162b960cf02ce3827bb363c\") or (resulthostingdatasourceid exact \"opendoar____::300891a62162b960cf02ce3827bb363c\")";
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath).addParameter("openaireProviderID", providerId1 + "," + providerId2);
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertNotNull("null page",page);
		assertEquals("unexpected query", expectedQuery, page.getResponseHeader().getQuery());
	}

	@Test
	public void testPublicationsBy2ProviderId() throws URISyntaxException, DocumentException {
		// this is PUMA
		String providerId1 = "opendoar____::300891a62162b960cf02ce3827bb363c";
		// this is UTL Repository
		String providerId2 = "opendoar____::0c8ce55163055c4da50a81e0a273468c";
		 String expectedQuery = publicationsQuery + " and (resulthostingdatasourceid exact \"opendoar____::300891a62162b960cf02ce3827bb363c\") or (resulthostingdatasourceid exact \"opendoar____::0c8ce55163055c4da50a81e0a273468c\")";
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath).addParameter("openaireProviderID", providerId1)
				.addParameter("openaireProviderID", providerId2);
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertNotNull("null page",page);
		assertEquals("unexpected query", expectedQuery, page.getResponseHeader().getQuery());
	}

	@Test
	public void testPublicationsByProject() throws URISyntaxException, DocumentException {
		// <code>213153</code>
		// <acronym>BREAST CT</acronym>
		// <objIdentifier>corda_______::227de3026bb4ceb724f139437520a9ce</objIdentifier>
		URIBuilder builderFP7ProjectID = new URIBuilder(requestBaseURL).setPath(publicationsPath);
		builderFP7ProjectID.addParameter("FP7ProjectID", "213153");
		URI uri1 = builderFP7ProjectID.build();
		System.out.println(uri1);
		String resultsFP7ProjectID = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri1);
		OpenAireDocumentPage pageFP7ProjectID = new OpenAireDocumentPage(DocumentHelper.parseText(resultsFP7ProjectID));

		URIBuilder builderOAProjectID = new URIBuilder(requestBaseURL).setPath(publicationsPath);
		builderOAProjectID.addParameter("openaireProjectID", "corda_______::227de3026bb4ceb724f139437520a9ce");
		URI uri2 = builderOAProjectID.build();
		System.out.println(uri2);
		String resultsOAProjectID = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri2);
		OpenAireDocumentPage pageOAProjectID = new OpenAireDocumentPage(DocumentHelper.parseText(resultsOAProjectID));

		assertEquals(pageFP7ProjectID.getResponseHeader().getTotal(), pageOAProjectID.getResponseHeader().getTotal());
	}

	@Test
	public void testPublicationsWithProjects() throws URISyntaxException, DocumentException {
		String expectedQuery = publicationsQuery + " and (relprojectid = \"*\")";
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath).addParameter("hasProject", "true");
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertNotNull("null page",page);
		assertEquals("unexpected query", expectedQuery, page.getResponseHeader().getQuery());
	}

	@Test
	public void testPublicationsWithoutProjects() throws URISyntaxException, DocumentException {
		String expectedQuery = publicationsQuery + " not (relprojectid = \"*\")";
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath).addParameter("hasProject", "false");
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertNotNull("null page",page);
		assertEquals("unexpected query", expectedQuery, page.getResponseHeader().getQuery());
	}

	@Test
	public void testPublicationsOA() throws URISyntaxException, DocumentException {
		String expectedQuery = publicationsQuery + " and (resultbestaccessright exact \"Open Access\")";
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath).addParameter("OA", "true");
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertNotNull("null page",page);
		assertEquals("unexpected query", expectedQuery, page.getResponseHeader().getQuery());
	}

	@Test
	public void testPublicationsNonOA() throws URISyntaxException, DocumentException {
		String expectedQuery = publicationsQuery + " and (resultbestaccessright <> \"Open Access\")";
		URIBuilder builder = new URIBuilder(requestBaseURL).setPath(publicationsPath).addParameter("OA", "false");
		URI uri = builder.build();
		System.out.println(uri);
		String results = getApiClient().doRequest(EntityType.publication, ApiModel.openaire, uri);
		OpenAireDocumentPage page = new OpenAireDocumentPage(DocumentHelper.parseText(results));
		assertNotNull("null page",page);
		assertEquals("unexpected query", expectedQuery, page.getResponseHeader().getQuery());
	}
}
