/**
   * Exposed as `POST /api/photos`.
   *
   * <p>Takes the following payload in the request body. Payload represents a Photo that should be
   * created. { "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>Returns the following JSON response representing the created Photo. { "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: 400: "Bad Request"
   * if the request is missing image data. 401: "Unauthorized request" (if certain parameters are
   * present in the request) 401: "Access token expired" (there is a logged in user, but he doesn't
   * have a refresh token and his access token is expiring in less than 100 seconds, get a new token
   * and retry) 500: "Error while writing app activity: " + error from client library.
   *
   * @see javax.servlet.http.HttpServlet#doPost( javax.servlet.http.HttpServletRequest,
   *     javax.servlet.http.HttpServletResponse)
   */
  @Override
  protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
    try {
      checkAuthorization(req);
      List<BlobKey> blobKeys = blobstoreService.getUploads(req).get("image");
      BlobKey imageKey = null;

      if (blobKeys != null) {
        imageKey = blobKeys.iterator().next();
      }

      if (imageKey == null) {
        sendError(resp, 400, "Missing image data.");
      }

      Long currentUserId = (Long) req.getSession().getAttribute(CURRENT_USER_SESSION_KEY);
      User author = ofy().load().type(User.class).id(currentUserId).get();
      GoogleCredential credential = this.getCredentialFromLoggedInUser(req);
      Photo photo = new Photo();
      photo.setOwnerUserId(author.getId());
      photo.setOwnerDisplayName(author.getGoogleDisplayName());
      photo.setOwnerProfilePhoto(author.getGooglePublicProfilePhotoUrl());
      photo.setOwnerProfileUrl(author.getGooglePublicProfileUrl());
      photo.setThemeId(Theme.getCurrentTheme().getId());
      photo.setThemeDisplayName(Theme.getCurrentTheme().getDisplayName());
      photo.setCreated(Calendar.getInstance().getTime());
      photo.setNumVotes(0);
      photo.setImageBlobKey(imageKey.getKeyString());
      ofy().save().entity(photo).now();
      ofy().clear();
      photo = ofy().load().type(Photo.class).id(photo.getId()).get();
      addPhotoToGooglePlusHistory(author, photo, credential);
      sendResponse(req, resp, photo);
    } catch (UserNotAuthorizedException e) {
      sendError(resp, 401, "Unauthorized request");
    } catch (MomentWritingException e) {
      sendError(resp, 500, "Error while writing app activity: " + e.getMessage());
    } catch (GoogleTokenExpirationException e) {
      sendError(resp, 401, "Access token expired");
    }
  }