class ApplicationOverviewModelPopulator extends AsyncAdaptor {

    public ApplicationOverviewViewModel populateModel(ApplicationResource application, UserResource user) {
        Future<OrganisationResource> organisation = async(() -> organisationRestService.getByUserAndApplicationId(user.getId(), application.getId()).getSuccess());
        Future<CompetitionResource> competition = async(() -> competitionRestService.getCompetitionById(application.getCompetition()).getSuccess());
        Future<List<SectionResource>> sections = async(() -> sectionRestService.getByCompetition(application.getCompetition()).getSuccess());
        Future<List<QuestionResource>> questions = async(() -> questionRestService.findByCompetition(application.getCompetition()).getSuccess());
        Future<List<ProcessRoleResource>> processRoles = async(() -> userRestService.findProcessRole(application.getId()).getSuccess());
        Future<List<QuestionStatusResource>> statuses = async(() -> questionStatusRestService.findByApplicationAndOrganisation(application.getId(), resolve(organisation).getId()).getSuccess());
        Future<List<Long>> completedSectionIds = async(() -> sectionStatusRestService.getCompletedSectionIds(application.getId(), resolve(organisation).getId()).getSuccess());
        Future<Map<Long, Set<Long>>> completedSectionsByOrganisation = async(() -> sectionStatusRestService.getCompletedSectionsByOrganisation(application.getId()).getSuccess());

        async(() -> {
            List<QuestionStatusResource> notifications = questionService.getNotificationsForUser(resolve(statuses), user.getId());
            questionService.removeNotifications(notifications);
        });

        ApplicationOverviewData data = new ApplicationOverviewData(resolve(competition), application, resolve(sections),
                resolve(questions), resolve(processRoles), resolve(organisation), resolve(statuses),
                resolve(completedSectionIds), resolve(completedSectionsByOrganisation), user);

        Set<ApplicationOverviewSectionViewModel> sectionViewModels = data.getSections()
                .values()
                .stream()
                .sorted(comparing(SectionResource::getPriority))
                .filter(section -> section.getParentSection() == null)
                .map(section -> sectionViewModel(section, data))
                .collect(toCollection(LinkedHashSet::new));

        return new ApplicationOverviewViewModel(data.getUserProcessRole(), data.getCompetition(), application, sectionViewModels, application.hasBeenReopened(), application.getLastStateChangeDate());
    }

    public  ApplicationOverviewModelPopulator(AsyncFuturesGenerator asyncFuturesGenerator, CompetitionRestService competitionRestService,
                                             SectionRestService sectionRestService, QuestionRestService questionRestService,
                                             UserRestService userRestService, MessageSource messageSource,
                                             OrganisationRestService organisationRestService, QuestionStatusRestService questionStatusRestService,
                                             SectionStatusRestService sectionStatusRestService,
                                             QuestionService questionService);

}