package eu.dnetlib.pace.distance;

import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;

import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.protobuf.GeneratedMessage;

import eu.dnetlib.data.proto.FieldTypeProtos.StringField;
import eu.dnetlib.data.proto.FieldTypeProtos.StructuredProperty;
import eu.dnetlib.data.proto.ResultProtos.Result;
import eu.dnetlib.data.proto.ResultProtos.Result.Metadata;
import eu.dnetlib.pace.config.Type;
import eu.dnetlib.pace.model.Document;
import eu.dnetlib.pace.model.Field;
import eu.dnetlib.pace.model.FieldListImpl;
import eu.dnetlib.pace.model.FieldValueImpl;
import eu.dnetlib.pace.model.MapDocument;

public class ProtoDistance extends AbstractDistance<GeneratedMessage> {

	private final String identifier;

	public ProtoDistance(final String identifier) {
		this.identifier = identifier;
	}

	@Override
	protected Document toDocument(final GeneratedMessage a) {

		Map<String, FieldListImpl> res = Maps.newHashMap();

		Metadata meta = ((Result) a).getMetadata();
		if (!meta.getTitleList().isEmpty()) {
			res.put("title", transformListSP("title", meta.getTitleList()));
		}

		if (!meta.getDescriptionList().isEmpty()) {
			res.put("description", transformListString("description", meta.getDescriptionList()));
		}

		return new MapDocument(identifier, res);
	}

	private FieldListImpl transformListSP(final String name, final List<StructuredProperty> input) {
		Function<StructuredProperty, Field> function = new Function<StructuredProperty, Field>() {

			@Override
			public Field apply(final StructuredProperty sp) {
				return new FieldValueImpl(Type.String, name, sp.getValue());
			}
		};
		final FieldListImpl fl = new FieldListImpl();
		fl.addAll(Lists.newArrayList(Lists.transform(input, function)));
		return fl;
	}

	private FieldListImpl transformListString(final String name, final List<StringField> input) {
		Function<StringField, Field> function = new Function<StringField, Field>() {

			@Override
			public Field apply(final StringField sp) {
				return new FieldValueImpl(Type.String, name, StringUtils.substring(sp.getValue(), 0, 100));
			}
		};
		final FieldListImpl fl = new FieldListImpl();
		fl.addAll(Lists.newArrayList(Lists.transform(input, function)));
		return fl;
	}
}
