package eu.dnetlib.data.mapreduce.dedup;

import java.util.List;
import java.util.UUID;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import eu.dnetlib.data.proto.DatasetProtos.Dataset;
import eu.dnetlib.data.proto.FieldTypeProtos.StructuredProperty;
import eu.dnetlib.data.proto.KindProtos.Kind;
import eu.dnetlib.data.proto.DNGFProtos.DNGF;
import eu.dnetlib.data.proto.DNGFProtos.DNGFEntity;
import eu.dnetlib.data.proto.DNGFProtos.DNGFEntity.Builder;
import eu.dnetlib.data.proto.PublicationProtos.Publication;
import eu.dnetlib.data.proto.TypeProtos.Type;
import eu.dnetlib.data.transform.DNGFEntityMerger;
import org.junit.Before;
import org.junit.Test;

import static eu.dnetlib.data.graph.model.DNGFUtils.*;

public class DNGFMergeTest {

	private List<DNGF> oafList;

	private DNGFEntityMerger merger;

	@Before
	public void setUp() throws Exception {

		merger = new DNGFEntityMerger();
		oafList = Lists.newArrayList();
		oafList.add(getDNGF("0.1").setEntity(
				getEntity("id_1", null, "pid_1").setPublication(
						Publication.newBuilder().setMetadata(
                                Publication.Metadata.newBuilder().setDateofacceptance(sf("2012-01-01"))
                                        .addTitle(sp("vvvv Title", "main title", "dnet:dataCite_title"))
                                        .setResulttype(simpleQualifier("publication", "dnet:result_typologies"))))).build());
        oafList.add(getDNGF("0.1").setEntity(
				getEntity("id_2", "originalId_2", "pid_2").setPublication(
						Publication.newBuilder().setMetadata(
                                Publication.Metadata.newBuilder().setDateofacceptance(sf(""))
                                        .addTitle(sp("aaaa Title", "main title", "dnet:dataCite_title"))
                                        .setResulttype(simpleQualifier("publication", "dnet:result_typologies"))))).build());
        oafList.add(getDNGF("0.2").setEntity(
				getEntity("id_3", "originalId_2", "pid_2").setPublication(
						Publication.newBuilder().setMetadata(
                                Publication.Metadata.newBuilder().addTitle(sp("cccc Title", "sub title", "dnet:dataCite_title"))
                                        .setResulttype(simpleQualifier("publication", "dnet:result_typologies"))))).build());

		oafList.add(getDNGF("0.3").setEntity(
				getEntity("id_$", null, "pid_3").setPublication(
						Publication.newBuilder().setMetadata(
                                Publication.Metadata.newBuilder().setPublisher(sf("AMER CHEMICAL SOCXXXXXXXXXXXXXXXXX"))
                                        .setResulttype(simpleQualifier("publication", "dnet:result_typologies"))))).build());
        oafList.add(getDNGF("0.5").setEntity(
				getEntity("id_5", null, null).setDataset(
						Dataset.newBuilder().setMetadata(
                                Dataset.Metadata.newBuilder().addTitle(sp("hhhh title", "main title", "dnet:dataCite_title"))
                                        .setPublisher(sf("AMER CHEMICAL SOC X"))
                                        .setResulttype(simpleQualifier("publication", "dnet:result_typologies")).setStoragedate(sf("2012-11-18"))
                                        .setLanguage(simpleQualifier("eng", "dnet:languages")).addDescription(sf("original description")))))
                .build());
		oafList.add(getDNGF("0.6").setEntity(
				getEntity("id_6", null, "pid_6").setPublication(
						Publication.newBuilder().setMetadata(
                                Publication.Metadata.newBuilder().setResulttype(simpleQualifier("publication", "dnet:result_typologies"))
                                        .addDescription(sf("new description"))))).build());
    }

	@Test
	public void test_merge() {

		final DNGF.Builder builder = DNGF.newBuilder();

		for (final DNGF oaf : oafList) {
			builder.mergeFrom(oaf);
		}

		final Publication.Metadata.Builder metadata = builder.getEntityBuilder().getPublicationBuilder().getMetadataBuilder();
		final Iterable<StructuredProperty> filter = Iterables.filter(metadata.getTitleList(), new Predicate<StructuredProperty>() {

			@Override
			public boolean apply(final StructuredProperty sp) {
				return (sp.getQualifier() != null) && sp.getQualifier().getClassname().equals("main title");
			}
		});

		final StructuredProperty last = Iterables.getLast(filter);

		metadata.clearTitle().addAllTitle(Lists.newArrayList(last));

		System.out.println(builder.build().toString());
	}

	@Test
	public void test_merger() {

		final DNGF merge = merger.mergeEntities(null, "id", oafList).build();

		System.out.println(merge.toString());
	}

	// @Test
	// public void test_sort() {
	// Queue<Publication> q = new PriorityQueue<Publication>(3, DedupReducer.cmp);
	// for (DNGF oaf : oafList) {
	// q.add(oaf.getEntity().getPublication());
	// }
	//
	// while (!q.isEmpty()) {
	// Publication r = q.remove();
	// List<StructuredProperty> titles = r.getMetadata().getTitleList();
	// if (!titles.isEmpty()) {
	// System.out.println(titles.get(0).getValue());
	// }
	// }
	// }

	private DNGF.Builder getDNGF(final String trust) {
        return DNGF.newBuilder().setKind(Kind.entity).setDataInfo(di(trust)).setLastupdatetimestamp(System.currentTimeMillis());
    }

	private DNGFEntity.Builder getEntity(final String id, final String originalId, final String pid) {
		final Builder entity =
				DNGFEntity.newBuilder().setType(Type.publication).setId(id).addOriginalId(originalId != null ? originalId : UUID.randomUUID().toString());

		if (pid != null) {
            entity.addPid(sp(pid, "class", "scheme"));
        }

		return entity;
	}

}
