@RequestMapping("/admin")
  public String admin(
      HttpSession session,
      @RequestParam(required = false, value = "password") String password,
      @RequestParam(required = false, value = "view") String groupId,
      @RequestParam(required = false, value = "item") String itemId,
      Model model)
      throws Exception {

    if (password != null) session.setAttribute("campodejazayeri-admin-password", password);
    if (!"PASSWORD".equals(session.getAttribute("campodejazayeri-admin-password"))) {
      return "admin-authenticate";
    }

    ViewQuery query =
        new ViewQuery().designDocId("_design/groups").viewName("groups").includeDocs(true);
    List<InvitationGroup> groups = db.queryView(query, InvitationGroup.class);
    model.addAttribute("groups", groups);

    List<String> attendees = new ArrayList<String>();
    List<String> notAttending = new ArrayList<String>();
    for (InvitationGroup g : groups) {
      for (Invitee inv : g.getAttending()) attendees.add(g.getGroupName() + ": " + inv.getName());
      for (Invitee inv : g.getSaidNo()) notAttending.add(g.getGroupName() + ": " + inv.getName());
    }
    model.addAttribute("numAttendees", attendees.size());
    model.addAttribute("attendees", attendees);
    model.addAttribute("numNotAttending", notAttending.size());
    model.addAttribute("notAttending", notAttending);

    List<String> attendingWednesday = new ArrayList<String>();
    List<String> attendingThursday = new ArrayList<String>();
    List<String> attendingFriday = new ArrayList<String>();
    List<String> attendingRehearsal = new ArrayList<String>();
    List<String> attendingCeremony = new ArrayList<String>();
    List<String> attendingFiesta = new ArrayList<String>();

    for (InvitationGroup g : groups) {
      for (Invitee i : g.getInvitees()) {
        if (test(i.getAttendingWednesday())) attendingWednesday.add(format(g, i));
        if (test(i.getAttendingThursday())) attendingThursday.add(format(g, i));
        if (test(i.getAttendingFriday())) attendingFriday.add(format(g, i));
        if (test(i.getAttendingRehearsal())) attendingRehearsal.add(format(g, i));
        if (test(i.getAttendingCeremony())) attendingCeremony.add(format(g, i));
        if (test(i.getAttendingFiesta())) attendingFiesta.add(format(g, i));
      }
    }

    model.addAttribute("attendingWednesday", attendingWednesday);
    model.addAttribute("attendingThursday", attendingThursday);
    model.addAttribute("attendingFriday", attendingFriday);
    model.addAttribute("attendingRehearsal", attendingRehearsal);
    model.addAttribute("attendingCeremony", attendingCeremony);
    model.addAttribute("attendingFiesta", attendingFiesta);

    List<String> englishGroups = new ArrayList<String>();
    List<String> spanishGroups = new ArrayList<String>();
    for (InvitationGroup g : groups) {
      if ("en".equals(g.getLanguage()) && g.getAttending().size() > 0) {
        englishGroups.add(g.getId() + " - " + g.getGroupName());
      } else if ("es".equals(g.getLanguage()) && g.getAttending().size() > 0) {
        spanishGroups.add(g.getId() + " - " + g.getGroupName());
      }
    }
    model.addAttribute("englishComing", englishGroups);
    model.addAttribute("spanishComing", spanishGroups);

    if (groupId != null) {
      InvitationGroup group = db.get(InvitationGroup.class, groupId);
      model.addAttribute("group", group);
    }

    return null;
  }
  @RequestMapping("/sendmail")
  public String sendMail(
      @RequestParam(value = "emailLanguage", required = false) String language,
      @RequestParam(value = "whichPeople", required = false) String whichPeople,
      @RequestParam(value = "codes", required = false) String whichCodes,
      @RequestParam("subject") String subject,
      @RequestParam("body") String body,
      HttpSession session) {
    if (!StringUtils.hasText(whichCodes)
        && !(StringUtils.hasText(language) && StringUtils.hasText(whichPeople))) {
      throw new RuntimeException("Must give codes or language & which");
    }
    if (!StringUtils.hasText(subject)) throw new RuntimeException("Missing Subject");
    if (!StringUtils.hasText(body)) throw new RuntimeException("Missing Body");
    if (body.indexOf("$code") < 0 || body.indexOf("$name") < 0)
      throw new RuntimeException("Must have $code and $name");

    if (!"en".equals(language) && !"es".equals(language))
      throw new RuntimeException("Must specify language");

    List<String> codes = new LinkedList<String>();

    if (StringUtils.hasText(whichCodes)) {
      for (StringTokenizer st = new StringTokenizer(whichCodes, ", "); st.hasMoreTokens(); ) {
        String groupId = st.nextToken();
        InvitationGroup group = db.get(InvitationGroup.class, groupId);
        if (group != null) codes.add(groupId);
      }

    } else {
      ViewQuery query =
          new ViewQuery().designDocId("_design/groups").viewName("groups").includeDocs(true);
      List<InvitationGroup> groups = db.queryView(query, InvitationGroup.class);
      for (InvitationGroup group : groups) {
        if (!whichPeople.equals("all")) {
          boolean anyYes = false;
          boolean anyNo = false;
          boolean anyNotYet = false;
          for (Invitee inv : group.getInvitees()) {
            Boolean coming = inv.getAttendingCeremony();
            if (coming == null) {
              anyNotYet = true;
            } else if (coming) {
              anyYes = true;
            } else {
              anyNo = true;
            }
          }
          boolean treatAsYes = anyYes && !anyNotYet;

          if (whichPeople.equals("notYet") && !anyNotYet) {
            continue;
          } else if (whichPeople.equals("yes") && !treatAsYes) {
            continue;
          }
        }
        if (group.getLanguage() == null)
          throw new RuntimeException(
              "Group " + group.getId() + " (" + group.getGroupName() + ") doesn't have a language");
        if (group.getLanguage().equals(language)) codes.add(group.getId());
      }

      // codes.add("4659");
    }

    session.setAttribute("wedding-mail-to", codes);
    session.setAttribute("wedding-mail-subject", subject);
    session.setAttribute("wedding-mail-body", body);

    return "redirect:sendingmail";
  }