package eu.dnetlib.resolver;

import com.googlecode.protobuf.format.JsonFormat;
import eu.dnetlib.data.collector.plugins.datacite.DataciteParser;
import eu.dnetlib.data.proto.dli.ScholixObjectProtos;
import eu.dnetlib.data.transform.xml.AbstractDNetXsltFunctions;
import eu.dnetlib.dli.DLIUtils;
import eu.dnetlib.dli.resolver.*;
import eu.dnetlib.dli.resolver.model.CompletionStatus;
import eu.dnetlib.dli.resolver.model.DLIObjectProvenance;
import eu.dnetlib.dli.resolver.model.DLIResolvedObject;
import eu.dnetlib.dli.resolver.model.ObjectProvisionMode;
import eu.dnetlib.dli.resolver.model.serializer.DLIResolverSerializer;
import eu.dnetlib.pid.resolver.AbstractPIDResolver;
import eu.dnetlib.resolver.parser.DMFResolverParser;
import eu.dnetlib.resolver.parser.PMFResolverParser;
import eu.dnetlib.resolver.parser.ScholixResolverParser;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;

import java.io.IOException;
import java.io.InputStream;
import java.net.URISyntaxException;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.Arrays;

/**
 * Created by sandro on 9/12/16.
 */


//@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration(classes = { ConfigurationTestConfig.class})
@Ignore
public class DLIParserTest extends  DLIAbstractTest{

	private static final Log log = LogFactory.getLog(DLIParserTest.class);

	@Autowired
    private DLIResolverSerializer serializer;

	@Test
	public void testDMFParser() throws IOException {
		final InputStream resourceAsStream = getClass().getResourceAsStream("/eu/dnetlib/dli/transform/huge.xml");
		String str = IOUtils.toString(resourceAsStream);
		DMFResolverParser parser = new DMFResolverParser();
        DLIResolvedObject object = parser.parseObject(str);
        Assert.assertNotNull(object);
		Assert.assertNotNull(object.getTitles());
		Assert.assertNotNull(object.getDescription());
		Assert.assertNotNull(object.getType());
		System.out.println(object);
//		object.setTitles(Arrays.asList("TITOLO 1", "TITOLO 2"));
//		Assert.assertEquals(CompletionStatus.complete.toString(), object.getCompletionStatus());
//        DLIResolvedObject nullObject = parser.parseObject(IOUtils.toString(getClass().getResourceAsStream("/eu/dnetlib/dli/parser/InputRecordScholix.xml")));
//        Assert.assertNull(nullObject);
//		nullObject = parser.parseObject(IOUtils.toString(getClass().getResourceAsStream("/eu/dnetlib/dli/parser/InputPMFRecord.xml")));
//		Assert.assertNull(nullObject);

	}



	@Test
    public void testDOI(){
	    final String url="https://ssl.fao.org/glisapi/v1/pgrfas?doi=5gg0w";

	    DLIUtils.isValidDoi(url);
    }


	@Test
	public void testResolvedDate() throws IOException {
		final InputStream resourceAsStream = getClass().getResourceAsStream("/eu/dnetlib/dli/parser/InputPMF.xml");
		String str = IOUtils.toString(resourceAsStream);

		PMFResolverParser parser = new PMFResolverParser();
        DLIResolvedObject object = parser.parseObject(str);
        Assert.assertNotNull(object.getResolvedDate());
	}


	@Test
	public void testDataciteParser() throws Exception {

		final InputStream resourceAsStream = getClass().getResourceAsStream("/eu/dnetlib/dli/parser/InputRecordOpenaire.xml");
		String str = IOUtils.toString(resourceAsStream);
		DMFResolverParser parser = new DMFResolverParser();
        DLIResolvedObject object = parser.parseObject(str);
        System.out.println(object.getType());
		object.getRelations().forEach(it -> System.out.println(it.getTargetPID()));
		Assert.assertTrue(object.getCompletionStatus().equals("complete"));
		System.out.println("object = " + object);

		final String replacingXML = serializer.serializeReplacingXML(str, object);

		log.debug(replacingXML);



	}

	@Test
	public void testScholixParser() throws IOException, URISyntaxException {
		final InputStream resourceAsStream = getClass().getResourceAsStream("/eu/dnetlib/dli/parser/ieda.xml");

		String str = IOUtils.toString(resourceAsStream);
		ScholixResolverParser parser = new ScholixResolverParser();
        DLIResolvedObject object = parser.parseObject(str);

        final ScholixObjectProtos.Scholix.Builder scholix = ScholixObjectProtos.Scholix.newBuilder();

        scholix.addLinkproviderBuilder()
                .setName(object.getDatasourceProvenance().get(0).getDatasource())
                .addIdentifiersBuilder()
                .setIdentifier(object.getDatasourceProvenance().get(0).getDatasourceId())
                .setSchema("dnetIdentifier");



        scholix.setRelationship(ScholixObjectProtos.ScholixRelationship.newBuilder()
                .setName(object.getRelations().get(0).getRelationSemantics())
                .setInverse(object.getRelations().get(0).getInverseRelation())
                .setSchema("datacite")
                .build());
        final CrossRefParserJSON parserJSON = new CrossRefParserJSON();
        DLIResolvedObject dli_source = parserJSON.parseRecord(IOUtils.toString(new URL("https://api.crossref.org/works/10.1002/2016JG003630").openStream()));
        DLIResolvedObject dli_target = DataciteResolver.parseResponse(AbstractPIDResolver.requestURL("http://search.datacite.org/api?wt=json&q=doi:10.6073/pasta/6038bd9745347610df8a51c92ca0e452"));
        final ScholixObjectProtos.ScholixResource source = generateResource(dli_source);
        final ScholixObjectProtos.ScholixResource target = generateResource(dli_target);
        scholix.setSource(source);
        scholix.setTarget(target);
        scholix.setPublicationDate(LocalDateTime.now().toString());
        System.out.println(JsonFormat.printToString(scholix.build()));

        System.out.println(generateIdentifier(dli_source, dli_target));


	}

    private String generateIdentifier(final DLIResolvedObject source, DLIResolvedObject target) {

        return AbstractDNetXsltFunctions.md5(String.format("%s::%s", source.getPid().toLowerCase().trim(), target.getPid().toLowerCase().trim()));

    }

    private ScholixObjectProtos.ScholixResource generateResource(DLIResolvedObject result) {
        final ScholixObjectProtos.ScholixResource.Builder builder = ScholixObjectProtos.ScholixResource.newBuilder();
        if (result.getDatasourceProvenance() != null)
            result.getDatasourceProvenance().forEach(
                    objectProvenance -> {
                        builder.addCollectedFrom(ScholixObjectProtos.ScholixCollectedFrom.newBuilder()
                                .setProvisionMode(((DLIObjectProvenance) objectProvenance).getProvisionMode())
                                .setCompletionStatus(((DLIObjectProvenance) objectProvenance).getCompletionStatus())
                                .setProvider(ScholixObjectProtos.ScholixEntityId.newBuilder()
                                        .setName(objectProvenance.getDatasource())
                                        .addIdentifiers(ScholixObjectProtos.ScholixIdentifier.newBuilder().setIdentifier(objectProvenance.getDatasourceId())
                                                .setSchema("dnetIdentifier").build())
                                        .build()));
                        if (StringUtils.isNotEmpty(((DLIObjectProvenance) objectProvenance).getPublisher())) {
                            builder.addPublisher(ScholixObjectProtos.ScholixEntityId.newBuilder()
                                    .setName(((DLIObjectProvenance) objectProvenance).getPublisher())
                                    .build());
                        }

                    });
        builder.addIdentifier(ScholixObjectProtos.ScholixIdentifier.newBuilder().
                setIdentifier(result.getPid())
                .setSchema(result.getPidType())
                .build());
        builder.setObjectType(result.getType().toString());
        if (result.getTitles() != null && result.getTitles().size() > 0)
            builder.setTitle(result.getTitles().get(0));
        if (result.getAuthors() != null)
            result.getAuthors().forEach(author -> builder.addCreator(
                    ScholixObjectProtos.ScholixEntityId.newBuilder()
                            .setName(author)
                            .build()));
        if (StringUtils.isNotBlank(result.getDate())) {
            builder.setPublicationDate(result.getDate());
        }

        String tp = null;

        switch (result.getType()) {
            case dataset:
                tp = "60";
                break;
            case unknown:
                tp = "70";
                break;
            case publication:
                tp = "50";
                break;
        }
        builder.setDnetIdentifier(tp + "|dnet________::" + result.getIdentifier());
        return builder.build();
    }

	@Test
	public void testScholixCompleteParser() throws IOException {
		final InputStream resourceAsStream = getClass().getResourceAsStream("/eu/dnetlib/dli/parser/InputRecordScholix.xml");

		String str = IOUtils.toString(resourceAsStream);
		ScholixResolverParser parser = new ScholixResolverParser();
        DLIResolvedObject object = parser.parseObject(str);

		log.debug("object = " + object);

		Assert.assertNotNull(object);
		log.debug("object.getCompletionStatus() = " + object.getCompletionStatus());

//		Assert.assertTrue(object.getCompletionStatus().equals(CompletionStatus.complete.toString()));
//
//		Assert.assertNotNull(object.getDate());
//		Assert.assertNotNull(object.getTitles());
//		Assert.assertTrue(object.getTitles().size() == 1);
//
//		Assert.assertNotNull(object.getDatasourceProvenance());
//		Assert.assertTrue(object.getDatasourceProvenance().size() == 1);
//		Assert.assertNotNull(object.getDatasourceProvenance().get(0).getPublisher());
//		Assert.assertNotNull(object.getDatasourceProvenance().get(0).getPublisherId());
//
//
//		Assert.assertNotNull(object.getRelations());
//
//		Assert.assertTrue(object.getRelations().size() == 1);
//
//		Assert.assertNotNull(object.getRelations().get(0).getTargetPID().getId());
//		Assert.assertNotNull(object.getRelations().get(0).getTargetPID().getType());
//
//
//		DLIResolvedObject nullObject = parser.parseObject(IOUtils.toString(getClass().getResourceAsStream("/eu/dnetlib/dli/parser/InputRecordDMF.xml")));
//		Assert.assertNull(nullObject);
//		nullObject = parser.parseObject(IOUtils.toString(getClass().getResourceAsStream("/eu/dnetlib/dli/parser/InputPMFRecord.xml")));
//		Assert.assertNull(nullObject);

	}


	@Test
	public void testPMFParser() throws Exception {
		final InputStream resource = getClass().getResourceAsStream("/eu/dnetlib/dli/parser/InputPMF.xml");
		String xml = IOUtils.toString(resource);

		PMFResolverParser parser = new PMFResolverParser();
        final DLIResolvedObject resolvedObject = parser.parseObject(xml);
        Assert.assertNotNull(resolvedObject);

        Assert.assertNotNull(resolvedObject.getPidType());
		log.debug("resolvedObject = " + resolvedObject);

		Assert.assertNotNull(resolvedObject.getRelations());
		resolvedObject.getRelations().forEach(it -> Assert.assertNotNull(it));

        DLIResolvedObject nullObject = parser.parseObject(IOUtils.toString(getClass().getResourceAsStream("/eu/dnetlib/dli/parser/InputRecordScholix.xml")));
        Assert.assertNull(nullObject);
		nullObject = parser.parseObject(IOUtils.toString(getClass().getResourceAsStream("/eu/dnetlib/dli/parser/InputRecordDMF.xml")));
		Assert.assertNull(nullObject);
	}

	@Test
	public void testOpenAIREParser() throws Exception {

		final InputStream resource = getClass().getResourceAsStream("/eu/dnetlib/dli/parser/InputRecordOpenaire.xml");

		final String record = IOUtils.toString(resource);

		final OpenAireParser parser = new OpenAireParser();
        final DLIResolvedObject object = parser.parseObject(record);
        object.setPid("od_______908::ff0270cae25acd9367ef26a53ee5e4a3");
		object.setPidType("openaire");

        final DLIObjectProvenance provenance = new DLIObjectProvenance();
        provenance.setCompletionStatus(CompletionStatus.complete.toString());
		provenance.setDatasourceId("dli::r3d100010778");
		provenance.setDatasource("NCBI Nucleotide");
		provenance.setProvisionMode(ObjectProvisionMode.resolved.toString());
		object.setDatasourceProvenance(Arrays.asList(provenance));

		log.debug(object);

	}

	@Test
	public void testProteinParser() throws IOException {
		final NCBINResolver resolver = new NCBINResolver();
		resolver.setNCBINParser(new NCBINParser());
        final DLIResolvedObject p02768 = resolver.resolve("U36380", "protein");

		log.debug(p02768.getDescription());
		Assert.assertNotNull(p02768);
		Assert.assertNotNull(p02768.getDescription());

		log.debug("p02768 = " + p02768);

	}









}
