/**
   * Returns a map where the key is a user and the value is a naturally-sorted list of results they
   * should receive.
   *
   * @param results all the validation run results, in a sorted set
   * @return map of users to results
   */
  private Map<User, SortedSet<ValidationResult>> getUserResults(
      SortedSet<ValidationResult> results) {
    Map<User, SortedSet<ValidationResult>> userResults = new HashMap<>();

    for (ValidationResult result : results) {
      for (ValidationRuleGroup ruleGroup : result.getValidationRule().getGroups()) {
        if (ruleGroup.hasUserGroupsToAlert()) {
          for (UserGroup userGroup : ruleGroup.getUserGroupsToAlert()) {
            for (User user : userGroup.getMembers()) {
              if (!ruleGroup.isAlertByOrgUnits()
                  || canUserAccessSource(user, result.getOrgUnit())) {
                SortedSet<ValidationResult> resultSet = userResults.get(user);

                if (resultSet == null) {
                  resultSet = new TreeSet<>();

                  userResults.put(user, resultSet);
                }

                resultSet.add(result);
              }
            }
          }
        }
      }
    }
    return userResults;
  }
  public void postObject(
      HttpServletResponse response, HttpServletRequest request, Message message) {
    List<User> users = new ArrayList<User>(message.getUsers());
    message.getUsers().clear();

    for (OrganisationUnit ou : message.getOrganisationUnits()) {
      OrganisationUnit organisationUnit = organisationUnitService.getOrganisationUnit(ou.getUid());

      if (organisationUnit == null) {
        ContextUtils.conflictResponse(response, "Organisation Unit does not exist: " + ou.getUid());
        return;
      }

      message.getUsers().addAll(organisationUnit.getUsers());
    }

    for (User u : users) {
      User user = userService.getUser(u.getUid());

      if (user == null) {
        ContextUtils.conflictResponse(response, "User does not exist: " + u.getUid());
        return;
      }

      message.getUsers().add(user);
    }

    for (UserGroup ug : message.getUserGroups()) {
      UserGroup userGroup = userGroupService.getUserGroup(ug.getUid());

      if (userGroup == null) {
        ContextUtils.conflictResponse(response, "User Group does not exist: " + ug.getUid());
        return;
      }

      message.getUsers().addAll(userGroup.getMembers());
    }

    if (message.getUsers().isEmpty()) {
      ContextUtils.conflictResponse(response, "No recipients selected.");
      return;
    }

    String metaData =
        MessageService.META_USER_AGENT + request.getHeader(ContextUtils.HEADER_USER_AGENT);

    int id =
        messageService.sendMessage(
            message.getSubject(), message.getText(), metaData, message.getUsers());

    MessageConversation conversation = messageService.getMessageConversation(id);

    ContextUtils.createdResponse(
        response,
        "Message conversation created",
        MessageConversationController.RESOURCE_PATH + "/" + conversation.getUid());
  }
  @SuppressWarnings("unchecked")
  public String execute() {
    gatewayId = transportService.getDefaultGateway();

    if (gatewayId == null || gatewayId.trim().length() == 0) {
      message = i18n.getString("please_select_a_gateway_type_to_send_sms");

      return ERROR;
    }

    if (smsMessage == null || smsMessage.trim().length() == 0) {
      message = i18n.getString("no_message");

      return ERROR;
    }

    User currentUser = currentUserService.getCurrentUser();

    if (sendTarget != null && sendTarget.equals("phone")) {
      try {
        ObjectMapper mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY);
        mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        recipients = mapper.readValue(recipients.iterator().next(), Set.class);
      } catch (JsonParseException e) {
        e.printStackTrace();
      } catch (JsonMappingException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }

      message =
          messageSender.sendMessage(
              smsSubject, smsMessage, currentUser, true, recipients, gatewayId);
    } else if (sendTarget.equals("userGroup")) {
      UserGroup group = userGroupService.getUserGroup(userGroup);

      if (group == null) {
        message = i18n.getString("selected_user_group_is_unavailable");

        return ERROR;
      }

      if (group.getMembers() == null || group.getMembers().isEmpty()) {
        message = i18n.getString("selected_user_group_has_no_member");

        return ERROR;
      }

      message =
          messageSender.sendMessage(
              smsSubject, smsMessage, currentUser, false, group.getMembers(), gatewayId);
    } else if (sendTarget.equals("user")) {
      Collection<OrganisationUnit> units =
          selectionTreeManager.getReloadedSelectedOrganisationUnits();

      if (units != null && !units.isEmpty()) {
        Set<User> users = new HashSet<User>();

        for (OrganisationUnit unit : units) {
          users.addAll(unit.getUsers());
        }

        if (users.isEmpty()) {
          message = i18n.getString("there_is_no_user_assigned_to_selected_units");

          return ERROR;
        }

        message =
            messageSender.sendMessage(smsSubject, smsMessage, currentUser, false, users, gatewayId);
      }
    } else if (sendTarget.equals("unit")) {
      for (OrganisationUnit unit : selectionTreeManager.getSelectedOrganisationUnits()) {
        if (unit.getPhoneNumber() != null && !unit.getPhoneNumber().isEmpty()) {
          recipients.add(unit.getPhoneNumber());
        }
      }

      if (recipients.isEmpty()) {
        message = i18n.getString("selected_units_have_no_phone_number");

        return ERROR;
      }

      message =
          messageSender.sendMessage(
              smsSubject, smsMessage, currentUser, true, recipients, gatewayId);
    } else {
      Patient patient = null;
      Set<String> phones = new HashSet<String>();

      try {
        ObjectMapper mapper = new ObjectMapper().setVisibility(JsonMethod.FIELD, Visibility.ANY);
        mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        recipients = mapper.readValue(recipients.iterator().next(), Set.class);
      } catch (JsonParseException e) {
        e.printStackTrace();
      } catch (JsonMappingException e) {
        e.printStackTrace();
      } catch (IOException e) {
        e.printStackTrace();
      }

      for (String patientId : recipients) {
        patient = patientService.getPatient(Integer.parseInt(patientId));

        if (patient != null
            && patient.getPhoneNumber() != null
            && !patient.getPhoneNumber().isEmpty()) {
          phones.add(patient.getPhoneNumber());
        }
      }

      if (phones.isEmpty()) {
        message = i18n.getString("selected_persons_have_no_phone_number");

        return ERROR;
      }

      message =
          messageSender.sendMessage(smsSubject, smsMessage, currentUser, true, phones, gatewayId);
    }

    if (message != null && !message.equals("success")) {
      message = i18n.getString(message);

      return ERROR;
    }

    return SUCCESS;
  }