package eu.dnetlib.openaire.directindex.api;

import static org.mockito.Mockito.CALLS_REAL_METHODS;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.withSettings;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.runners.MockitoJUnitRunner;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.gson.Gson;

import eu.dnetlib.openaire.directindex.objects.DatasourceEntry;

/**
 * Created by Alessia Bardi on 26/05/2017.
 *
 * @author Alessia Bardi
 */
@RunWith(MockitoJUnitRunner.class)
public class OpenAIRESubmitterUtilsTest {

	private OpenAIRESubmitterUtils utils;

	final String fullProject = "info:eu-repo/grantAgreement/EC/FP7/244909/EU/Making Capabilities Work/WorkAble";
	final String minimalProject = "info:eu-repo/grantAgreement/EC/FP7/244909///WorkAble";
	final String onlyId = "info:eu-repo/grantAgreement/EC/FP7/244909/";
	final String onlyTitle = "info:eu-repo/grantAgreement/EC/FP7/244909/EU/Making Capabilities Work";
	final String escapedId = "info:eu-repo/grantAgreement/RCUK//NE%2FL003066%2F1/";
	final String heProjectFromZenodo =
		"info:eu-repo/grantAgreement/EC/Horizon Europe Framework Programme - HORIZON-CSA\\HORIZON Action Grant Budget-Based/101058527/";
	final String chistera = "info:eu-repo/grantAgreement/CHIST-ERA//CHIST-ERA-19-XAI-002/";

	final String intelcomp = "info:eu-repo/grantAgreement/EC/H2020/101004870//A Competitive Intelligence Cloud%2FHPC Platform for AI-based STI Policy Making/IntelComp";

	@Before
	public void setup() {
		utils = mock(OpenAIRESubmitterUtils.class, withSettings().defaultAnswer(CALLS_REAL_METHODS));
		doReturn(Lists.newArrayList("dh-ch", "dariah", "bar", "x")).when(utils).translateZenodoCommunity("https://zenodo.org/communities/dimpo");
		doReturn(Lists.newArrayList()).when(utils).translateZenodoCommunity("https://zenodo.org/communities/dumbo");

	}

	@Test
	public void testCalculateProjectInfoCHISTERA() {
		final Map<String, String> project = utils.calculateProjectInfo(chistera);
		print(project);
		Assert.assertEquals("CHIST-ERA-19-XAI-002", project.get("code"));
		Assert.assertEquals("chistera____::289ec73ce0e9ece89a0cbdf74c445cd8", project.get("id"));

	}

	@Test
	public void testCalculateProjectInfoZenodo() {
		final Map<String, String> project = utils.calculateProjectInfo(onlyId);
		print(project);
		Assert.assertEquals("244909", project.get("code"));

	}

	@Test
	public void testCalculateProjectInfoZenodoHE() {
		final Map<String, String> project = utils.calculateProjectInfo(heProjectFromZenodo);
		print(project);
		Assert.assertEquals("101058527", project.get("code"));
		Assert.assertEquals("corda_____he::eab43774d3762e87f5e66030c6e01d2b", project.get("id"));
	}

	@Test
	public void testCalculateProjectInfoZenodoIntelComp() {
		final Map<String, String> project = utils.calculateProjectInfo(intelcomp);
		print(project);
		Assert.assertEquals("101004870", project.get("code"));
		Assert.assertEquals("corda__h2020::8264fd9d5f5d59b1b76fc618f3a8af24", project.get("id"));
		Assert.assertEquals("IntelComp", project.get("acronym"));

	}

	@Test
	public void testCalculateProjectInfoEscaped() {
		final Map<String, String> project = utils.calculateProjectInfo(escapedId);
		print(project);
		Assert.assertEquals("NE/L003066/1", project.get("code"));
	}

	@Test
	public void testCalculateProjectInfoFull() {
		final Map<String, String> project = utils.calculateProjectInfo(fullProject);
		print(project);
		Assert.assertEquals(10, project.size());
		for (final String k : project.keySet()) {
			Assert.assertNotNull(project.get(k));
			Assert.assertNotSame("", project.get(k));
		}
	}

	@Test
	public void testCalculateProjectInfoOnlyId() {
		final Map<String, String> project = utils.calculateProjectInfo(onlyId);
		print(project);
		Assert.assertEquals("244909", project.get("code"));
	}

	@Test
	public void testCalculateProjectInfoMinimalAcro() {
		final Map<String, String> project = utils.calculateProjectInfo(minimalProject);
		print(project);
		Assert.assertEquals("244909", project.get("code"));
		Assert.assertEquals("WorkAble", project.get("acronym"));
	}

	@Test
	public void testCalculateProjectInfoOnlyTitle() {
		final Map<String, String> project = utils.calculateProjectInfo(onlyTitle);
		print(project);
		Assert.assertEquals("244909", project.get("code"));
		Assert.assertEquals("Making Capabilities Work", project.get("title"));
	}

	@Test
	public void testJerusalem() {
		final String s =
			"info:eu-repo/grantAgreement/EC/FP7/337895/EU/Opening Jerusalem Archives: For a connected History of ‘Citadinité’ in the Holy City (1840-1940)/OPEN-JERUSALEM";
		final Map<String, String> project = utils.calculateProjectInfo(s);
		print(project);
		Assert.assertEquals("337895", project.get("code"));
		Assert.assertEquals("Opening Jerusalem Archives: For a connected History of ‘Citadinité’ in the Holy City (1840-1940)", project.get("title"));
		Assert.assertEquals("OPEN-JERUSALEM", project.get("acronym"));
	}

	private void print(final Map<String, String> map) {
		for (final Entry e : map.entrySet()) {
			System.out.println(e.getKey() + " = " + e.getValue());
		}
	}

	@Test
	public void testContext() {
		final List<String> zenodoCommunities = new ArrayList<>();
		zenodoCommunities.add("https://zenodo.org/communities/dimpo");
		zenodoCommunities.add("https://zenodo.org/communities/dumbo");
		final Map<String, String> labelMap = Maps.newHashMap();
		labelMap.put("dariah", "DARIAH");
		labelMap.put("dh-ch", "DH-CH");
		labelMap.put("foo", "FOO");
		labelMap.put("bar", "");

		final List<OpenAIRESubmitterUtils.ContextInfo> tmp = utils.processContexts(zenodoCommunities, labelMap);
		Assert.assertEquals(2, tmp.size());

		Assert.assertTrue(tmp.get(0).getId().equals("dh-ch") || tmp.get(1).getId().equalsIgnoreCase("dh-ch"));
		Assert.assertTrue(tmp.get(0).getId().equals("dariah") || tmp.get(1).getId().equalsIgnoreCase("dariah"));
	}

	@Test
	public void testWrongH2020() {
		final String link = "info:eu-repo/grantAgreement/EC/Horizon 2020 Framework Programme - Research and Innovation action/881825/";
		final Map<String, String> info = utils.calculateProjectInfo(link);
		System.out.println(info);
		Assert.assertEquals("H2020", info.get("fundingName"));
	}

	@Test
	@Ignore
	public void testFindDatasource_01() {
		final OpenAIRESubmitterUtils utils = new OpenAIRESubmitterUtils("", "https://services.openaire.eu/openaire/ds/");
		final DatasourceEntry res = utils.findDatasource("opendoar____::1112");
		System.err.println(new Gson().toJson(res));
	}

	@Test
	@Ignore
	public void testFindDatasourceCrossref() {
		final OpenAIRESubmitterUtils utils = new OpenAIRESubmitterUtils("", "https://services.openaire.eu/openaire/ds/");
		final DatasourceEntry res = utils.findDatasource("openaire____::crossref");
		System.err.println(new Gson().toJson(res));
	}

}
