package eu.dnetlib.resolver;

import eu.dnetlib.dli.resolver.model.CompletionStatus;
import eu.dnetlib.dli.resolver.model.DLIObjectProvenance;
import eu.dnetlib.dli.resolver.model.DLIObjectRelation;
import eu.dnetlib.dli.resolver.model.DLIResolvedObject;
import eu.dnetlib.dli.resolver.model.serializer.DLIResolverSerializer;
import eu.dnetlib.pid.resolver.model.ObjectType;
import eu.dnetlib.pid.resolver.model.PID;
import eu.dnetlib.resolver.parser.DMFResolverParser;
import eu.dnetlib.resolver.parser.PMFResolverParser;
import org.apache.commons.io.IOUtils;
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.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.Arrays;

/**
 * Created by sandro on 10/4/16.
 */
@Ignore
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { ConfigurationTestConfig.class})
public class DLISerializerTest extends DLIAbstractTest {

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

	@Autowired
    private DLIResolverSerializer serializer;

	@Test
	public void testSerializeScholix() {
        DLIResolvedObject scholixMock = createScholixMock();
        log.debug(serializer.serializeToXML(scholixMock));
	}

	@Test
	public void testSerializePMF() throws IOException {
		final InputStream recordStream = this.getClass().getResourceAsStream("/eu/dnetlib/dli/parser/InputPMF.xml");

		final DLIResolvedObject object = createPMFMock();

		object.setCompletionStatus(CompletionStatus.complete.toString());

		final DLIObjectProvenance provencance = new DLIObjectProvenance();
		provencance.setDatasource("Provencance1");
		provencance.setDatasourceId("pid1");
		provencance.setProvisionMode("resolved");
		provencance.setCompletionStatus("complete");
		object.getDatasourceProvenance().add(provencance);



		object.setPid("MOCKPID");
		object.setPidType("MOCKPIDType");
		final String replacingXML = serializer.serializeReplacingXML(IOUtils.toString(recordStream), object);

		log.debug(replacingXML);
	}


	@Test
	public void testDeserializeNullPointer() throws IOException {
		final InputStream recordStream = this.getClass().getResourceAsStream("/eu/dnetlib/dli/transform/input2.json");


		DLIResolvedObject.fromJson(IOUtils.toString(recordStream));
	}

	@Test
	public void testSerializeDMF() throws Exception {
		final DLIResolvedObject object = createDMFMock();
		final InputStream recordStream = this.getClass().getResourceAsStream("/eu/dnetlib/dli/parser/InputRecordDMF.xml");

		final String replacingXML = serializer.serializeReplacingXML(IOUtils.toString(recordStream), object);

		log.debug(replacingXML);

	}


	@Test
	public void testSerializeFromJson() throws Exception {
		final InputStream recordStream = this.getClass().getResourceAsStream("/eu/dnetlib/dli/transform/resolvedObject.json");


		final DLIResolvedObject resolvedObject = DLIResolvedObject.fromJson(IOUtils.toString(recordStream));
		Assert.assertEquals(resolvedObject.getType(), ObjectType.dataset);
		final String recordTemplate =
				"<root xmlns:oaf=\"http://namespace.dnet.eu/oaf\" xmlns:dri=\"http://www.driver-repository.eu/namespace/dri\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\">%s</root>";
		final String xml = serializer.serializeToXML(resolvedObject);

		final String inputRecord = String.format(recordTemplate, xml);

		final InputStream xsltAsStream = getClass().getResourceAsStream("/eu/dnetlib/resolver/xslt/transformResolvedRecord.xsl");

		final InputStream xmlAsStream = getClass().getResourceAsStream("/eu/dnetlib/dli/transform/inputResolved.xml");

		final TransformerFactory factory = TransformerFactory.newInstance();
		factory.newTransformer();
		final StreamSource xsltSource = new StreamSource(xsltAsStream);

		final Transformer transformer = factory.newTransformer(xsltSource);
		transformer.setOutputProperty(OutputKeys.INDENT, "yes");
		final StringWriter output = new StringWriter();
		transformer.transform(new StreamSource(new ByteArrayInputStream(inputRecord.getBytes())), new StreamResult(output));
		final String record = output.toString();
		System.out.println("record = " + record);
	}

	private DLIResolvedObject createPMFMock() throws IOException {
		final InputStream resource = getClass().getResourceAsStream("/eu/dnetlib/dli/parser/InputPMF.xml");
		String xml = IOUtils.toString(resource);

		PMFResolverParser parser = new PMFResolverParser();
		return parser.parseObject(xml);
	}

	private DLIResolvedObject createDMFMock() throws Exception {
		final InputStream xsltAsStream = this.getClass().getResourceAsStream("/eu/dnetlib/dli/transform/oai_datacite_transform.xsl");

		final TransformerFactory factory = TransformerFactory.newInstance();
		factory.newTransformer();
		final StreamSource xsltSource = new StreamSource(xsltAsStream);
		final InputStream recordStream = this.getClass().getResourceAsStream("/eu/dnetlib/dli/parser/InputRecordDMF.xml");
		final Transformer transformer = factory.newTransformer(xsltSource);
		transformer.setOutputProperty(OutputKeys.INDENT, "yes");
		final StringWriter output = new StringWriter();
		transformer.transform(new StreamSource(recordStream), new StreamResult(output));
		final String record = output.toString();
		final DMFResolverParser parser = new DMFResolverParser();
		return parser.parseObject(record);

	}

	private DLIResolvedObject createScholixMock() {

		final DLIResolvedObject mock = new DLIResolvedObject();
		mock.setPid("mock");
		mock.setPidType("mockType");
		final DLIObjectProvenance provenance = new DLIObjectProvenance();
		provenance.setDatasource("Mock Datasource");
        provenance.setDatasourceId("Mock Id");
        mock.setDatasourceProvenance(Arrays.asList(provenance));
		final DLIObjectRelation relation = new DLIObjectRelation();
		relation.setTargetPID(new PID("mockTarget", "mockType"));
		relation.setTargetType(ObjectType.unknown);
        relation.setRelationSemantics("unknown");
        relation.setRelationProvenance(Arrays.asList(provenance));


        final DLIObjectRelation relation1 = new DLIObjectRelation();
        relation1.setTargetPID(new PID("mockTarget", "mockType"));
        relation1.setTargetType(ObjectType.unknown);
        relation1.setRelationSemantics("unknown");
        relation1.setRelationProvenance(Arrays.asList(provenance));



		mock.setRelations(Arrays.asList(relation, relation1));
		return mock;
	}

}
