/**
   * displays the profile data of the principal if no user is entered.
   *
   * @param theUser used to determine whether theUser is visiting his profile or an other profile.
   * @return the profile page.
   */
  @RequestMapping(value = "/profile", method = RequestMethod.GET)
  public ModelAndView profile(@RequestParam(required = false, name = "user") User theUser) {
    ModelAndView model = new ModelAndView("profile");
    User principal = userService.getPrincipalUser();
    String principalEmail = principal.getEmail();
    model.addObject("principalEmail", principalEmail);

    User user = principal;
    if (theUser != null) user = theUser;
    model.addObject(user);

    ArrayList<UserCourse> userCourses = new ArrayList<UserCourse>();
    userCourses = userCourseDao.findByUser(user);
    model.addObject("userCourses", userCourses);

    return model;
  }
  public Message sendContactDetails(User sender, User receiver) {
    assert (!sender.equals(receiver));
    Message contactDetails = new Message();

    String allContactInformations =
        new StringBuilder()
            .append("You can contact me as follows: \n")
            .append("<br>Full name: " + sender.getFirstName() + " " + sender.getLastName() + " \n")
            .append("<br>Email: " + sender.getEmail() + " \n")
            .append("<br>This message is auto generated. Do not answer")
            .toString();
    contactDetails.setMessageSubject("Contact Details");
    contactDetails.setMessageText(allContactInformations);
    contactDetails.setReceiver(receiver);
    contactDetails.setSender(sender);
    return send(contactDetails);
  }
  /**
   * shows profile of the user belonging to tutorEmailaddress.
   *
   * @param userCourseId to determine which request has to be sent when visiting an other student's
   *     profile.
   * @param studentsEmail of Tutor to be displayed
   * @return ModelView profile of the entered student that is teaching the course belonging to
   *     userCourseId.
   */
  @RequestMapping(value = "/profile", method = RequestMethod.POST)
  public ModelAndView postProfile(
      @RequestParam(required = false, defaultValue = "0", name = "userCourseId") long userCourseId,
      @RequestParam(required = false, name = "studentsEmail") String studentsEmail) {
    ModelAndView model = new ModelAndView("profile");
    User principal = userService.getPrincipalUser();
    User user = new User();

    if (studentsEmail != null) {
      user = userService.getUserByEmail(studentsEmail);
      userCourseId = 0;
    } else if (userCourseId != 0) {
      user = selectService.getUserFromUserCourseId(userCourseId);
      Request outgoingRequestWithUserCourse =
          requestDao.findByUserCourseIdAndStudent(userCourseId, principal);
      if (outgoingRequestWithUserCourse == null
          || (!outgoingRequestWithUserCourse.getIsAccepted()
              && !outgoingRequestWithUserCourse.getIsActiv())) {
        Course selectedCourse = selectService.getCourseFromUserCourseId(userCourseId);
        model.addObject("selectedCourse", selectedCourse);

        Subject selectedSubject = selectService.getSubjectFromUserCourseId(userCourseId);
        model.addObject("selectedSubject", selectedSubject);

        University selectedUniversity = selectService.getUniversityFromUserCourseId(userCourseId);
        model.addObject("selectedUniversity", selectedUniversity);
      } else {
        userCourseId = 0;
      }
    }

    model.addObject("userCourseId", userCourseId);
    model.addObject(user);

    String principalEmail = principal.getEmail();
    model.addObject("principalEmail", principalEmail);

    ArrayList<UserCourse> userCourses = new ArrayList<UserCourse>();
    userCourses = userCourseDao.findByUser(user);
    model.addObject("userCourses", userCourses);

    return model;
  }
  /**
   * Validates all changes and tries to save them to the database.
   *
   * @param principal the user that edited his profile.
   * @param signupForm the form which contains all information about the principal.
   * @param result contains error messages.
   * @param redirectAttributes used to add some attributes to the model.
   * @param session the current session especially containing the username.
   * @return the profile page if validations succeeded else returns the editProfile page with
   *     attached errors.
   */
  @RequestMapping(value = "/editProfile", method = RequestMethod.POST)
  public ModelAndView postProfile(
      Principal principal,
      @Validated(SignupForm.SignupValidatorGroup.class) SignupForm signupForm,
      BindingResult result,
      RedirectAttributes redirectAttributes,
      HttpSession session) {
    User user = userService.getPrincipalUser();
    signupForm.setEmail(user.getEmail());
    ModelAndView model;

    try {
      if (!signupForm.getPassword().equals(signupForm.getPasswordVerify())) {
        redirectAttributes.addFlashAttribute("passwordVerifyError", "Your passwords do not match!");
        redirectAttributes.addFlashAttribute("infoMessage", "Your passwords do not match!");
        return new ModelAndView("redirect:/editProfile");
      }
    } catch (Exception d) {
    }

    if (!result.hasErrors()) {
      try {
        User updatedUser = userService.saveFrom(signupForm, user);
        userService.createAndSaveUserCoursesFromForm(signupForm, user);
        redirectAttributes.addFlashAttribute(
            "infoMessage", "You successfully edited your profile!");
        session.setAttribute("username", updatedUser.getWholeName());

        model = new ModelAndView("redirect:/profile");
      } catch (InvalidUserException e) {
        model = new ModelAndView("editProfile");
        model.addObject("page_error", e.getMessage());
      }
    } else {
      model = new ModelAndView("editProfile");
      model.addObject("infoMessage", result.toString());
      System.out.println("Form has errors:\n" + result.toString());
    }
    return model;
  }
  @Test
  public void testTheBasicUserServiceUserSaving() {
    updatedUser = userService.saveFrom(signupForm);
    Iterator<UserRole> roleItr = updatedUser.getUserRole().iterator();

    assertEquals("Capitain", updatedUser.getFirstName());
    assertEquals("Awesome", updatedUser.getLastName());
    assertEquals("*****@*****.**", updatedUser.getEmail());
    assertEquals("I try to be .......... awesome...", updatedUser.getBiography());

    assertTrue(roleItr.hasNext());
    assertEquals("ROLE_USER", roleItr.next().getRole());
    assertFalse(roleItr.hasNext());

    assertTrue(updatedUser.isEnabled());
    assertTrue(passwordEncoder.matches("123456", updatedUser.getPassword()));

    assertEquals(
        expectedTimeSlotArrayList.toString(),
        updatedUser
            .getTimeSlots()
            .toString()); // don't compare references but string representation
  }