public static void unregisterDevicePushNotifications(final Context ctx) {
    com.wordpress.rest.RestRequest.Listener listener =
        new RestRequest.Listener() {
          @Override
          public void onResponse(JSONObject jsonObject) {
            AppLog.d(T.NOTIFS, "Unregister token action succeeded");
            SharedPreferences.Editor editor =
                PreferenceManager.getDefaultSharedPreferences(ctx).edit();
            editor.remove(WPCOM_PUSH_DEVICE_SERVER_ID);
            editor.remove(WPCOM_PUSH_DEVICE_NOTIFICATION_SETTINGS);
            editor.remove(WPCOM_PUSH_DEVICE_UUID);
            editor.commit();
          }
        };
    RestRequest.ErrorListener errorListener =
        new RestRequest.ErrorListener() {
          @Override
          public void onErrorResponse(VolleyError volleyError) {
            AppLog.e(T.NOTIFS, "Unregister token action failed", volleyError);
          }
        };

    SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(ctx);
    String deviceID = settings.getString(WPCOM_PUSH_DEVICE_SERVER_ID, null);
    if (TextUtils.isEmpty(deviceID)) {
      return;
    }
    WordPress.getRestClientUtils()
        .post("/devices/" + deviceID + "/delete", listener, errorListener);
  }
  /**
   * reply to an individual comment that came from a notification - this differs from
   * submitReplyToComment() in that it enables responding to a reply to a comment this user made on
   * someone else's blog
   */
  static void submitReplyToCommentNote(
      final Note note, final String replyText, final CommentActionListener actionListener) {
    if (note == null || TextUtils.isEmpty(replyText)) {
      if (actionListener != null) actionListener.onActionResult(false);
      return;
    }

    RestRequest.Listener listener =
        new RestRequest.Listener() {
          @Override
          public void onResponse(JSONObject jsonObject) {
            if (actionListener != null) actionListener.onActionResult(true);
          }
        };
    RestRequest.ErrorListener errorListener =
        new RestRequest.ErrorListener() {
          @Override
          public void onErrorResponse(VolleyError volleyError) {
            if (volleyError != null) AppLog.e(T.COMMENTS, volleyError.getMessage(), volleyError);
            if (actionListener != null) actionListener.onActionResult(false);
          }
        };

    Note.Reply reply = note.buildReply(replyText);
    WordPress.getRestClientUtils().replyToComment(reply, listener, errorListener);
  }
  private void fetchCurrentTheme(final int page) {
    final String siteId = getBlogId();

    WordPress.getRestClientUtils()
        .getCurrentTheme(
            siteId,
            new Listener() {
              @Override
              public void onResponse(JSONObject response) {
                try {
                  Theme theme = Theme.fromJSON(response);
                  if (theme != null) {
                    WordPress.wpDB.setCurrentTheme(siteId, theme.getThemeId());
                    setRefreshing(false, page);
                  }
                } catch (JSONException e) {
                  AppLog.e(T.THEMES, e);
                }
              }
            },
            new ErrorListener() {
              @Override
              public void onErrorResponse(VolleyError response) {}
            });
  }
  public static void registerDeviceForPushNotifications(final Context ctx, String token) {
    SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(ctx);
    String uuid = settings.getString(WPCOM_PUSH_DEVICE_UUID, null);
    if (uuid == null) return;

    String deviceName = DeviceUtils.getInstance().getDeviceName(ctx);
    Map<String, String> contentStruct = new HashMap<String, String>();
    contentStruct.put("device_token", token);
    contentStruct.put("device_family", "android");
    contentStruct.put("app_secret_key", NotificationUtils.getAppPushNotificationsName());
    contentStruct.put("device_name", deviceName);
    contentStruct.put("device_model", Build.MANUFACTURER + " " + Build.MODEL);
    contentStruct.put("app_version", WordPress.versionName);
    contentStruct.put("os_version", android.os.Build.VERSION.RELEASE);
    contentStruct.put("device_uuid", uuid);
    com.wordpress.rest.RestRequest.Listener listener =
        new RestRequest.Listener() {
          @Override
          public void onResponse(JSONObject jsonObject) {
            AppLog.d(T.NOTIFS, "Register token action succeeded");
            try {
              String deviceID = jsonObject.getString("ID");
              if (deviceID == null) {
                AppLog.e(
                    T.NOTIFS,
                    "Server response is missing of the device_id. Registration skipped!!");
                return;
              }
              SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(ctx);
              SharedPreferences.Editor editor = settings.edit();
              editor.putString(WPCOM_PUSH_DEVICE_SERVER_ID, deviceID);
              JSONObject settingsJSON = jsonObject.getJSONObject("settings");
              editor.putString(WPCOM_PUSH_DEVICE_NOTIFICATION_SETTINGS, settingsJSON.toString());
              editor.commit();
              AppLog.d(T.NOTIFS, "Server response OK. The device_id : " + deviceID);
            } catch (JSONException e1) {
              AppLog.e(T.NOTIFS, "Server response is NOT ok. Registration skipped!!", e1);
            }
          }
        };
    RestRequest.ErrorListener errorListener =
        new RestRequest.ErrorListener() {
          @Override
          public void onErrorResponse(VolleyError volleyError) {
            AppLog.e(T.NOTIFS, "Register token action failed", volleyError);
          }
        };

    WordPress.getRestClientUtils()
        .post("/devices/new", contentStruct, null, listener, errorListener);
  }
  @Override
  public void onActivateThemeClicked(String themeId, final Fragment fragment) {
    final String siteId = getBlogId();
    if (themeId == null) {
      themeId = mPreviewFragment.getThemeId();
    }

    final String newThemeId = themeId;
    final WeakReference<ThemeBrowserActivity> ref = new WeakReference<ThemeBrowserActivity>(this);
    mIsActivatingTheme = true;
    final int page = mViewPager.getCurrentItem();
    WordPress.getRestClientUtils()
        .setTheme(
            siteId,
            themeId,
            new Listener() {
              @Override
              public void onResponse(JSONObject arg0) {
                mIsActivatingTheme = false;
                Toast.makeText(
                        ThemeBrowserActivity.this, R.string.theme_set_success, Toast.LENGTH_LONG)
                    .show();

                WordPress.wpDB.setCurrentTheme(siteId, newThemeId);
                if (mDetailsFragment != null) {
                  mDetailsFragment.onThemeActivated(true);
                }
                setRefreshing(false, page);

                if (ref.get() != null && mIsRunning && fragment instanceof ThemePreviewFragment) {
                  FragmentManager fm = ref.get().getSupportFragmentManager();

                  if (fm.getBackStackEntryCount() > 0) {
                    fm.popBackStack();
                    setupBaseLayout();
                    invalidateOptionsMenu();
                  }
                }
              }
            },
            new ErrorListener() {
              @Override
              public void onErrorResponse(VolleyError arg0) {
                mIsActivatingTheme = false;
                if (mDetailsFragment != null && mDetailsFragment.isVisible())
                  mDetailsFragment.onThemeActivated(false);
                if (ref.get() != null)
                  Toast.makeText(ref.get(), R.string.theme_set_failed, Toast.LENGTH_LONG).show();
              }
            });
  }
  public void fetchThemes(final int page) {
    if (mFetchingThemes) {
      return;
    }
    String siteId = getBlogId();
    mFetchingThemes = true;
    WordPress.getRestClientUtils()
        .getThemes(
            siteId,
            0,
            0,
            new Listener() {
              @Override
              public void onResponse(JSONObject response) {
                new FetchThemesTask(page).execute(response);
              }
            },
            new ErrorListener() {
              @Override
              public void onErrorResponse(VolleyError response) {
                if (response.toString().equals(AuthFailureError.class.getName())) {
                  String errorTitle = getString(R.string.theme_auth_error_title);
                  String errorMsg = getString(R.string.theme_auth_error_message);

                  if (mIsRunning) {
                    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                    WPAlertDialogFragment fragment =
                        WPAlertDialogFragment.newAlertDialog(errorMsg, errorTitle);
                    ft.add(fragment, "alert");
                    ft.commitAllowingStateLoss();
                  }
                  AppLog.d(T.THEMES, "Failed to fetch themes: failed authenticate user");
                } else {
                  Toast.makeText(
                          ThemeBrowserActivity.this, R.string.theme_fetch_failed, Toast.LENGTH_LONG)
                      .show();
                  AppLog.d(T.THEMES, "Failed to fetch themes: " + response.toString());
                }

                mFetchingThemes = false;
                setRefreshing(false, page);
              }
            });
  }
  public static void getPushNotificationSettings(
      Context context, RestRequest.Listener listener, RestRequest.ErrorListener errorListener) {
    if (!WordPress.hasValidWPComCredentials(context)) {
      return;
    }

    String gcmToken = GCMRegistrar.getRegistrationId(context);
    if (TextUtils.isEmpty(gcmToken)) {
      return;
    }

    SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
    String deviceID = settings.getString(WPCOM_PUSH_DEVICE_SERVER_ID, null);
    if (TextUtils.isEmpty(deviceID)) {
      AppLog.e(T.NOTIFS, "device_ID is null in preferences. Get device settings skipped.");
      return;
    }

    WordPress.getRestClientUtils().get("/device/" + deviceID, listener, errorListener);
  }
  public static void setPushNotificationSettings(Context context) {
    if (!WordPress.hasValidWPComCredentials(context)) {
      return;
    }

    String gcmToken = GCMRegistrar.getRegistrationId(context);
    if (TextUtils.isEmpty(gcmToken)) {
      return;
    }

    SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(context);
    String deviceID = settings.getString(WPCOM_PUSH_DEVICE_SERVER_ID, null);
    if (TextUtils.isEmpty(deviceID)) {
      AppLog.e(T.NOTIFS, "device_ID is null in preferences. Set device settings skipped.");
      return;
    }

    String settingsJson = settings.getString(WPCOM_PUSH_DEVICE_NOTIFICATION_SETTINGS, null);
    if (settingsJson == null) return;

    Gson gson = new Gson();
    Map<String, StringMap<String>> notificationSettings =
        gson.fromJson(settingsJson, HashMap.class);
    Map<String, Object> updatedSettings = new HashMap<String, Object>();
    if (notificationSettings == null) return;

    // Build the settings object to send back to WP.com
    StringMap<?> mutedBlogsMap = notificationSettings.get("muted_blogs");
    StringMap<?> muteUntilMap = notificationSettings.get("mute_until");
    ArrayList<StringMap<Double>> blogsList =
        (ArrayList<StringMap<Double>>) mutedBlogsMap.get("value");
    notificationSettings.remove("muted_blogs");
    notificationSettings.remove("mute_until");

    for (Map.Entry<String, StringMap<String>> entry : notificationSettings.entrySet()) {
      StringMap<String> setting = entry.getValue();
      updatedSettings.put(entry.getKey(), setting.get("value"));
    }

    if (muteUntilMap != null && muteUntilMap.get("value") != null) {
      updatedSettings.put("mute_until", muteUntilMap.get("value"));
    }

    ArrayList<StringMap<Double>> mutedBlogsList = new ArrayList<StringMap<Double>>();
    for (StringMap<Double> userBlog : blogsList) {
      if (MapUtils.getMapBool(userBlog, "value")) {
        mutedBlogsList.add(userBlog);
      }
    }

    if (updatedSettings.size() == 0 && mutedBlogsList.size() == 0) return;

    updatedSettings.put(
        "muted_blogs",
        mutedBlogsList); // If muted blogs list is unchanged we can even skip this assignment.

    Map<String, String> contentStruct = new HashMap<String, String>();
    contentStruct.put("device_token", gcmToken);
    contentStruct.put("device_family", "android");
    contentStruct.put("app_secret_key", NotificationUtils.getAppPushNotificationsName());
    contentStruct.put("settings", gson.toJson(updatedSettings));
    WordPress.getRestClientUtils().post("/device/" + deviceID, contentStruct, null, null, null);
  }