/**
   * Display the allocations (portfolio entry and activity) of the actor.
   *
   * @param id the actor id
   * @param pagePortfolioEntry the current page for the portfolio entry allocations
   * @param pageActivity the current page for the activity allocations
   * @param viewAllActivities set to true if all activities (including the past ones) must be
   *     displayed
   */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_VIEW_DYNAMIC_PERMISSION)
  public Result allocationDetails(
      Long id, Integer pagePortfolioEntry, Integer pageActivity, Boolean viewAllActivities) {

    // get the actor
    Actor actor = ActorDao.getActorById(id);

    // construct the "portfolio entry" allocations tables

    Pagination<PortfolioEntryResourcePlanAllocatedActor> portfolioEntryPagination =
        PortfolioEntryResourcePlanDAO.getPEPlanAllocatedActorAsPaginationByActorAndActive(id, true);
    portfolioEntryPagination.setCurrentPage(pagePortfolioEntry);
    portfolioEntryPagination.setPageQueryName("pagePortfolioEntry");

    List<PortfolioEntryResourcePlanAllocatedActorListView> allocationListView =
        new ArrayList<PortfolioEntryResourcePlanAllocatedActorListView>();
    for (PortfolioEntryResourcePlanAllocatedActor allocatedActor :
        portfolioEntryPagination.getListOfObjects()) {
      allocationListView.add(new PortfolioEntryResourcePlanAllocatedActorListView(allocatedActor));
    }

    Set<String> columnsToHide = new HashSet<String>();
    columnsToHide.add("editActionLink");
    columnsToHide.add("removeActionLink");
    columnsToHide.add("followPackageDates");
    columnsToHide.add("actor");
    if (!getBudgetTrackingService().isActive()) {
      columnsToHide.add("currency");
      columnsToHide.add("dailyRate");
      columnsToHide.add("forecastDays");
      columnsToHide.add("forecastDailyRate");
    }

    Table<PortfolioEntryResourcePlanAllocatedActorListView> portfolioEntryTable =
        this.getTableProvider()
            .get()
            .portfolioEntryResourcePlanAllocatedActor
            .templateTable
            .fill(allocationListView, columnsToHide);

    portfolioEntryTable.setLineAction(
        new IColumnFormatter<PortfolioEntryResourcePlanAllocatedActorListView>() {
          @Override
          public String apply(
              PortfolioEntryResourcePlanAllocatedActorListView
                  portfolioEntryResourcePlanAllocatedActorListView,
              Object value) {
            return controllers.core.routes.PortfolioEntryPlanningController.resources(
                    portfolioEntryResourcePlanAllocatedActorListView.portfolioEntryId)
                .url();
          }
        });

    // construct the "activity" allocations tables

    Pagination<TimesheetActivityAllocatedActor> activityPagination =
        TimesheetDao.getTimesheetActivityAllocatedActorAsPaginationByActor(id, !viewAllActivities);
    activityPagination.setCurrentPage(pageActivity);
    activityPagination.setPageQueryName("pageActivity");

    List<TimesheetActivityAllocatedActorListView> activityAllocationListView =
        new ArrayList<TimesheetActivityAllocatedActorListView>();
    for (TimesheetActivityAllocatedActor allocatedActor : activityPagination.getListOfObjects()) {
      activityAllocationListView.add(new TimesheetActivityAllocatedActorListView(allocatedActor));
    }

    Set<String> columnsToHideForActivity = new HashSet<String>();
    columnsToHideForActivity.add("actor");

    Table<TimesheetActivityAllocatedActorListView> activityTable =
        this.getTableProvider()
            .get()
            .timesheetActivityAllocatedActor
            .templateTable
            .fill(activityAllocationListView, columnsToHideForActivity);

    return ok(
        views.html.core.actor.actor_allocation_details.render(
            actor,
            portfolioEntryTable,
            portfolioEntryPagination,
            activityTable,
            activityPagination,
            viewAllActivities));
  }
  /**
   * Display the gantt of allocations of the actor.
   *
   * @param id the actor id
   */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_VIEW_DYNAMIC_PERMISSION)
  public Result allocation(Long id) {

    // get the actor
    Actor actor = ActorDao.getActorById(id);

    // prepare the data (to order them)
    SortableCollection<DateSortableObject> sortableCollection = new SortableCollection<>();
    for (PortfolioEntryResourcePlanAllocatedActor allocatedActor :
        PortfolioEntryResourcePlanDAO.getPEPlanAllocatedActorAsListByActorAndActive(id, true)) {
      if (allocatedActor.endDate != null) {
        sortableCollection.addObject(
            new DateSortableObject(allocatedActor.endDate, allocatedActor));
      }
    }
    for (TimesheetActivityAllocatedActor allocatedActivity :
        TimesheetDao.getTimesheetActivityAllocatedActorAsListByActor(id, true)) {
      if (allocatedActivity.endDate != null) {
        sortableCollection.addObject(
            new DateSortableObject(allocatedActivity.endDate, allocatedActivity));
      }
    }

    // construct the gantt

    List<SourceItem> items = new ArrayList<SourceItem>();

    for (DateSortableObject dateSortableObject : sortableCollection.getSorted()) {

      if (dateSortableObject.getObject() instanceof PortfolioEntryResourcePlanAllocatedActor) {

        PortfolioEntryResourcePlanAllocatedActor allocatedActor =
            (PortfolioEntryResourcePlanAllocatedActor) dateSortableObject.getObject();

        // get the from date
        Date from = allocatedActor.startDate;

        // get the to date
        Date to = allocatedActor.endDate;

        // get the portfolio entry
        Long portfolioEntryId =
            allocatedActor.portfolioEntryResourcePlan.lifeCycleInstancePlannings.get(0)
                .lifeCycleInstance
                .portfolioEntry
                .id;
        PortfolioEntry portfolioEntry = PortfolioEntryDao.getPEById(portfolioEntryId);

        String packageName =
            allocatedActor.portfolioEntryPlanningPackage != null
                ? allocatedActor.portfolioEntryPlanningPackage.getName()
                : "";

        SourceItem item = new SourceItem(portfolioEntry.getName(), packageName);

        String cssClass = null;

        if (from != null) {

          to = JqueryGantt.cleanToDate(from, to);
          cssClass = "";

        } else {

          from = to;
          cssClass = "diamond diamond-";
        }

        if (allocatedActor.isConfirmed) {
          cssClass += "success";
        } else {
          cssClass += "warning";
        }

        SourceDataValue dataValue =
            new SourceDataValue(
                controllers.core.routes.PortfolioEntryPlanningController.resources(
                        portfolioEntry.id)
                    .url(),
                null,
                null,
                null,
                null);

        item.values.add(
            new SourceValue(
                from,
                to,
                "",
                views
                    .html
                    .framework_views
                    .parts
                    .formats
                    .display_number
                    .render(allocatedActor.days, null, false)
                    .body(),
                cssClass,
                dataValue));

        items.add(item);
      }

      if (dateSortableObject.getObject() instanceof TimesheetActivityAllocatedActor) {

        TimesheetActivityAllocatedActor allocatedActivity =
            (TimesheetActivityAllocatedActor) dateSortableObject.getObject();

        // get the from date
        Date from = allocatedActivity.startDate;

        // get the to date
        Date to = allocatedActivity.endDate;

        SourceItem item = new SourceItem(allocatedActivity.timesheetActivity.getName(), "");

        String cssClass = null;

        if (from != null) {

          to = JqueryGantt.cleanToDate(from, to);
          cssClass = "";

        } else {

          from = to;
          cssClass = "diamond diamond-";
        }

        cssClass += "info";

        SourceDataValue dataValue =
            new SourceDataValue(
                controllers.core.routes.ActorController.allocationDetails(actor.id, 0, 0, false)
                    .url(),
                null,
                null,
                null,
                null);

        item.values.add(
            new SourceValue(
                from,
                to,
                "",
                views
                    .html
                    .framework_views
                    .parts
                    .formats
                    .display_number
                    .render(allocatedActivity.days, null, false)
                    .body(),
                cssClass,
                dataValue));

        items.add(item);
      }
    }

    String ganttSource = "";
    try {
      ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
      ganttSource = ow.writeValueAsString(items);
    } catch (JsonProcessingException e) {
      Logger.error(e.getMessage());
    }

    return ok(views.html.core.actor.actor_allocation.render(actor, ganttSource));
  }