package com.epam.ta.reportportal.database.dao.aggregation;

import com.epam.ta.reportportal.commons.Predicates;
import com.epam.ta.reportportal.commons.validation.BusinessRule;
import com.epam.ta.reportportal.exception.ReportPortalException;
import com.epam.ta.reportportal.ws.model.ErrorType;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
import org.springframework.data.mongodb.core.aggregation.AggregationOperationContext;

import java.util.Arrays;

/**
 * @author Pavel Bortnik
 */
public class GroupingOperation implements AggregationOperation {

	private String id = "_id";

	private BasicDBObject idExpression;

	private BasicDBObject groupExpression;

	public GroupingOperation() {
		idExpression = new BasicDBObject();
		groupExpression = new BasicDBObject();
	}

	public static GroupingOperation build() {
		return new GroupingOperation();
	}

	@Override
	public DBObject toDBObject(AggregationOperationContext context) {
		return new BasicDBObject("$group", groupExpression.append(id, idExpression));
	}

	public GroupingOperation groupWithPeriod(GroupingPeriod period, String groupingField) {
		BusinessRule.expect(groupingField, Predicates.notNull()).verify(ErrorType.INCORRECT_REQUEST, "Grouping field shouldn't be null");
		idExpression.append(period.getValue(), new BasicDBObject(period.getOperation(), groupingField));
		return this;
	}

	public GroupingOperation withFieldId(String alias, Object value) {
		idExpression.append(alias, value);
		return this;
	}

	public GroupingOperation push(String alias, Object value) {
		groupExpression.append(alias, new BasicDBObject("$push", value));
		return this;
	}

	public GroupingOperation sum(String alias, String contentField) {
		groupExpression.append(alias, new BasicDBObject("$sum", contentField));
		return this;
	}

	public GroupingOperation first(String alias, String field) {
		groupExpression.append(alias, new BasicDBObject("$first", field));
		return this;
	}

	public enum GroupingPeriod {
		BY_DAY("by_day", "$dayOfYear"),
		BY_WEEK("by_week", "$week"),
		BY_MONTH("by_month", "$month");

		private String value;

		private String operation;

		GroupingPeriod(String value, String operation) {
			this.value = value;
			this.operation = operation;
		}

		public static GroupingPeriod getByValue(String groupingBy) {
			return Arrays.stream(GroupingPeriod.values())
					.filter(it -> it.getValue().equals(groupingBy))
					.findFirst()
					.orElseThrow(
							() -> new ReportPortalException(ErrorType.INCORRECT_REQUEST, groupingBy + " type of grouping is unsupported"));
		}

		public String getValue() {
			return value;
		}

		public String getOperation() {
			return operation;
		}
	}

}

@@ -1,8 +1,796 @@
+/*%0A * Copyright 2017 EPAM Systems%0A *%0A *%0A * This file is part of EPAM Report Portal.%0A * https://github.com/reportportal/commons-dao%0A *%0A * Report Portal is free software: you can redistribute it and/or modify%0A * it under the terms of the GNU General Public License as published by%0A * the Free Software Foundation, either version 3 of the License, or%0A * (at your option) any later version.%0A *%0A * Report Portal is distributed in the hope that it will be useful,%0A * but WITHOUT ANY WARRANTY; without even the implied warranty of%0A * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the%0A * GNU General Public License for more details.%0A *%0A * You should have received a copy of the GNU General Public License%0A * along with Report Portal.  If not, see %3Chttp://www.gnu.org/licenses/%3E.%0A */%0A%0A
 package 
@@ -962,73 +962,8 @@
 le;%0A
-import com.epam.ta.reportportal.exception.ReportPortalException;%0A
 impo
@@ -1268,11 +1268,99 @@
 ys;%0A
-%0A/*
+import java.util.Optional;%0A%0A/**%0A * Custom group operation for mongo aggregation framework%0A 
 *%0A *
@@ -3139,32 +3139,41 @@
 %09%09public static 
+Optional%3C
 GroupingPeriod g
@@ -3170,16 +3170,17 @@
 ngPeriod
+%3E
  getByVa
@@ -3252,22 +3252,16 @@
 alues())
-%0A%09%09%09%09%09
 .filter(
@@ -3299,22 +3299,16 @@
 pingBy))
-%0A%09%09%09%09%09
 .findFir
@@ -3315,145 +3315,8 @@
 st()
-%0A%09%09%09%09%09.orElseThrow(%0A%09%09%09%09%09%09%09() -%3E new ReportPortalException(ErrorType.INCORRECT_REQUEST, groupingBy + %22 type of grouping is unsupported%22))
 ;%0A%09%09

replace error with returning optional