@RequestMapping(method = RequestMethod.POST)
  public ModelAndView editProfile(ServletRequest request) throws Exception {
    Template tmpl = Template.getTemplate(request);

    if (!tmpl.isSessionAuthorized()) {
      throw new AccessViolationException("Not authorized");
    }

    String profile = tmpl.getNick();

    int topics = Integer.parseInt(request.getParameter("topics"));
    int messages = Integer.parseInt(request.getParameter("messages"));
    int tags = Integer.parseInt(request.getParameter("tags"));

    if (topics <= 0 || topics > 500) {
      throw new BadInputException("некорректное число тем");
    }

    if (messages <= 0 || messages > 1000) {
      throw new BadInputException("некорректное число сообщений");
    }

    if (tags <= 0 || tags > 100) {
      throw new BadInputException("некорректное число меток в облаке");
    }

    if (!DefaultProfile.getStyleList().contains(request.getParameter("style"))) {
      throw new BadInputException("неправльное название темы");
    }

    tmpl.getProf().setTopics(topics);
    tmpl.getProf().setMessages(messages);
    tmpl.getProf().setTags(tags);
    tmpl.getProf().setShowNewFirst("on".equals(request.getParameter("newfirst")));
    tmpl.getProf().setShowPhotos("on".equals(request.getParameter("photos")));
    tmpl.getProf().setHideAdsense("on".equals(request.getParameter("hideAdsense")));
    tmpl.getProf().setShowGalleryOnMain("on".equals(request.getParameter("mainGallery")));
    tmpl.getProf().setFormatMode(request.getParameter("format_mode"));
    tmpl.getProf().setStyle(request.getParameter("style")); // TODO убрать как только
    userDao.setStyle(tmpl.getCurrentUser(), request.getParameter("style"));

    tmpl.getProf().setShowSocial("on".equals(request.getParameter("showSocial")));

    String avatar = request.getParameter("avatar");

    if (!DefaultProfile.getAvatars().contains(avatar)) {
      throw new BadInputException("invalid avatar value");
    }

    tmpl.getProf().setAvatarMode(avatar);

    tmpl.getProf().setThreeColumnsOnMain("on".equals(request.getParameter("3column")));

    tmpl.getProf().setShowAnonymous("on".equals(request.getParameter("showanonymous")));
    tmpl.getProf().setUseHover("on".equals(request.getParameter("hover")));

    tmpl.writeProfile(profile);

    return new ModelAndView(new RedirectView("/"));
  }
  @RequestMapping("/people/{nick}/remarks")
  public ModelAndView showRemarks(
      ServletRequest request,
      @PathVariable String nick,
      @RequestParam(value = "offset", defaultValue = "0") int offset,
      @RequestParam(value = "sort", defaultValue = "0") int sortorder)
      throws Exception {
    Template tmpl = Template.getTemplate(request);
    if (!tmpl.isSessionAuthorized() || !tmpl.getCurrentUser().getNick().equals(nick)) {
      throw new AccessViolationException("Not authorized");
    }

    int count = userDao.getRemarkCount(tmpl.getCurrentUser());

    ModelAndView mv = new ModelAndView("view-remarks");

    int limit = tmpl.getProf().getMessages();

    if (count > 0) {
      if (offset >= count) {
        throw new UserErrorException("Offset is too long");
      }
      if (offset < 0) offset = 0;

      if (sortorder != 1) {
        sortorder = 0;
        mv.getModel().put("sortorder", "");
      } else {
        mv.getModel().put("sortorder", "&amp;sort=1");
      }

      List<Remark> remarks = userDao.getRemarkList(tmpl.getCurrentUser(), offset, sortorder, limit);
      List<PreparedRemark> preparedRemarks = prepareService.prepareRemarkList(remarks);

      mv.getModel().put("remarks", preparedRemarks);
    } else {
      mv.getModel().put("remarks", ImmutableList.of());
    }
    mv.getModel().put("offset", offset);
    mv.getModel().put("limit", limit);
    mv.getModel().put("hasMore", (count > (offset + limit)));

    return mv;
  }
  @RequestMapping("/tracker")
  public ModelAndView tracker(
      @RequestParam(value = "filter", defaultValue = "all") String filterAction,
      @RequestParam(value = "offset", required = false) Integer offset,
      HttpServletRequest request)
      throws Exception {

    if (offset == null) {
      offset = 0;
    } else {
      if (offset < 0 || offset > 300) {
        throw new UserErrorException("Некорректное значение offset");
      }
    }

    TrackerFilterEnum trackerFilter = getFilterValue(filterAction);

    Map<String, Object> params = new HashMap<>();
    params.put("mine", trackerFilter == TrackerFilterEnum.MINE);
    params.put("offset", offset);
    params.put("filter", trackerFilter.getValue());

    if (trackerFilter != TrackerFilterEnum.ALL) {
      params.put("addition_query", "&amp;filter=" + trackerFilter.getValue());
    } else {
      params.put("addition_query", "");
    }

    Calendar calendar = Calendar.getInstance();
    calendar.setTime(new Date());
    if (trackerFilter == TrackerFilterEnum.MINE) {
      calendar.add(Calendar.MONTH, -6);
    } else {
      calendar.add(Calendar.HOUR, -24);
    }
    Timestamp dateLimit = new Timestamp(calendar.getTimeInMillis());

    Template tmpl = Template.getTemplate(request);
    int messages = tmpl.getProf().getMessages();
    int topics = tmpl.getProf().getTopics();

    params.put("topics", topics);

    User user = tmpl.getCurrentUser();

    if (trackerFilter == TrackerFilterEnum.MINE) {
      if (!tmpl.isSessionAuthorized()) {
        throw new UserErrorException("Not authorized");
      }
      params.put("title", "Последние сообщения (мои темы)");
    } else {
      params.put("title", "Последние сообщения");
    }
    params.put(
        "msgs", trackerDao.getTrackAll(trackerFilter, user, dateLimit, topics, offset, messages));

    if (tmpl.isModeratorSession() && trackerFilter != TrackerFilterEnum.MINE) {
      params.put("newUsers", userDao.getNewUsers());
      params.put("deleteStats", deleteInfoDao.getRecentStats());
    }

    return new ModelAndView("tracker", params);
  }