package eu.dnetlib.data.mapreduce.dedup;

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

import org.junit.Before;
import org.junit.Test;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;

import eu.dnetlib.data.mapreduce.hbase.dedup.OafEntityMerger;
import eu.dnetlib.data.mapreduce.hbase.dedup.config.DedupConfigLoader;
import eu.dnetlib.data.proto.DataInfoProtos.DataInfo;
import eu.dnetlib.data.proto.KindProtos.Kind;
import eu.dnetlib.data.proto.OafProtos.Oaf;
import eu.dnetlib.data.proto.OafProtos.OafEntity;
import eu.dnetlib.data.proto.QualifierProtos.Qualifier;
import eu.dnetlib.data.proto.ResultProtos.Result;
import eu.dnetlib.data.proto.StructuredPropertyProtos.StructuredProperty;
import eu.dnetlib.data.proto.TypeProtos.Type;

public class OafMergeTest {

	private final String config = "dedup.conf { threshold = 0.99, run = '001', entity.type = result, order.field = title, rootbuilder = [result,personResult,resultProject,resultOrganization,resultResult] }";

	private List<Oaf> oafList;

	private OafEntityMerger merger;

	@Before
	public void setUp() throws Exception {

		merger = new OafEntityMerger(DedupConfigLoader.load(config));
		oafList = Lists.newArrayList();
		oafList.add(getOaf("0.1").setEntity(
				getEntity("id_1").setResult(
						Result.newBuilder().setMetadata(
								Result.Metadata
										.newBuilder()
										.addTitle(
												StructuredProperty.newBuilder().setValue("vvvv Title")
														.setQualifier(getQualifier("main title", "dnet:dataCite_title")))
										.setResulttype(getQualifier("publication", "dnet:result_typologies"))))).build());
		oafList.add(getOaf("0.1").setEntity(
				getEntity("id_2").setResult(
						Result.newBuilder().setMetadata(
								Result.Metadata
										.newBuilder()
										.addTitle(
												StructuredProperty.newBuilder().setValue("aaaa Title")
														.setQualifier(getQualifier("main title", "dnet:dataCite_title")))
										.setResulttype(getQualifier("publication", "dnet:result_typologies"))))).build());
		oafList.add(getOaf("0.2").setEntity(
				getEntity("id_3").setResult(
						Result.newBuilder().setMetadata(
								Result.Metadata
										.newBuilder()
										.addTitle(
												StructuredProperty.newBuilder().setValue("cccc Title")
														.setQualifier(getQualifier("sub title", "dnet:dataCite_title")))
										.setResulttype(getQualifier("publication", "dnet:result_typologies"))))).build());

		oafList.add(getOaf("0.3").setEntity(
				getEntity("id_$").setResult(
						Result.newBuilder().setMetadata(
								Result.Metadata.newBuilder().setPublisher("AMER CHEMICAL SOCXXXXXXXXXXXXXXXXX")
										.setResulttype(getQualifier("publication", "dnet:result_typologies"))))).build());
		oafList.add(getOaf("0.5").setEntity(
				getEntity("id_5").setResult(
						Result.newBuilder().setMetadata(
								Result.Metadata
										.newBuilder()
										.addTitle(
												StructuredProperty.newBuilder().setValue("hhhh title")
														.setQualifier(getQualifier("main title", "dnet:dataCite_title")))
										.setDateofacceptance("2012-01-01").setPublisher("AMER CHEMICAL SOC X")
										.setResulttype(getQualifier("publication", "dnet:result_typologies")).setStoragedate("2012-11-18")
										.setLanguage(getQualifier("eng", "dnet:languages")).addDescription("original description")))).build());
		oafList.add(getOaf("0.6").setEntity(
				getEntity("id_6").setResult(
						Result.newBuilder().setMetadata(
								Result.Metadata.newBuilder().setResulttype(getQualifier("publication", "dnet:result_typologies"))
										.addDescription("new description")))).build());
	}

	@Test
	public void test_merge() {

		Oaf.Builder builder = Oaf.newBuilder();

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

		Result.Metadata.Builder metadata = builder.getEntityBuilder().getResultBuilder().getMetadataBuilder();
		Iterable<StructuredProperty> filter = Iterables.filter(metadata.getTitleList(), new Predicate<StructuredProperty>() {
			@Override
			public boolean apply(StructuredProperty sp) {
				return sp.getQualifier() != null && sp.getQualifier().getClassname().equals("main title");
			}
		});

		StructuredProperty last = Iterables.getLast(filter);

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

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

	@Test
	public void test_merger() {

		Oaf merge = merger.mergeEntities("id", oafList).build();

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

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

	private Oaf.Builder getOaf(String trust) {
		return Oaf.newBuilder().setKind(Kind.entity).setDataInfo(getDataInfo(trust)).setTimestamp(System.currentTimeMillis());
	}

	private OafEntity.Builder getEntity(String id) {
		return OafEntity.newBuilder().setType(Type.result).setId(id).addOriginalId(UUID.randomUUID().toString());
	}

	public static Qualifier.Builder getQualifier(String classname, String schemename) {
		return Qualifier.newBuilder().setClassid(classname).setClassname(classname).setSchemeid(schemename).setSchemename(schemename);
	}

	public static DataInfo.Builder getDataInfo(String trust) {
		return DataInfo.newBuilder().setProvenanceaction(getQualifier("UNKNOWN", "dnet:provenanceActions")).setDeletedbyinference(false)
				.setInferred(false).setTrust(trust);
	}

}
