/**
   * Delete a custom KPI.
   *
   * @param kpiDefinitionId the KPI definition id
   */
  public Result delete(Long kpiDefinitionId) {

    // get the KPI
    KpiDefinition kpiDefinition = KpiDefinition.getById(kpiDefinitionId);
    Kpi kpi = new Kpi(kpiDefinition, getKpiService());

    if (!kpiDefinition.isStandard) {

      // cancel the scheduler
      kpi.cancel();

      // delete the values and data
      deleteKpiValueDefinition(kpiDefinition.mainKpiValueDefinition);
      deleteKpiValueDefinition(kpiDefinition.additional1KpiValueDefinition);
      deleteKpiValueDefinition(kpiDefinition.additional2KpiValueDefinition);

      // delete the colors
      if (kpiDefinition.kpiColorRules != null) {
        for (KpiColorRule kpiColorRule : kpiDefinition.kpiColorRules) {
          kpiColorRule.doDelete();
        }
      }

      kpiDefinition.deleted = true;
      kpiDefinition.save();

      Utilities.sendSuccessFlashMessage(Msg.get("admin.kpi.delete.successful"));

    } else {
      Utilities.sendSuccessFlashMessage(Msg.get("admin.kpi.delete.error"));
    }

    return redirect(controllers.admin.routes.KpiManagerController.index());
  }
  /** Process the form to create/edit an allocation with an activity. */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_EDIT_DYNAMIC_PERMISSION)
  public Result processManageAllocatedActivity() {

    // bind the form
    Form<TimesheetActivityAllocatedActorFormData> boundForm =
        allocatedActivityFormTemplate.bindFromRequest();

    // get the actor
    Long id = Long.valueOf(boundForm.data().get("id"));
    Actor actor = ActorDao.getActorById(id);

    if (boundForm.hasErrors()
        || this.getCustomAttributeManagerService()
            .validateValues(boundForm, TimesheetActivityAllocatedActor.class)) {
      return ok(views.html.core.actor.allocated_activity_manage.render(actor, boundForm));
    }

    TimesheetActivityAllocatedActorFormData allocatedActivityFormData = boundForm.get();

    TimesheetActivityAllocatedActor allocatedActivity = null;

    if (allocatedActivityFormData.allocatedActivityId == null) { // create
      // case

      allocatedActivity = new TimesheetActivityAllocatedActor();
      allocatedActivityFormData.fill(allocatedActivity);
      allocatedActivity.save();

      Utilities.sendSuccessFlashMessage(Msg.get("core.actor.allocated_activity.add.successful"));

    } else { // edit case

      allocatedActivity =
          TimesheetDao.getTimesheetActivityAllocatedActorById(
              allocatedActivityFormData.allocatedActivityId);

      // security: the actor must be related to the object
      if (!allocatedActivity.actor.id.equals(id)) {
        return forbidden(views.html.error.access_forbidden.render(""));
      }

      allocatedActivityFormData.fill(allocatedActivity);
      allocatedActivity.update();

      Utilities.sendSuccessFlashMessage(Msg.get("core.actor.allocated_activity.edit.successful"));
    }

    // save the custom attributes
    this.getCustomAttributeManagerService()
        .validateAndSaveValues(
            boundForm, TimesheetActivityAllocatedActor.class, allocatedActivity.id);

    return redirect(controllers.core.routes.ActorController.allocationDetails(id, 0, 0, false));
  }
  /** Process the manage form of a KPI color rule. */
  public Result saveRule() {

    // bind the form
    Form<KpiColorRuleFormData> boundForm = kpiColorRuleFormTemplate.bindFromRequest();

    // get the KPI
    Long kpiDefinitionId = Long.valueOf(boundForm.data().get("kpiDefinitionId"));
    KpiDefinition kpiDefinition = KpiDefinition.getById(kpiDefinitionId);
    Kpi kpi = new Kpi(kpiDefinition, getKpiService());

    if (boundForm.hasErrors()) {
      return ok(
          views.html.admin.kpi.manageRule.render(
              kpiDefinition,
              kpi,
              boundForm,
              Color.getColorsAsValueHolderCollection(getI18nMessagesPlugin())));
    }

    KpiColorRuleFormData kpiColorRuleFormData = boundForm.get();

    KpiColorRule kpiColorRule = null;

    if (kpiColorRuleFormData.kpiColorRuleId == null) { // create case

      kpiColorRule = new KpiColorRule();

      kpiColorRule.kpiDefinition = kpiDefinition;
      kpiColorRule.order = KpiColorRule.getLastOrder(kpiDefinition.id) + 1;

      kpiColorRuleFormData.fill(kpiColorRule);

      kpiColorRule.save();

      Utilities.sendSuccessFlashMessage(Msg.get("admin.kpi.rule.add.successful"));

    } else { // edit case

      kpiColorRule = KpiColorRule.getById(kpiColorRuleFormData.kpiColorRuleId);

      kpiColorRuleFormData.fill(kpiColorRule);

      kpiColorRule.update();

      Utilities.sendSuccessFlashMessage(Msg.get("admin.kpi.rule.edit.successful"));
    }

    kpiColorRuleFormData.renderLabel.persist(getI18nMessagesPlugin());

    reloadKpiDefinition(kpiDefinition.uid);

    return redirect(controllers.admin.routes.KpiManagerController.view(kpiDefinition.id));
  }
  /** Save the capacity. */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_EDIT_DYNAMIC_PERMISSION)
  public Result saveCapacity() {

    // bind the form
    Form<ActorCapacityFormData> boundForm = capacityFormTemplate.bindFromRequest();

    // get the actor
    Long id = Long.valueOf(boundForm.data().get("id"));
    Actor actor = ActorDao.getActorById(id);

    // get the year
    Integer year = Integer.valueOf(boundForm.data().get("year"));

    if (boundForm.hasErrors()) {
      return ok(views.html.core.actor.actor_capacity.render(actor, year, boundForm, true));
    }

    ActorCapacityFormData capacityFormData = boundForm.get();

    for (ActorCapacity capacity : capacityFormData.getFilledCapacities()) {
      capacity.save();
    }

    Utilities.sendSuccessFlashMessage(Msg.get("core.actor.capacity.save.successful"));

    return redirect(
        controllers.core.routes.ActorController.capacity(
            capacityFormData.id, capacityFormData.year));
  }
  /**
   * Trigger the scheduler of a KPI definition.
   *
   * @param kpiDefinitionId the KPI definition id
   */
  public Result triggerScheduler(final Long kpiDefinitionId) {

    getSysAdminUtils()
        .scheduleOnce(
            false,
            "KpiManager",
            Duration.create(0, TimeUnit.MILLISECONDS),
            new Runnable() {
              @Override
              public void run() {

                KpiDefinition kpiDefinition = KpiDefinition.getById(kpiDefinitionId);

                Kpi kpi = getKpiService().getKpi(kpiDefinition.uid);

                if (kpi != null && kpi.hasScheduler()) {
                  kpi.storeValues();
                }
              }
            });

    Utilities.sendSuccessFlashMessage(Msg.get("admin.kpi.scheduler.trigger"));

    return redirect(controllers.admin.routes.KpiManagerController.view(kpiDefinitionId));
  }
  /** Process the form to create a new custom and external KPI. */
  public Result processCreate() {

    // bind the form
    Form<CustomExternalKpiFormData> boundForm = customExternalKpiFormTemplate.bindFromRequest();

    // get the object type
    String objectType = boundForm.data().get("objectType");

    if (boundForm.hasErrors()) {
      return ok(views.html.admin.kpi.create.render(objectType, boundForm));
    }

    CustomExternalKpiFormData customExternalKpiFormData = boundForm.get();

    KpiDefinition kpiDefinition = customExternalKpiFormData.constructKpiDefinition();

    kpiDefinition.mainKpiValueDefinition.save();
    kpiDefinition.additional1KpiValueDefinition.save();
    kpiDefinition.additional2KpiValueDefinition.save();
    kpiDefinition.save();

    customExternalKpiFormData.mainName.persist(getI18nMessagesPlugin());
    customExternalKpiFormData.additional1Name.persist(getI18nMessagesPlugin());
    customExternalKpiFormData.additional2Name.persist(getI18nMessagesPlugin());

    reloadKpiDefinition(kpiDefinition.uid);

    Utilities.sendSuccessFlashMessage(Msg.get("admin.kpi.create.successful"));

    return redirect(controllers.admin.routes.KpiManagerController.view(kpiDefinition.id));
  }
  /** Process the edit form of the scheduler of a KPI definition. */
  public Result saveScheduler() {

    // bind the form
    Form<KpiSchedulerFormData> boundForm = kpiSchedulerFormTemplate.bindFromRequest();

    // get the KPI
    Long kpiDefinitionId = Long.valueOf(boundForm.data().get("id"));
    KpiDefinition kpiDefinition = KpiDefinition.getById(kpiDefinitionId);
    Kpi kpi = new Kpi(kpiDefinition, getKpiService());

    if (boundForm.hasErrors()) {
      return ok(views.html.admin.kpi.editScheduler.render(kpiDefinition, kpi, boundForm));
    }

    KpiSchedulerFormData kpiSchedulerFormData = boundForm.get();

    kpiSchedulerFormData.fill(kpiDefinition);
    kpiDefinition.update();

    reloadKpiDefinition(kpiDefinition.uid);

    Utilities.sendSuccessFlashMessage(Msg.get("admin.kpi.editscheduler.successful"));

    return redirect(controllers.admin.routes.KpiManagerController.view(kpiDefinition.id));
  }
  /** Send a notification message. */
  public Result sendMessage() {

    try {
      Form<NotificationMessage> boundForm = notificationMessageForm.bindFromRequest();
      if (boundForm.hasErrors()) {

        String loggedUser = getUserSessionManagerPlugin().getUserSessionId(ctx());

        List<MessageListView> messageListViewRows = new ArrayList<>();
        List<Notification> notifications =
            getNotificationManagerPlugin().getMessagesForUid(loggedUser);
        for (Notification notification : notifications) {
          messageListViewRows.add(
              new MessageListView(this.getAccountManagerPlugin(), notification));
        }
        Table<MessageListView> messagesTables =
            this.getTableProvider().get().message.templateTable.fill(messageListViewRows);

        return ok(views.html.messaging.index.render(messagesTables, boundForm));
      }
      NotificationMessage notificationMessage = boundForm.get();
      getNotificationManagerPlugin()
          .sendMessage(
              getUserSessionManagerPlugin().getUserSessionId(ctx()),
              notificationMessage.principalUids,
              notificationMessage.title,
              notificationMessage.message);
      Utilities.sendSuccessFlashMessage(
          getI18nMessagesPlugin().get("messaging.send.success", notificationMessage.title));
      return redirect(routes.MessagingController.index());
    } catch (Exception e) {
      return ControllersUtils.logAndReturnUnexpectedError(
          e, log, getConfiguration(), getI18nMessagesPlugin());
    }
  }
  /**
   * Delete a KPI color rule.
   *
   * @param kpiColorRuleId the KPI color rule id
   */
  public Result deleteRule(Long kpiColorRuleId) {

    KpiColorRule kpiColorRule = KpiColorRule.getById(kpiColorRuleId);

    kpiColorRule.doDelete();

    reloadKpiDefinition(kpiColorRule.kpiDefinition.uid);

    Utilities.sendSuccessFlashMessage(Msg.get("admin.kpi.rule.delete"));

    return redirect(
        controllers.admin.routes.KpiManagerController.view(kpiColorRule.kpiDefinition.id));
  }
  /**
   * Delete an actor.
   *
   * @param id the actor id
   */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_DELETE_DYNAMIC_PERMISSION)
  public Result delete(Long id) {

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

    // delete the actor
    actor.doDelete();

    // success message
    Utilities.sendSuccessFlashMessage(Msg.get("core.actor.delete.successful"));

    return redirect(controllers.core.routes.SearchController.index());
  }
  /**
   * Delete the scheduler of a KPI definition.
   *
   * @param kpiDefinitionId the KPI definition id
   */
  public Result deleteScheduler(Long kpiDefinitionId) {

    KpiDefinition kpiDefinition = KpiDefinition.getById(kpiDefinitionId);

    kpiDefinition.schedulerFrequency = null;
    kpiDefinition.schedulerRealTime = null;
    kpiDefinition.schedulerStartTime = null;
    kpiDefinition.save();

    reloadKpiDefinition(kpiDefinition.uid);

    Utilities.sendSuccessFlashMessage(Msg.get("admin.kpi.scheduler.delete"));

    return redirect(controllers.admin.routes.KpiManagerController.view(kpiDefinitionId));
  }
  /** Process the form to select the competencies of the actor. */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_EDIT_DYNAMIC_PERMISSION)
  public Result processEditCompetencies() {

    // bind the form
    Form<ActorCompetenciesFormData> boundForm = competenciesFormTemplate.bindFromRequest();

    // get the actor
    Long id = Long.valueOf(boundForm.data().get("id"));
    Actor actor = ActorDao.getActorById(id);

    if (boundForm.hasErrors()) {
      return ok(
          views.html.core.actor.competencies_edit.render(
              actor, ActorDao.getCompetencyActiveAsVH(), boundForm));
    }

    ActorCompetenciesFormData competenciesFormData = boundForm.get();

    competenciesFormData.fill(actor);
    // actor.saveManyToManyAssociations("competencies");

    if (actor.competencies.size() == 0) {
      actor.defaultCompetency = null;
      actor.save();
    } else if (actor.competencies.size() == 1) {
      actor.defaultCompetency = actor.competencies.get(0);
      actor.save();
    } else {
      Form<ActorDefaultCompetencyFormData> defaultCompetencyForm =
          defaultCompetencyFormTemplate.fill(new ActorDefaultCompetencyFormData(actor));
      // force the default competency to an existing one
      actor.defaultCompetency = actor.competencies.get(0);
      actor.save();
      return ok(
          views.html.core.actor.default_competency_edit.render(
              actor,
              new DefaultSelectableValueHolderCollection<Long>(actor.competencies),
              defaultCompetencyForm));
    }

    Utilities.sendSuccessFlashMessage(Msg.get("core.actor.competencies.edit.successful"));

    return redirect(controllers.core.routes.ActorController.view(actor.id));
  }
 /**
  * Display reset password form.
  *
  * @param uuid the user uid
  */
 public Result triggerResetPassword(final String uuid) {
   Form<ResetPasswordRequest> boundForm = passwordResetRequestForm.bindFromRequest();
   if (boundForm.hasErrors()) {
     return badRequest(reset_password.render(uuid, boundForm));
   }
   ResetPasswordRequest resetPasswordRequest = boundForm.get();
   String decodedUuid = new String(Base64.decodeBase64(uuid));
   if (!CaptchaManager.validateCaptcha(decodedUuid, resetPasswordRequest.captchaText)) {
     boundForm.reject("captchaText", Msg.get("captcha.error.wrong_word"));
     return badRequest(reset_password.render(uuid, boundForm));
   }
   if (!getUserManagerController().resetUserPasswordFromEmail(resetPasswordRequest.mail, false)) {
     boundForm.reject("mail", Msg.get("authentication.standalone.reset.mail.unknown.message"));
     return badRequest(reset_password.render(uuid, boundForm));
   }
   Utilities.sendSuccessFlashMessage(Msg.get("authentication.standalone.reset.success.message"));
   return redirect(controllers.dashboard.routes.DashboardController.index(0, false));
 }
  /**
   * Delete an allocated activity.
   *
   * @param id the actor id
   * @param allocatedActivityId the allocated activity id
   */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_EDIT_DYNAMIC_PERMISSION)
  public Result deleteAllocatedActivity(Long id, Long allocatedActivityId) {

    // get the allocated activity
    TimesheetActivityAllocatedActor allocatedActivity =
        TimesheetDao.getTimesheetActivityAllocatedActorById(allocatedActivityId);

    // security: the actor must be related to the object
    if (!allocatedActivity.actor.id.equals(id)) {
      return forbidden(views.html.error.access_forbidden.render(""));
    }

    // set the delete flag to true
    allocatedActivity.doDelete();

    Utilities.sendSuccessFlashMessage(Msg.get("core.actor.allocated_activity.delete.successful"));

    return redirect(controllers.core.routes.ActorController.allocationDetails(id, 0, 0, false));
  }
  /** Process the form to edit the default competency of an actor. */
  @With(CheckActorExists.class)
  @Dynamic(IMafConstants.ACTOR_EDIT_DYNAMIC_PERMISSION)
  public Result processEditDefaultCompetency() {

    // bind the form
    Form<ActorDefaultCompetencyFormData> boundForm =
        defaultCompetencyFormTemplate.bindFromRequest();

    // get the actor
    Long id = Long.valueOf(boundForm.data().get("id"));
    Actor actor = ActorDao.getActorById(id);

    ActorDefaultCompetencyFormData defaultCompetencyFormData = boundForm.get();

    defaultCompetencyFormData.fill(actor);
    actor.save();

    Utilities.sendSuccessFlashMessage(Msg.get("core.actor.competencies.edit.successful"));

    return redirect(controllers.core.routes.ActorController.view(actor.id));
  }
  /** Process the save of an actor (create and edit cases). */
  @Dynamic(IMafConstants.ACTOR_EDIT_DYNAMIC_PERMISSION)
  public Result save() {

    // bind the form
    Form<ActorFormData> boundForm = formTemplate.bindFromRequest();

    if (boundForm.hasErrors()
        || this.getCustomAttributeManagerService().validateValues(boundForm, Actor.class)) {

      if (boundForm.data().get("id") != null) { // edit case
        // get the actor
        Long id = Long.valueOf(boundForm.data().get("id"));
        Actor actor = ActorDao.getActorById(id);
        return ok(
            views.html.core.actor.actor_edit.render(
                actor, boundForm, ActorDao.getActorTypeActiveAsVH()));
      } else { // new case
        return ok(
            views.html.core.actor.actor_new.render(boundForm, ActorDao.getActorTypeActiveAsVH()));
      }
    }

    ActorFormData actorFormData = boundForm.get();

    // check the uid is not already used by another actor
    if (actorFormData.uid != null && !actorFormData.uid.equals("")) {
      Actor testActor = ActorDao.getActorByUid(actorFormData.uid);
      if (testActor != null) { // edit case

        if (actorFormData.id != null) {
          if (!testActor.id.equals(actorFormData.id)) {
            boundForm.reject("uid", Msg.get("object.actor.uid.invalid"));
            Actor actor = ActorDao.getActorById(actorFormData.id);
            return ok(
                views.html.core.actor.actor_edit.render(
                    actor, boundForm, ActorDao.getActorTypeActiveAsVH()));
          }
        } else { // new case
          boundForm.reject("uid", Msg.get("object.actor.uid.invalid"));
          return ok(
              views.html.core.actor.actor_new.render(boundForm, ActorDao.getActorTypeActiveAsVH()));
        }
      }
    }

    Actor actor = null;

    if (actorFormData.id != null) { // edit case

      actor = ActorDao.getActorById(actorFormData.id);
      actorFormData.fill(actor);
      actor.update();

      Utilities.sendSuccessFlashMessage(Msg.get("core.actor.edit.successful"));

    } else { // new case

      actor = new Actor();
      actorFormData.fill(actor);
      actor.save();

      Utilities.sendSuccessFlashMessage(Msg.get("core.actor.new.successful"));
    }

    // save the custom attributes
    this.getCustomAttributeManagerService().validateAndSaveValues(boundForm, Actor.class, actor.id);

    return redirect(controllers.core.routes.ActorController.view(actor.id));
  }
  /** Process the edit form of a KPI value definition. */
  public Result saveValue() {

    // get the KPI value
    Long kpiValueDefinitionId = Long.valueOf(request().body().asFormUrlEncoded().get("id")[0]);
    KpiValueDefinition kpiValueDefinition = KpiValueDefinition.getById(kpiValueDefinitionId);

    // get the KPI
    KpiDefinition kpiDefinition = KpiDefinition.getById(kpiValueDefinition.getKpiDefinition().id);
    Kpi kpi = new Kpi(kpiDefinition, getKpiService());

    // bind the form
    Form<KpiValueDefinitionFormData> boundForm = null;
    if (kpiDefinition.isStandard) {
      boundForm = standardKpiValueDefinitionFormTemplate.bindFromRequest();
    } else {
      boundForm = customKpiValueDefinitionFormTemplate.bindFromRequest();
    }

    // get the value type
    String valueType = boundForm.data().get("valueType");

    if (boundForm.hasErrors()) {
      return ok(
          views.html.admin.kpi.editValue.render(
              kpiDefinition,
              kpi,
              kpiValueDefinition,
              valueType,
              boundForm,
              getRenderTypesAsValueHolderCollection()));
    }

    KpiValueDefinitionFormData kpiValueDefinitionFormData = boundForm.get();

    if (kpiValueDefinitionFormData.renderType.equals(RenderType.PATTERN.name())
        && (kpiValueDefinitionFormData.renderPattern == null
            || kpiValueDefinitionFormData.renderPattern.equals(""))) {
      boundForm.reject(
          "renderPattern", Msg.get("object.kpi_value_definition.render_pattern.invalid"));
      return ok(
          views.html.admin.kpi.editValue.render(
              kpiDefinition,
              kpi,
              kpiValueDefinition,
              valueType,
              boundForm,
              getRenderTypesAsValueHolderCollection()));
    }

    kpiValueDefinitionFormData.fill(kpiValueDefinition, !kpiDefinition.isStandard);
    kpiValueDefinition.update();

    if (!kpiDefinition.isStandard) {
      kpiValueDefinitionFormData.name.persist(getI18nMessagesPlugin());
    }

    reloadKpiDefinition(kpiDefinition.uid);

    Utilities.sendSuccessFlashMessage(Msg.get("admin.kpi.value.edit.successful"));

    return redirect(controllers.admin.routes.KpiManagerController.view(kpiDefinition.id));
  }