/**
   * Exposed as `GET /api/photos`.
   *
   * <p>Accepts the following request parameters.
   *
   * <p>'photoId': id of the requested photo. Will return a single Photo. 'themeId': id of a theme.
   * Will return the collection of photos for the specified theme. 'userId': id of the owner of the
   * photo. Will return the collection of photos for that user. The keyword ‘me’ can be used and
   * will be converted to the logged in user. Requires auth. 'friends': value evaluated to boolean,
   * if true will filter only photos from friends of the logged in user. Requires auth.
   *
   * <p>Returns the following JSON response representing a list of Photos.
   *
   * <p>[ { "id":0, "ownerUserId":0, "ownerDisplayName":"", "ownerProfileUrl":"",
   * "ownerProfilePhoto":"", "themeId":0, "themeDisplayName":"", "numVotes":0, "voted":false, //
   * Whether or not the current user has voted on this. "created":0, "fullsizeUrl":"",
   * "thumbnailUrl":"", "voteCtaUrl":"", // URL for Vote interactive post button.
   * "photoContentUrl":"" // URL for Google crawler to hit to get info. }, ... ]
   *
   * <p>Issues the following errors along with corresponding HTTP response codes: 401: "Unauthorized
   * request" (if certain parameters are present in the request)
   *
   * @see javax.servlet.http.HttpServlet#doGet( javax.servlet.http.HttpServletRequest,
   *     javax.servlet.http.HttpServletResponse)
   */
  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
    try {
      BASE_URL = getBaseUrlFromRequest(req);
      String photoId = req.getParameter("photoId");
      String themeId = req.getParameter("themeId");
      String userIdParam = req.getParameter("userId");
      Long userId;
      Long currentUserId = null;
      if (req.getSession().getAttribute(CURRENT_USER_SESSION_KEY) != null) {
        currentUserId =
            Long.parseLong(req.getSession().getAttribute(CURRENT_USER_SESSION_KEY).toString());
      }
      boolean showFriends = Boolean.parseBoolean(req.getParameter("friends"));
      Query<Photo> q = ofy().load().type(Photo.class);
      if (photoId != null) {
        // Get the photo with the given ID and return it.
        Photo photo = q.filter("id", Long.parseLong(photoId)).first().get();
        sendResponse(req, resp, photo);
      } else {
        if (userIdParam != null) {
          // If the key word me is used, retrieve the current user from the session
          // The user needs to be authenticated to use 'me'
          if (userIdParam.equals("me")) {
            checkAuthorization(req);
            userId = currentUserId;
          } else {
            userId = Long.parseLong(userIdParam);
          }
          if (showFriends) {
            checkAuthorization(req);
            // Get all photos for the user's friends.
            User user = ofy().load().type(User.class).filterKey(User.key(userId)).first().get();
            List<Long> friendIds = user.getFriendIds();
            if (friendIds.size() > 30) {
              friendIds = friendIds.subList(0, 30);
            }
            if (friendIds.size() > 0) {
              q = q.filter("ownerUserId in", friendIds);
            } else {
              List<Photo> emptyList = new ArrayList<Photo>();
              // If there are no friends for the user, return an empty list
              sendResponse(req, resp, emptyList, "photohunt#photos");
              return;
            }
          } else {
            // Get all photos for the user.
            q = q.filter("ownerUserId", userId);
          }
        }
        if (themeId != null) {
          // Limit photos to just those for the given theme.
          q = q.filter("themeId", Long.parseLong(themeId));
        }
        List<Photo> photos = q.list();

        if (currentUserId != null) {
          // Build Hash map of voted photos
          List<Vote> userVotes =
              ofy().load().type(Vote.class).filter("ownerUserId", currentUserId).list();
          HashMap<Long, Boolean> userVotesTable = new HashMap<Long, Boolean>(userVotes.size());
          Iterator<Vote> votesIterator = userVotes.iterator();
          while (votesIterator.hasNext()) {
            userVotesTable.put(votesIterator.next().getPhotoId(), true);
          }
          // Check if user voted for each photo
          Iterator<Photo> photosIterator = photos.iterator();
          while (photosIterator.hasNext()) {
            Photo current = photosIterator.next();
            current.setVoted(userVotesTable.containsKey(current.getId()));
          }
        }
        sendResponse(req, resp, photos, "photohunt#photos");
      }
    } catch (UserNotAuthorizedException e) {
      sendError(resp, 401, "Unauthorized request");
    }
  }