package eu.eudat.criteria;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import eu.eudat.criteria.entities.Criteria;
import eu.eudat.logic.services.operations.DatabaseRepository;
import eu.eudat.query.DatasetQuery;

import java.io.IOException;
import java.util.*;

public class DatasetCriteria {
	private Criteria<UUID> id;
	private Criteria<String> label;
	private DMPCriteria dmp;

	public Criteria<UUID> getId() {
		return id;
	}

	public void setId(JsonNode jsonNode) throws IOException {
		if (jsonNode.getNodeType().equals(JsonNodeType.STRING)) {
			Criteria<UUID> criteria = new Criteria<>();
			criteria.setAs(jsonNode.asText());
			this.id = criteria;
		} else if (jsonNode.getNodeType().equals(JsonNodeType.OBJECT)) {
			ObjectReader reader = new ObjectMapper().readerFor(new TypeReference<Criteria<UUID>>() {
			});
			this.id = reader.readValue(jsonNode);
		}
	}

	public Criteria<String> getLabel() {
		return label;
	}

	public void setLabel(JsonNode jsonNode) throws IOException {
		if (jsonNode.getNodeType().equals(JsonNodeType.STRING)) {
			Criteria<String> criteria = new Criteria<>();
			criteria.setAs(jsonNode.asText());
			this.label = criteria;
		} else if (jsonNode.getNodeType().equals(JsonNodeType.OBJECT)) {
			ObjectReader reader = new ObjectMapper().readerFor(new TypeReference<Criteria<String>>() {
			});
			this.label = reader.readValue(jsonNode);
		}
	}

	public DMPCriteria getDmp() {
		return dmp;
	}

	public void setDmp(DMPCriteria dmp) {
		this.dmp = dmp;
	}

	protected List<String> buildFields(String path) {
		Set<String> fields = new HashSet<>();
		path = path != null && !path.isEmpty() ? path + "." : "";
		if (this.id != null) fields.add(path + this.id.getAs());
		if (this.label != null) fields.add(path + this.label.getAs());
		if (this.dmp != null) fields.addAll(this.dmp.buildFields(path + "dmp"));
		if (!fields.contains(path + "id")) fields.add(path + "id");
		return new LinkedList<>(fields);
	}

	public DatasetQuery buildQuery(DatabaseRepository dao) {
		List<String> fields = this.buildFields("");
		DatasetQuery datasetQuery = new DatasetQuery(dao.getDatasetDao(), fields);
		if (this.id != null) datasetQuery.setId(this.id.getValue());
		if (this.dmp != null) datasetQuery.setDmpQuery(this.dmp.buildQuery(dao));
		return datasetQuery;
	}
}
