class AverageTenderAndAwardPeriodsController extends GenericOCDSController {

    @ApiOperation(value = "Calculates the average award period, per each year. The year is taken from "
            + "awards.date and the duration is taken by counting the days"
            + "between tender.tenderPeriod.endDate and tender.tenderPeriod.startDate. The award has to be active.")
    @RequestMapping(value = "/api/averageAwardPeriod", method = {RequestMethod.POST, RequestMethod.GET},
            produces = "application/json")
    public List<Document> averageAwardPeriod(@ModelAttribute @Valid final YearFilterPagingRequest filter) {

        DBObject awardLengthDays = new BasicDBObject("$divide", Arrays.asList(
                new BasicDBObject("$subtract", Arrays.asList(
                        ref(MongoConstants.FieldNames.AWARDS_DATE),
                        ref(MongoConstants.FieldNames.TENDER_PERIOD_END_DATE)
                )), DAY_MS));

        DBObject project = new BasicDBObject();
        project.put(Fields.UNDERSCORE_ID, 0);
        addYearlyMonthlyProjection(filter, project, ref(MongoConstants.FieldNames.AWARDS_DATE));
        project.put("awardLengthDays", awardLengthDays);
        project.put(MongoConstants.FieldNames.AWARDS_DATE, 1);
        project.put(MongoConstants.FieldNames.AWARDS_STATUS, 1);
        project.put(MongoConstants.FieldNames.TENDER_PERIOD_END_DATE, 1);

        Aggregation agg = newAggregation(
                // this is repeated so we gain speed by filtering items before
                // unwind
                match(where(MongoConstants.FieldNames.TENDER_PERIOD_END_DATE)
                        .exists(true).and(MongoConstants.FieldNames.AWARDS_DATE).exists(true)
                        .and(MongoConstants.FieldNames.AWARDS_STATUS).is(Award.Status.active.toString())),
                unwind("awards"),
                // we need to filter the awards again after unwind
                match(where(MongoConstants.FieldNames.AWARDS_DATE).exists(true)
                        .and(MongoConstants.FieldNames.AWARDS_STATUS)
                        .is(Award.Status.active.toString())
                        .andOperator(getYearDefaultFilterCriteria(
                                filter.awardFiltering(),
                                MongoConstants.FieldNames.AWARDS_DATE
                        ))),
                new CustomOperation(new Document("$project", project)),
                group(getYearlyMonthlyGroupingFields(filter)).avg("$awardLengthDays").as(Keys.AVERAGE_AWARD_DAYS),
                transformYearlyGrouping(filter).andInclude(Keys.AVERAGE_AWARD_DAYS),
                getSortByYearMonth(filter), skip(filter.getSkip()),
                limit(filter.getPageSize())
        );

        return releaseAgg(agg);
    }

}