package eu.eudat.query;

import eu.eudat.data.dao.DatabaseAccessLayer;
import eu.eudat.data.entities.DMP;
import eu.eudat.data.entities.Dataset;
import eu.eudat.data.entities.Grant;
import eu.eudat.data.entities.UserInfo;
import eu.eudat.queryable.QueryableList;
import eu.eudat.queryable.types.FieldSelectionType;
import eu.eudat.queryable.types.SelectionField;

import javax.persistence.criteria.Subquery;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;

public class DMPQuery extends Query<DMP, UUID> {
	private UUID id;
	private UUID groupId;
	private String label;
	private int version;
	private GrantQuery grantQuery;
	private UserQuery userQuery;
	private DatasetQuery datasetQuery;
	private List<Integer> statuses;
	private Date created;
	private Date modified;

	public DMPQuery(DatabaseAccessLayer<DMP, UUID> databaseAccessLayer) {
		super(databaseAccessLayer);
	}

	public DMPQuery(DatabaseAccessLayer<DMP, UUID> databaseAccessLayer, List<String> selectionFields) {
		super(databaseAccessLayer, selectionFields);
	}

	public UUID getId() {
		return id;
	}

	public void setId(UUID id) {
		this.id = id;
	}

	public UUID getGroupId() {
		return groupId;
	}

	public void setGroupId(UUID groupId) {
		this.groupId = groupId;
	}

	public String getLabel() {
		return label;
	}

	public void setLabel(String label) {
		this.label = label;
	}

	public int getVersion() {
		return version;
	}

	public void setVersion(int version) {
		this.version = version;
	}

	public GrantQuery getGrantQuery() {
		return grantQuery;
	}

	public void setGrantQuery(GrantQuery grantQuery) {
		this.grantQuery = grantQuery;
	}

	public List<Integer> getStatuses() {
		return statuses;
	}

	public void setStatuses(List<Integer> statuses) {
		statuses = statuses;
	}

	public Date getCreated() {
		return created;
	}

	public void setCreated(Date created) {
		this.created = created;
	}

	public Date getModified() {
		return modified;
	}

	public void setModified(Date modified) {
		this.modified = modified;
	}

	public UserQuery getUserQuery() {
		return userQuery;
	}

	public void setUserQuery(UserQuery userQuery) {
		this.userQuery = userQuery;
	}

	public DatasetQuery getDatasetQuery() {
		return datasetQuery;
	}

	public void setDatasetQuery(DatasetQuery datasetQuery) {
		this.datasetQuery = datasetQuery;
	}

	public QueryableList<DMP> getQuery() {
		QueryableList<DMP> query = this.databaseAccessLayer.asQueryable();
		if (this.id != null) {
			query.where((builder, root) -> builder.equal(root.get("id"), this.id));
		}
		if (this.grantQuery != null) {
			Subquery<Grant> grantQuery = this.grantQuery.getQuery().query(Arrays.asList(new SelectionField(FieldSelectionType.FIELD, "id")));
			query.where((builder, root) -> root.get("grant").get("id").in(grantQuery));
		}
		if (this.getStatuses() != null && !this.getStatuses().isEmpty()) {
			query.where((builder, root) -> root.get("status").in(this.getStatuses()));
		}
		if (this.userQuery != null) {
			Subquery<UserInfo> userInfoSubQuery = this.userQuery.getQuery().query(Arrays.asList(new SelectionField(FieldSelectionType.FIELD, "id")));
			query.where((builder, root) -> root.get("creator").get("id").in(userInfoSubQuery));
		}
		if(this.datasetQuery != null){
			Subquery<Dataset> datasetSubQuery = this.datasetQuery.getQuery().query(Arrays.asList(new SelectionField(FieldSelectionType.COMPOSITE_FIELD, "dmp:id")));
			query.where((builder, root) -> root.get("id").in(datasetSubQuery ));
		}
		if (!this.getSelectionFields().isEmpty() && this.getSelectionFields() != null) {
			query.withFields(this.getSelectionFields());
		}
		return query;
	}
}
