/**
   * Used by dismissed and missed states, to update parent alarm. This will either disable, delete
   * or reschedule parent alarm.
   *
   * @param context application context
   * @param instance to update parent for
   */
  private static void updateParentAlarm(Context context, AlarmInstance instance) {
    ContentResolver cr = context.getContentResolver();
    Alarm alarm = Alarm.getAlarm(cr, instance.mAlarmId);
    if (alarm == null) {
      LogUtils.e("Parent has been deleted with instance: " + instance.toString());
      return;
    }

    if (!alarm.daysOfWeek.isRepeating()) {
      if (alarm.deleteAfterUse) {
        LogUtils.i("Deleting parent alarm: " + alarm.id);
        Alarm.deleteAlarm(cr, alarm.id);
      } else {
        LogUtils.i("Disabling parent alarm: " + alarm.id);
        alarm.enabled = false;
        Alarm.updateAlarm(cr, alarm);
      }
    } else {
      // Schedule the next repeating instance after the current time
      AlarmInstance nextRepeatedInstance = alarm.createInstanceAfter(getCurrentTime());
      LogUtils.i(
          "Creating new instance for repeating alarm "
              + alarm.id
              + " at "
              + AlarmUtils.getFormattedTime(context, nextRepeatedInstance.getAlarmTime()));
      AlarmInstance.addInstance(cr, nextRepeatedInstance);
      registerInstance(context, nextRepeatedInstance, true);
    }
  }
  /**
   * This will set the alarm instance to the SNOOZE_STATE and update the application notifications
   * and schedule any state changes that need to occur in the future.
   *
   * @param context application context
   * @param instance to set state to
   */
  public static void setSnoozeState(
      final Context context, AlarmInstance instance, boolean showToast) {
    // Stop alarm if this instance is firing it
    AlarmService.stopAlarm(context, instance);

    // Calculate the new snooze alarm time
    String snoozeMinutesStr =
        PreferenceManager.getDefaultSharedPreferences(context)
            .getString(SettingsActivity.KEY_ALARM_SNOOZE, DEFAULT_SNOOZE_MINUTES);
    final int snoozeMinutes = Integer.parseInt(snoozeMinutesStr);
    Calendar newAlarmTime = Calendar.getInstance();
    newAlarmTime.add(Calendar.MINUTE, snoozeMinutes);

    // Update alarm state and new alarm time in db.
    LogUtils.v(
        "Setting snoozed state to instance "
            + instance.mId
            + " for "
            + AlarmUtils.getFormattedTime(context, newAlarmTime));
    instance.setAlarmTime(newAlarmTime);
    instance.mAlarmState = AlarmInstance.SNOOZE_STATE;
    AlarmInstance.updateInstance(context.getContentResolver(), instance);

    // Setup instance notification and scheduling timers
    AlarmNotifications.showSnoozeNotification(context, instance);
    scheduleInstanceStateChange(
        context, instance.getAlarmTime(), instance, AlarmInstance.FIRED_STATE);

    // Display the snooze minutes in a toast.
    if (showToast) {
      final Handler mainHandler = new Handler(context.getMainLooper());
      final Runnable myRunnable =
          new Runnable() {
            @Override
            public void run() {
              String displayTime =
                  String.format(
                      context
                          .getResources()
                          .getQuantityText(R.plurals.alarm_alert_snooze_set, snoozeMinutes)
                          .toString(),
                      snoozeMinutes);
              Toast.makeText(context, displayTime, Toast.LENGTH_LONG).show();
            }
          };
      mainHandler.post(myRunnable);
    }

    // Instance time changed, so find next alarm that will fire and notify system
    updateNextAlarm(context);
  }
  /** Used in pre-L devices, where "next alarm" is stored in system settings. */
  private static void updateNextAlarmInSystemSettings(Context context, AlarmInstance nextAlarm) {
    // Send broadcast message so pre-L AppWidgets will recognize an update
    String timeString = "";
    boolean showStatusIcon = false;
    if (nextAlarm != null) {
      timeString = AlarmUtils.getFormattedTime(context, nextAlarm.getAlarmTime());
      showStatusIcon = true;
    }

    // Set and notify next alarm text to system
    LogUtils.i("Displaying next alarm time: \'" + timeString + '\'');
    // Write directly to NEXT_ALARM_FORMATTED in all pre-L versions
    Settings.System.putString(
        context.getContentResolver(), Settings.System.NEXT_ALARM_FORMATTED, timeString);
    Intent alarmChanged = new Intent(SYSTEM_ALARM_CHANGE_ACTION);
    alarmChanged.putExtra("alarmSet", showStatusIcon);
    context.sendBroadcast(alarmChanged);
  }
    @Override
    public void scheduleInstanceStateChange(
        Context context, Calendar time, AlarmInstance instance, int newState) {
      final long timeInMillis = time.getTimeInMillis();
      LogUtils.v(
          "Scheduling state change %d to instance %d at %s (%d)",
          newState, instance.mId, AlarmUtils.getFormattedTime(context, time), timeInMillis);
      final Intent stateChangeIntent =
          createStateChangeIntent(context, ALARM_MANAGER_TAG, instance, newState);
      // Treat alarm state change as high priority, use foreground broadcasts
      stateChangeIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
      PendingIntent pendingIntent =
          PendingIntent.getBroadcast(
              context, instance.hashCode(), stateChangeIntent, PendingIntent.FLAG_UPDATE_CURRENT);

      final AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
      if (Utils.isKitKatOrLater()) {
        am.setExact(AlarmManager.RTC_WAKEUP, timeInMillis, pendingIntent);
      } else {
        am.set(AlarmManager.RTC_WAKEUP, timeInMillis, pendingIntent);
      }
    }