// this method is meant to be called just by AlarmReceiver class!
  public static void registerNextReminder(int currentVocabularyId, boolean doesTriggersNext) {
    Vocabulary current = Vocabularies.select(currentVocabularyId);
    if (current == null) {
      // exception occurred.
      return;
    }

    current.setLearned(true);
    Vocabularies.update(current);

    if (!doesTriggersNext) {
      return;
    }

    ReminderSettings settings = ReminderManager.getReminderSettings();

    Vocabulary next = Vocabularies.next(currentVocabularyId);
    if (next == null) {
      settings.setStatus(ReminderSettings.Status.FINISHED);
      settings.setReminder(null);
      ReminderManager.applyReminderSettings(settings);
      return;
    }

    Reminder reminder =
        new Reminder(next.getId(), null, next.getVocabulary(), next.getVocabEnglishDef(), true);
    int todaySentWords = getTodaySentWords();
    if (todaySentWords < settings.getWordsPerDay()) {
      Calendar calendar = Calendar.getInstance();
      calendar.add(Calendar.MINUTE, settings.getIntervals());

      reminder.setTime(calendar.getTime());
      settings.setReminder(reminder);
      addAlarm(reminder);

      applyReminderSettings(settings);
    } else {
      settings.setReminder(reminder);
      applyReminderSettings(settings);
      start(false);
    }
  }
  public static void stop() {
    setLastReminder(null);
    ReminderSettings settings = getReminderSettings();
    if (settings == null) {
      return;
    }

    if (settings.getReminder() != null) {
      removeAlarm(settings.getReminder().getVocabularyId());
    }

    settings.setStatus(ReminderSettings.Status.STOP);
    settings.setReminder(null);
    applyReminderSettings(settings);

    App.preferences.edit().putInt(SENT_WORDS_PER_DAY, 0).apply();

    Vocabularies.resetLearnedVocabularies();
  }
  public static void start(boolean isResume) {
    ReminderSettings settings = getReminderSettings();
    if (settings == null) {
      return;
    }

    if (settings.getStatus() != ReminderSettings.Status.RUNNING) {
      return;
    }

    Vocabulary vocabulary = Vocabularies.select(settings.getReminder().getVocabularyId());
    if (vocabulary == null) {
      return;
    }

    Calendar calendar = Calendar.getInstance();
    int today = calendar.get(Calendar.DAY_OF_WEEK);
    int[] timeParts = getTimeParts(settings.getStartTime());
    int nextDayOffset = 0;
    long elapsedMinutes = getElapsedMinutes(); // returns minutes passed from midnight till now
    int startTime = timeParts[0] * 60 + timeParts[1];

    Reminder nextReminder = settings.getReminder();
    Date now = new Date();
    if (nextReminder.getTime() == null) {
      isResume = false;
    } else if (nextReminder.getTime().after(now)) {
      SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMdd", Locale.getDefault());
      isResume = formatter.format(nextReminder.getTime()).equals(formatter.format(now));
    }

    // in case user manually resumes reminder
    if (isResume && settings.getWeekdays()[today - 1] && elapsedMinutes >= startTime) {
      Reminder lastReminder = getLastReminder();
      Vocabulary lastVocabulary = null;
      if (lastReminder != null) {
        lastVocabulary = Vocabularies.next(lastReminder.getVocabularyId());
      }

      // if there is no reminder at all or current vocabulary isn't in another group
      int todaySentWords = getTodaySentWords();
      if (lastVocabulary == null || todaySentWords < settings.getWordsPerDay()) {

        Vocabulary pivotal = lastVocabulary;
        if (pivotal == null) {
          pivotal = Vocabularies.next(0);
        }
        if (pivotal == null) {
          return;
        }
        ArrayList<Vocabulary> queuedVocabularies =
            Vocabularies.select(
                " Where " + Vocabularies.Id + " >= ?",
                new String[] {String.valueOf(pivotal.getId())},
                " Limit " + String.valueOf(settings.getWordsPerDay() - todaySentWords));
        for (int j = todaySentWords; j < settings.getWordsPerDay(); j++) {
          Vocabulary current = queuedVocabularies.get(j - todaySentWords);
          calendar.add(Calendar.SECOND, 1);
          Date time = calendar.getTime();

          if (elapsedMinutes < startTime + (j * settings.getIntervals())) {
            time = getTime(nextDayOffset, startTime + j * settings.getIntervals());
          }

          Reminder reminder =
              new Reminder(
                  current.getId(),
                  time,
                  current.getVocabulary(),
                  current.getVocabEnglishDef(),
                  false);

          // we'll meet this condition for sure!
          if (j == settings.getWordsPerDay() - 1
              || elapsedMinutes <= startTime + (j * settings.getIntervals())) {
            reminder.setTriggerNext(true);

            settings.setReminder(reminder);
            addAlarm(reminder);
            ReminderManager.applyReminderSettings(settings);

            return;
          } else {
            settings.setReminder(reminder);
            addAlarm(reminder);
            ReminderManager.applyReminderSettings(settings);
          }
        }
      }
    }

    if (!settings.getWeekdays()[today - 1]
        || elapsedMinutes > startTime
        || getTodaySentWords() >= settings.getWordsPerDay()) {
      for (int j = 1; j <= 7; j++) {
        if (settings.getWeekdays()[(today - 1 + j) % 7]) {
          nextDayOffset = j;
          break;
        }
      }
    }

    Date alarmTime = getTime(nextDayOffset, startTime);
    settings.getReminder().setTime(alarmTime);
    ReminderManager.applyReminderSettings(settings);

    addAlarm(
        new Reminder(
            vocabulary.getId(),
            alarmTime,
            vocabulary.getVocabulary(),
            vocabulary.getVocabEnglishDef(),
            true));
  }