package eu.dnetlib.resolver;

import com.google.gson.Gson;
import eu.dnetlib.dli.resolver.model.*;
import eu.dnetlib.dli.resolver.model.serializer.ResolverSerializer;
import eu.dnetlib.resolver.parser.DMFResolverParser;
import eu.dnetlib.resolver.parser.PMFResolverParser;
import eu.dnetlib.resolver.store.ConfigurationResolverStoreTestConfig;
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.
 */
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {ConfigurationTestConfig.class, ConfigurationResolverStoreTestConfig.class})
public class DLISerializerTest {

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

	@Autowired
	private ResolverSerializer serializer;

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

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

		final ResolvedObject object = createPMFMock();

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

		final ObjectProvenance provencance = new ObjectProvenance();
		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 testSerializeDMF() throws Exception {
		final ResolvedObject 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 Gson gson = new Gson();
		final ResolvedObject resolvedObject = gson.fromJson(IOUtils.toString(recordStream), ResolvedObject.class);
		Assert.assertEquals(resolvedObject.getType(), ObjectType.publication);
		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);


		System.out.println("xml = " + xml);

		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);
	}


	@Test
	public void testEscapingXML() {


	}

	private ResolvedObject 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 ResolvedObject 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 ResolvedObject createScholixMock() {

		final ResolvedObject mock = new ResolvedObject();
		mock.setPid("mock");
		mock.setPidType("mockType");
		final ObjectProvenance provenance = new ObjectProvenance();
		provenance.setDatasource("Mock Datasource");
        provenance.setDatasourceId("Mock Id");
        mock.setDatasourceProvenance(Arrays.asList(provenance));
		final ObjectRelation relation = new ObjectRelation();
		relation.setTargetPID(new PID("mockTarget", "mockType"));
		relation.setTargetType(ObjectType.unknown);
        relation.setRelationSemantics("unknown");
        relation.setRelationProvenance(Arrays.asList(provenance));
		mock.setRelations(Arrays.asList(relation));
		return mock;
	}

}
