class FrequentTenderersController extends GenericOCDSController {

    @ApiOperation(value = "Detect frequent pairs of tenderers that apply together to bids."
            + "We are only showing pairs if they applied to more than one bid together."
            + "We are sorting the results after the number of occurences, descending."
            + "You can use all the filters that are available along with pagination options.")
    @RequestMapping(value = "/api/frequentTenderers", method = {RequestMethod.POST, RequestMethod.GET},
            produces = "application/json")
    public List<Document> frequentTenderers(@ModelAttribute @Valid final YearFilterPagingRequest filter) {

        Aggregation agg = newAggregation(
                match(where("tender.tenderers.1").exists(true).and("awards.suppliers.0").exists(true)
                        .and(MongoConstants.FieldNames.AWARDS_STATUS).is(Award.Status.active.toString())
                        .andOperator(getYearDefaultFilterCriteria(
                                filter,
                                MongoConstants.FieldNames.TENDER_PERIOD_START_DATE
                        ))),
                unwind("tender.tenderers"),
                unwind("awards"),
                unwind("awards.suppliers"),
                match(where(MongoConstants.FieldNames.AWARDS_STATUS).is(Award.Status.active.toString())
                        .andOperator(getYearFilterCriteria(
                                filter.awardFiltering(),
                                MongoConstants.FieldNames.TENDER_PERIOD_START_DATE
                        ))),
                project().and(MongoConstants.FieldNames.AWARDS_SUPPLIERS_ID).as("supplierId")
                        .and("tender.tenderers._id").as("tendererId").andExclude(
                        Fields.UNDERSCORE_ID)
                        .and(ComparisonOperators.valueOf(MongoConstants.FieldNames.AWARDS_SUPPLIERS_ID).
                                compareTo("tender.tenderers._id")).as("cmp"),
                match((where("cmp").ne(0))),
                project("supplierId", "tendererId", "cmp")
                        .and(ConditionalOperators.when(
                                Criteria.where("cmp").is(1)).thenValueOf("$supplierId")
                                .otherwiseValueOf("$tendererId")).as("tendererId1")
                        .and(ConditionalOperators.when(
                                Criteria.where("cmp").is(1)).thenValueOf("$tendererId")
                                .otherwiseValueOf("$supplierId")).as("tendererId2"),
                group("tendererId1", "tendererId2").count().as("pairCount"),
                sort(Sort.Direction.DESC, "pairCount"), skip(filter.getSkip()), limit(filter.getPageSize())
        );

        return releaseAgg(agg);
    }

}