/* (non-Javadoc)
   * @see org.sakaiproject.evaluation.logic.EvalEmailsLogic#sendEvalResultsNotifications(java.lang.Long, boolean, boolean, java.lang.String)
   */
  public String[] sendEvalResultsNotifications(
      Long evaluationId, boolean includeEvaluatees, boolean includeAdmins, String jobType) {
    log.debug(
        "evaluationId: "
            + evaluationId
            + ", includeEvaluatees: "
            + includeEvaluatees
            + ", includeAdmins: "
            + includeAdmins);

    /*TODO deprecated?
    if(EvalConstants.EVAL_INCLUDE_ALL.equals(includeConstant)) {
    }
    boolean includeEvaluatees = true;
    if (includeEvaluatees) {
    // TODO Not done yet
    log.error("includeEvaluatees Not implemented");
    }
    */

    EvalEvaluation eval = getEvaluationOrFail(evaluationId);
    String from = getFromEmailOrFail(eval);
    EvalEmailTemplate emailTemplate =
        getEmailTemplateOrFail(EvalConstants.EMAIL_TEMPLATE_RESULTS, evaluationId);

    // get the associated eval groups for this evaluation
    Map<Long, List<EvalGroup>> evalGroupIds =
        evaluationService.getEvalGroupsForEval(new Long[] {evaluationId}, false, null);
    // only one possible map key so we can assume evaluationId
    List<EvalGroup> groups = evalGroupIds.get(evaluationId);
    if (log.isDebugEnabled())
      log.debug("Found " + groups.size() + " groups for available evaluation: " + evaluationId);
    Map<String, EvalGroup> groupsMap = new HashMap<String, EvalGroup>();
    for (EvalGroup evalGroup : groups) {
      groupsMap.put(evalGroup.evalGroupId, evalGroup);
    }

    // get the associated eval assign groups for this evaluation
    Map<Long, List<EvalAssignGroup>> evalAssignGroups =
        evaluationService.getAssignGroupsForEvals(new Long[] {evaluationId}, false, null);
    // only one possible map key so we can assume evaluationId
    List<EvalAssignGroup> assignGroups = evalAssignGroups.get(evaluationId);
    if (log.isDebugEnabled())
      log.debug(
          "Found "
              + assignGroups.size()
              + " assign groups for available evaluation: "
              + evaluationId);

    List<String> sentEmails = new ArrayList<String>();
    // loop through groups and send emails to correct users in each evalGroupId
    for (int i = 0; i < assignGroups.size(); i++) {
      EvalAssignGroup evalAssignGroup = assignGroups.get(i);
      String evalGroupId = evalAssignGroup.getEvalGroupId();
      EvalGroup group = groupsMap.get(evalGroupId);
      if (group == null || EvalConstants.GROUP_TYPE_INVALID.equals(group.type)) {
        log.warn(
            "Invalid group returned for groupId ("
                + evalGroupId
                + "), could not send results notifications");
        continue;
      }

      /*
       * Notification of results may occur on separate dates for owner,
       * instructors, and students. Job type is used to distinguish the
       * intended recipient group.
       */

      // always send results email to eval.getOwner()
      Set<String> userIdsSet = new HashSet<String>();
      if (jobType.equals(EvalConstants.JOB_TYPE_VIEWABLE)) {
        userIdsSet.add(eval.getOwner());
      }

      // if results are not private
      if (!EvalConstants.SHARING_PRIVATE.equals(eval.getResultsSharing())) {
        // at present, includeAdmins is always true
        if (includeAdmins
            && evalAssignGroup.getInstructorsViewResults().booleanValue()
            && jobType.equals(EvalConstants.JOB_TYPE_VIEWABLE_INSTRUCTORS)) {
          userIdsSet.addAll(
              commonLogic.getUserIdsForEvalGroup(evalGroupId, EvalConstants.PERM_BE_EVALUATED));
        }

        // at present, includeEvaluatees is always true
        if (includeEvaluatees
            && evalAssignGroup.getStudentsViewResults().booleanValue()
            && jobType.equals(EvalConstants.JOB_TYPE_VIEWABLE_STUDENTS)) {
          userIdsSet.addAll(
              commonLogic.getUserIdsForEvalGroup(evalGroupId, EvalConstants.PERM_TAKE_EVALUATION));
        }
      }

      if (userIdsSet.size() > 0) {
        // turn the set into an array
        String[] toUserIds = (String[]) userIdsSet.toArray(new String[] {});
        log.debug(
            "Found "
                + toUserIds.length
                + " users ("
                + toUserIds
                + ") to send "
                + EvalConstants.EMAIL_TEMPLATE_RESULTS
                + " notification to for available evaluation ("
                + evaluationId
                + ") and group ("
                + evalGroupId
                + ")");

        // replace the text of the template with real values
        Map<String, String> replacementValues = new HashMap<String, String>();
        replacementValues.put("HelpdeskEmail", from);
        String message =
            makeEmailMessage(emailTemplate.getMessage(), eval, group, replacementValues);
        String subject =
            makeEmailMessage(emailTemplate.getSubject(), eval, group, replacementValues);

        // send the actual emails for this evalGroupId
        String[] emailAddresses =
            commonLogic.sendEmailsToUsers(from, toUserIds, subject, message, true);
        log.info(
            "Sent evaluation results message to "
                + emailAddresses.length
                + " users (attempted to send to "
                + toUserIds.length
                + ")");
        // store sent emails to return
        for (int j = 0; j < emailAddresses.length; j++) {
          sentEmails.add(emailAddresses[j]);
        }
        commonLogic.registerEntityEvent(EVENT_EMAIL_RESULTS, eval);
      }
    }
    return (String[]) sentEmails.toArray(new String[] {});
  }
  /* (non-Javadoc)
   * @see org.sakaiproject.evaluation.logic.EvalEmailsLogic#sendEvalCreatedNotifications(java.lang.Long, boolean)
   */
  public String[] sendEvalCreatedNotifications(Long evaluationId, boolean includeOwner) {
    log.debug("evaluationId: " + evaluationId + ", includeOwner: " + includeOwner);

    EvalEvaluation eval = getEvaluationOrFail(evaluationId);
    String from = getFromEmailOrFail(eval);
    EvalEmailTemplate emailTemplate =
        getEmailTemplateOrFail(EvalConstants.EMAIL_TEMPLATE_CREATED, evaluationId);

    Map<String, String> replacementValues = new HashMap<String, String>();
    replacementValues.put("HelpdeskEmail", from);

    // setup the opt-in, opt-out, and add questions variables
    int addItems = ((Integer) settings.get(EvalSettings.ADMIN_ADD_ITEMS_NUMBER)).intValue();
    if (!eval.getInstructorOpt().equals(EvalConstants.INSTRUCTOR_REQUIRED) || (addItems > 0)) {
      if (eval.getInstructorOpt().equals(EvalConstants.INSTRUCTOR_OPT_IN)) {
        // if eval is opt-in notify instructors that they may opt in
        replacementValues.put("ShowOptInText", "true");
      } else if (eval.getInstructorOpt().equals(EvalConstants.INSTRUCTOR_OPT_OUT)) {
        // if eval is opt-out notify instructors that they may opt out
        replacementValues.put("ShowOptOutText", "true");
      }
      if (addItems > 0) {
        // if eval allows instructors to add questions notify instructors they may add questions
        replacementValues.put("ShowAddItemsText", "true");
      }
    }

    String message = emailTemplate.getMessage();

    // get the associated groups for this evaluation
    Map<Long, List<EvalGroup>> evalGroups =
        evaluationService.getEvalGroupsForEval(new Long[] {evaluationId}, true, null);

    // only one possible map key so we can assume evaluationId
    List<EvalGroup> groups = evalGroups.get(evaluationId);
    if (log.isDebugEnabled()) {
      log.debug("Found " + groups.size() + " groups for new evaluation: " + evaluationId);
    }

    List<String> sentEmails = new ArrayList<String>();
    // loop through contexts and send emails to correct users in each evalGroupId
    for (int i = 0; i < groups.size(); i++) {
      EvalGroup group = (EvalGroup) groups.get(i);
      if (EvalConstants.GROUP_TYPE_INVALID.equals(group.type)) {
        continue; // skip processing for invalid groups
      }

      Set<String> userIdsSet =
          commonLogic.getUserIdsForEvalGroup(group.evalGroupId, EvalConstants.PERM_BE_EVALUATED);
      // add in the owner or remove them based on the setting
      if (includeOwner) {
        userIdsSet.add(eval.getOwner());
      } else {
        if (userIdsSet.contains(eval.getOwner())) {
          userIdsSet.remove(eval.getOwner());
        }
      }

      // skip ahead if there is no one to send to
      if (userIdsSet.size() == 0) continue;

      // turn the set into an array
      String[] toUserIds = (String[]) userIdsSet.toArray(new String[] {});
      if (log.isDebugEnabled()) {
        log.debug(
            "Found "
                + toUserIds.length
                + " users ("
                + toUserIds
                + ") to send "
                + EvalConstants.EMAIL_TEMPLATE_CREATED
                + " notification to for new evaluation ("
                + evaluationId
                + ") and evalGroupId ("
                + group.evalGroupId
                + ")");
      }

      // replace the text of the template with real values
      message = makeEmailMessage(message, eval, group, replacementValues);
      String subject = makeEmailMessage(emailTemplate.getSubject(), eval, group, replacementValues);

      // send the actual emails for this evalGroupId
      String[] emailAddresses =
          commonLogic.sendEmailsToUsers(from, toUserIds, subject, message, true);
      log.info(
          "Sent evaluation created message to "
              + emailAddresses.length
              + " users (attempted to send to "
              + toUserIds.length
              + ")");
      // store sent emails to return
      for (int j = 0; j < emailAddresses.length; j++) {
        sentEmails.add(emailAddresses[j]);
      }
      commonLogic.registerEntityEvent(EVENT_EMAIL_CREATED, eval);
    }

    return (String[]) sentEmails.toArray(new String[] {});
  }
  /* (non-Javadoc)
   * @see org.sakaiproject.evaluation.logic.EvalEmailsLogic#sendEvalReminderNotifications(java.lang.Long, java.lang.String)
   */
  public String[] sendEvalReminderNotifications(Long evaluationId, String includeConstant) {
    log.debug("evaluationId: " + evaluationId + ", includeConstant: " + includeConstant);
    EvalUtils.validateEmailIncludeConstant(includeConstant);

    EvalEvaluation eval = getEvaluationOrFail(evaluationId);
    String from = getFromEmailOrFail(eval);
    EvalEmailTemplate emailTemplate =
        getEmailTemplateOrFail(EvalConstants.EMAIL_TEMPLATE_REMINDER, evaluationId);

    // get the associated eval groups for this evaluation
    // NOTE: this only returns the groups that should get emails, there is no need to do an
    // additional check
    // to see if the instructor has opted in in this case -AZ
    Map<Long, List<EvalGroup>> evalGroupIds =
        evaluationService.getEvalGroupsForEval(new Long[] {evaluationId}, false, null);

    // only one possible map key so we can assume evaluationId
    List<EvalGroup> groups = evalGroupIds.get(evaluationId);
    log.debug("Found " + groups.size() + " groups for available evaluation: " + evaluationId);

    List<String> sentEmails = new ArrayList<String>();
    // loop through groups and send emails to correct users in each
    for (int i = 0; i < groups.size(); i++) {
      EvalGroup group = (EvalGroup) groups.get(i);
      if (EvalConstants.GROUP_TYPE_INVALID.equals(group.type)) {
        continue; // skip processing for invalid groups
      }
      String evalGroupId = group.evalGroupId;

      Set<String> userIdsSet =
          evaluationService.getUserIdsTakingEvalInGroup(evaluationId, evalGroupId, includeConstant);
      if (userIdsSet.size() > 0) {
        // turn the set into an array
        String[] toUserIds = (String[]) userIdsSet.toArray(new String[] {});
        log.debug(
            "Found "
                + toUserIds.length
                + " users ("
                + toUserIds
                + ") to send "
                + EvalConstants.EMAIL_TEMPLATE_REMINDER
                + " notification to for available evaluation ("
                + evaluationId
                + ") and group ("
                + group.evalGroupId
                + ")");

        // replace the text of the template with real values
        Map<String, String> replacementValues = new HashMap<String, String>();
        replacementValues.put("HelpdeskEmail", from);
        String message =
            makeEmailMessage(emailTemplate.getMessage(), eval, group, replacementValues);
        String subject =
            makeEmailMessage(emailTemplate.getSubject(), eval, group, replacementValues);

        // send the actual emails for this evalGroupId
        String[] emailAddresses =
            commonLogic.sendEmailsToUsers(from, toUserIds, subject, message, true);
        log.info(
            "Sent evaluation reminder message to "
                + emailAddresses.length
                + " users (attempted to send to "
                + toUserIds.length
                + ")");
        // store sent emails to return
        for (int j = 0; j < emailAddresses.length; j++) {
          sentEmails.add(emailAddresses[j]);
        }
        commonLogic.registerEntityEvent(EVENT_EMAIL_REMINDER, eval);
      }
    }

    return (String[]) sentEmails.toArray(new String[] {});
  }