/**
   * Set up volunteer's displayName in patient object
   *
   * @param p patient
   * @param who volunteer1 or volunteer2 in patient
   */
  private void setVolunteerDisplayName(Patient p, String who) {
    try {
      statement =
          con.prepareStatement("SELECT firstname, lastname FROM volunteers WHERE volunteer_ID=?");
      if (who.equals("volunteer1")) statement.setInt(1, p.getVolunteer());
      else statement.setInt(1, p.getPartner());
      ResultSet rs = statement.executeQuery();
      while (rs.next()) {
        StringBuilder sb = new StringBuilder();
        if (!Utils.isNullOrEmpty(rs.getString("firstname"))) {
          sb.append(rs.getString("firstname"));
          sb.append(" ");
        }

        if (rs.getString("lastname") != null) {
          sb.append(rs.getString("lastname"));
        }

        if (who.equals("volunteer1")) {
          if (!Utils.isNullOrEmpty(sb.toString())) p.setVolunteerName(sb.toString());
          else p.setVolunteerName("");

        } else {
          if (!Utils.isNullOrEmpty(sb.toString())) p.setPartnerName(sb.toString());
          else p.setPartnerName("");
        }
      }
    } catch (SQLException e) {
      System.out.println("Error: Failed to create Patient object");
      e.printStackTrace();
    }
  }
  /** @return a list of patients who have availability */
  public List<Patient> getAllPatientsWithAvailability() {
    List<Patient> patients = getAllPatients();
    List<Patient> aList = new ArrayList<Patient>();
    String pAvailability;

    for (Patient p : patients) {
      pAvailability = p.getAvailability();

      if ((!Utils.isNullOrEmpty(pAvailability))
          && (!pAvailability.equals("1non,2non,3non,4non,5non"))) aList.add(p);
    }

    return aList;
  }
  /**
   * Creates a Patient object from a database query
   *
   * @param result The ResultSet from the database query
   * @return The Patient object
   */
  private Patient createFromSearch(ResultSet result) {
    Patient p = new Patient();
    try {
      p.setPatientID(result.getInt("patient_ID"));
      p.setFirstName(result.getString("firstname"));
      p.setLastName(result.getString("lastname"));
      p.setPreferredName(result.getString("preferredname"));
      // set gender
      String gender = result.getString("gender");
      if ("M".equals(gender)) p.setGender("Male");
      else if ("F".equals(gender)) p.setGender("Female");
      else p.setGender("Other");
      // set clinic
      String clinicCode = result.getString("clinic");
      p.setClinic(clinicCode);
      p.setClinicName(Utils.getClinicName(clinicCode));

      p.setVolunteer(result.getInt("volunteer"));
      p.setNotes(result.getString("notes"));
      p.setAvailability(result.getString("availability"));
      p.setAlerts(result.getString("alerts"));

      String myOscarVerfied = result.getString("myoscar_verified");
      p.setMyoscarVerified(myOscarVerfied);
      // set myoscar authentication for display in client's detail page
      if ("1".equals(myOscarVerfied)) p.setMyOscarAuthentication("Authenticated");
      else p.setMyOscarAuthentication("Not Authenticated");
      p.setPartner(result.getInt("volunteer2"));
      // Set volunteer name and partner name
      setVolunteerDisplayName(p, "volunteer1");
      setVolunteerDisplayName(p, "volunteer2");

    } catch (SQLException e) {
      System.out.println("Error: Failed to create Patient object");
      e.printStackTrace();
    }
    return p;
  }
  /** @return the next url to go to, excluding contextPath */
  public static ModelAndView execute(
      HttpServletRequest request,
      String documentId,
      TapestryPHRSurvey currentSurvey,
      PHRSurvey templateSurvey)
      throws Exception {
    ModelAndView m = new ModelAndView();
    final String questionId = request.getParameter("questionid");
    String direction = request.getParameter("direction");
    String observerNotes = request.getParameter("observernote");

    if (direction == null) direction = "forward";

    if (documentId == null) {
      logger.error("no selected survey? documentId=" + documentId);
      m.setViewName("failed");
      return m;
    }

    String[] answerStrs = request.getParameterValues("answer");

    String nextQuestionId = questionId;
    // if requested survey does not exist
    if (currentSurvey == null) {
      logger.error("Cannot find requested survey. documentId=" + documentId);
      m.setViewName("failed");
      return m;
    }
    // if requested survey is completed
    if (currentSurvey.isComplete()) logger.error("trying to complete already completed survey?");

    boolean saved = false;

    // if starting/continuing survey, clear session
    if (questionId == null) {
      // if just starting/continuing(from before) the survey, direct to last question
      String lastQuestionId;

      if (currentSurvey.getQuestions().size() == 0) {
        boolean moreQuestions = addNextQuestion(null, currentSurvey, templateSurvey);
        if (!moreQuestions) {
          logger.error("Survey has no questions?");
          m.setViewName("failed");
          return m;
        }
      }

      if (currentSurvey.isComplete()) { // if complete show first question		
        lastQuestionId = currentSurvey.getQuestions().get(0).getId();
        m.addObject("hideObservernote", true);
      } else { // if not complete show next question
        lastQuestionId =
            currentSurvey.getQuestions().get(currentSurvey.getQuestions().size() - 1).getId();
        // logic for displaying Observer Notes button
        if (isFirstQuestionId(lastQuestionId, '0')) m.addObject("hideObservernote", true);
        else m.addObject("hideObservernote", false);
      }
      m.addObject("survey", currentSurvey);
      m.addObject("templateSurvey", templateSurvey);
      m.addObject("questionid", lastQuestionId);
      m.addObject("resultid", documentId);

      m.setViewName("/surveys/show_survey");

      return m;
    } // end of questionId == null;

    String errMsg = null;

    // if continuing survey (just submitted an answer)
    if (questionId != null && direction.equalsIgnoreCase("forward")) {
      if (currentSurvey
              .getQuestionById(questionId)
              .getQuestionType()
              .equals(SurveyQuestion.ANSWER_CHECK)
          && answerStrs == null) answerStrs = new String[0];

      if (answerStrs != null
          && (currentSurvey
                  .getQuestionById(questionId)
                  .getQuestionType()
                  .equals(SurveyQuestion.ANSWER_CHECK)
              || !answerStrs[0].equals(""))) {
        SurveyQuestion question = currentSurvey.getQuestionById(questionId);
        SurveyQuestion questionWithoutObserverNotes = currentSurvey.getQuestionById(questionId);

        // keep answers without obserbernotes for validation
        //				ArrayList<SurveyAnswer> answersWithoutObserverNotes =
        // convertToSurveyAnswers(answerStrs, questionWithoutObserverNotes);
        //
        //				//add observernotes into answer when there is no condition or non-number type input
        //				List<SurveyDirectionStatement> logicStatements = question.getNextQuestionLogic();
        //				String type = question.getQuestionType();

        String questionText = question.getQuestionText();

        if (!Utils.isNullOrEmpty(questionText)) {
          String separator = "/observernote/ ";
          StringBuffer sb = new StringBuffer();
          sb.append(questionText);
          sb.append(separator);
          sb.append(observerNotes);

          questionText = sb.toString();
          question.setQuestionText(questionText);
        }

        //				if (!Utils.isNullOrEmpty(type) && (!type.equalsIgnoreCase("number")) &&
        // (logicStatements.size() <= 1))
        //				{
        //					if (answerStrs.length == 1)
        //					{
        //						String content = answerStrs[0];
        //						String separator = "/observernote/ ";
        //						StringBuffer sb = new StringBuffer();
        //						sb.append(content);
        //						sb.append(separator);
        //						sb.append(observerNotes);
        //						answerStrs[0] = sb.toString();
        //					}
        //				}

        ArrayList<SurveyAnswer> answers = convertToSurveyAnswers(answerStrs, question);

        boolean goodAnswerFormat = true;
        if (answers == null) goodAnswerFormat = false;

        // check each answer for validation
        // if answer passes validation
        //			if (goodAnswerFormat && question.validateAnswers(answersWithoutObserverNotes))
        if (goodAnswerFormat && question.validateAnswers(answers)) {
          boolean moreQuestions;
          // see if the user went back (if current question the last question in user's question
          // profile)
          if (!currentSurvey
              .getQuestions()
              .get(currentSurvey.getQuestions().size() - 1)
              .equals(question)) {
            ArrayList<SurveyAnswer> existingAnswers =
                currentSurvey.getQuestionById(questionId).getAnswers();
            // if user hit back, and then forward, and answer wasn't changed
            if (StringUtils.join(answerStrs, ", ").equals(StringUtils.join(existingAnswers, ", "))
                || currentSurvey.isComplete()) {
              logger.debug("user hit back and went forward, no answer was changed");
              moreQuestions = true;
              // if the user hit "back" and changed the answer - remove all questions after it
            } else {
              ArrayList<SurveyQuestion> tempquestions =
                  new ArrayList<
                      SurveyQuestion>(); // Create a temp array list to transfer answered questions

              // remove all future answers
              logger.debug("user hit back and changed an answer");
              // clear all questions following it
              int currentSurveySize =
                  currentSurvey.getQuestions().size(); // stores number of questions
              int currentQuestionIndex =
                  currentSurvey.getQuestions().indexOf(question); // gets the current question index

              for (int i = currentQuestionIndex + 1; i < currentSurveySize; i++) {
                tempquestions.add(currentSurvey.getQuestions().get(currentQuestionIndex + 1));
                currentSurvey
                    .getQuestions()
                    .remove(
                        currentQuestionIndex
                            + 1); // goes through quesitons list and removes each question after it
              }
              // save answers modified/input by user into question
              question.setAnswers(answers);
              saved = true;
              // add new question
              moreQuestions = addNextQuestion(questionId, currentSurvey, templateSurvey);

              // check if old index and new index contain same questions in the same list
              int sizeofcurrentquestionslist =
                  currentSurvey
                      .getQuestions()
                      .size(); // Size of new getQuestions aftre removing future questions

              if (currentSurvey
                  .getQuestions()
                  .get(sizeofcurrentquestionslist - 1)
                  .getId()
                  .equals(tempquestions.get(0).getId())) {
                currentSurvey.getQuestions().remove(sizeofcurrentquestionslist - 1);
                for (int y = 0; y < tempquestions.size(); y++)
                  currentSurvey.getQuestions().add(tempquestions.get(y));
                moreQuestions = addNextQuestion(questionId, currentSurvey, templateSurvey);
              }
              // if same then replace temp list with new list
              // if not then add the one new item.
            }
            // if user didn't go back, and requesting the next question
          } else {
            logger.debug("user hit forward, and requested the next question");
            question.setAnswers(answers);
            saved = true;
            moreQuestions = addNextQuestion(questionId, currentSurvey, templateSurvey);
          }
          // finished survey
          if (!moreQuestions) {
            if (!currentSurvey.isComplete()) {
              SurveyAction.updateSurveyResult(currentSurvey);

              m.addObject("survey_completed", true);
              m.addObject("survey", currentSurvey);
              m.addObject("templateSurvey", templateSurvey);
              m.addObject("questionid", questionId);
              m.addObject("resultid", documentId);
              m.addObject("message", "SURVEY FINISHED - Please click END SURVEY");
              m.addObject("hideObservernote", false);
              m.setViewName("/surveys/show_survey");
              return m;
            } else {
              m.addObject("survey", currentSurvey);
              m.addObject("templateSurvey", templateSurvey);
              m.addObject("questionid", questionId);
              m.addObject("resultid", documentId);
              m.addObject("message", "End of Survey");
              m.addObject("hideObservernote", false);
              m.setViewName("/surveys/show_survey");
              return m;
            }
          }
          int questionIndex = currentSurvey.getQuestionIndexbyId(questionId);
          nextQuestionId = currentSurvey.getQuestions().get(questionIndex + 1).getId();
          logger.debug("Next question id: " + nextQuestionId);

          // save to indivo
          if (saved && questionIndex % SAVE_INTERVAL == 0 && !currentSurvey.isComplete())
            SurveyAction.updateSurveyResult(currentSurvey);

          // if answer fails validation
        } // end of validation answers
        else {
          m.addObject("survey", currentSurvey);
          m.addObject("templateSurvey", templateSurvey);
          m.addObject("questionid", questionId);
          m.addObject("resultid", documentId);

          if (question.getRestriction() != null
              && question.getRestriction().getInstruction() != null)
            m.addObject("message", question.getRestriction().getInstruction());
          m.addObject("hideObservernote", false);
          m.setViewName("/surveys/show_survey");
          return m;
        }
        // if answer not specified, and hit forward
      } else errMsg = "You must supply an answer";
    } // end of forward action
    else if (direction.equalsIgnoreCase("backward")) {
      int questionIndex = currentSurvey.getQuestionIndexbyId(questionId);
      if (questionIndex > 0)
        nextQuestionId = currentSurvey.getQuestions().get(questionIndex - 1).getId();
    }

    // backward to the description page(before the first qustion)
    if ((questionId != null)
        && ("backward".equals(direction))
        && (isFirstQuestionId(questionId, '0'))) m.addObject("hideObservernote", true);
    else m.addObject("hideObservernote", false);

    m.addObject("survey", currentSurvey);
    m.addObject("templateSurvey", templateSurvey);
    m.addObject("questionid", nextQuestionId);
    m.addObject("resultid", documentId);
    if (errMsg != null) m.addObject("message", errMsg);

    m.setViewName("/surveys/show_survey");
    return m;
  }