public static void ScheduleDayBeforeAlarm(Context context, AccountDataItem account, DateTime today, AgendaViewItemsGroup agendaItems)
        {
            if (agendaItems == null)
            {
                return;
            }

            DateTime dayBeforeReminderTime = RemindersExtension.GetDayBeforeReminderTime(today, account, agendaItems);

            DateTime timeToScheduleAt;

            // If we haven't reached that time yet for "due tomorrow"
            if (dayBeforeReminderTime > DateTime.Now)
            {
                timeToScheduleAt = dayBeforeReminderTime.AddMilliseconds(1);
            }

            // Otherwise we'll need to set the timer for the "due today"
            else
            {
                timeToScheduleAt = today.AddDays(1).AddMilliseconds(1);
            }

            AlarmManagerHelper.Schedule(
                context: context,
                receiverType: typeof(UpdateDayBeforeNotificationReceiver),
                wakeTime: timeToScheduleAt,
                uriData: "powerplanner:?localAccountId=" + account.LocalAccountId,
                wakeDevice: true);
        }
        private async Task AddScheduledDayBeforeNotifications(AccountDataItem account, AgendaViewItemsGroup agendaItems, DateTime now)
        {
            try
            {
                string idStartString = GetIdentifierStartStringForDayBefore(account.LocalAccountId);

                DateTime artificialToday = now.Date;
                for (int i = 0; i < DAYS_IN_ADVANCE; i++, artificialToday = artificialToday.AddDays(1))
                {
                    DateTime artificialTomorrow           = artificialToday.AddDays(1);
                    BaseViewItemHomeworkExam[] itemsOnDay = agendaItems.Items.Where(x => x.Date.Date == artificialTomorrow).OrderBy(x => x).ToArray();

                    if (itemsOnDay.Length > 0)
                    {
                        DateTime reminderTime = RemindersExtension.GetDayBeforeReminderTime(artificialToday, account, agendaItems);

                        string title = "Due tomorrow";
                        string body  = "";
                        if (itemsOnDay.Length == 1)
                        {
                            body = StringTools.TrimLengthWithEllipses(itemsOnDay[0].Name, 200);
                        }
                        else
                        {
                            title += " (" + itemsOnDay.Length + ")";

                            foreach (var item in itemsOnDay.Take(5))
                            {
                                body += StringTools.TrimLengthWithEllipses(item.Name, 30) + "\n";
                            }
                            body = body.Trim();
                        }
                        await ScheduleDayBeforeNotification(idStartString + artificialToday.ToString(DAY_BEFORE_DATE_FORMAT, CultureInfo.InvariantCulture), title, body, reminderTime);
                    }
                }
            }
            catch (Exception ex)
            {
                TelemetryExtension.Current?.TrackException(ex);
            }
        }
        private static async Task UpdateDayBeforeNotification(AccountDataItem account, AgendaViewItemsGroup agendaItems, Context context, NotificationManager notificationManager, bool fromForeground)
        {
            string tag = account.LocalAccountId.ToString();

            // If no current semester, or no items, then just clear
            if (agendaItems == null || agendaItems.Items.Count == 0)
            {
                notificationManager.Cancel(tag, NotificationIds.DAY_BEFORE_NOTIFICATION);
                return;
            }

            StatusBarNotification existing;

            if (Android.OS.Build.VERSION.SdkInt >= BuildVersionCodes.M)
            {
                existing = notificationManager.GetActiveNotifications().FirstOrDefault(i => i.Id == NotificationIds.DAY_BEFORE_NOTIFICATION && i.Tag == tag);
            }
            else
            {
                // GetActiveNotifications didn't exist till API 23
                existing = null;
            }

            const string EXTRA_UNIQUE_ID = "UniqueId";

            DateTime now = DateTime.Now;

            DateTime reminderTime = RemindersExtension.GetDayBeforeReminderTime(now.Date, account, agendaItems);

            bool sendingDueTomorrow = now >= reminderTime;

            NotificationCompat.Builder builder;

            if (sendingDueTomorrow)
            {
                var itemsDueTomorrow = agendaItems.Items.Where(i => i.Date.Date == now.Date.AddDays(1)).OrderBy(i => i).ToArray();

                // If nothing tomorrow, we clear
                if (itemsDueTomorrow.Length == 0)
                {
                    notificationManager.Cancel(tag, NotificationIds.DAY_BEFORE_NOTIFICATION);
                    return;
                }

                string extraUniqueId = "DueTomorrow" + string.Join(";", itemsDueTomorrow.Select(i => i.Name)).GetHashCode();

                // If already updated
                if (existing != null && existing.Notification.Extras.GetString(EXTRA_UNIQUE_ID).Equals(extraUniqueId))
                {
                    return;
                }

                // If all the items have been updated more recently than the reminder time, we won't show a new notification
                if (existing == null && itemsDueTomorrow.All(i => i.Updated.ToLocalTime() > reminderTime))
                {
                    return;
                }

                // If we already sent the notification today
                if (account.DateLastDayBeforeReminderWasSent.Date == now.Date)
                {
                    // If the notification has been dismissed, do nothing
                    if (existing == null)
                    {
                        return;
                    }
                }

                // Otherwise we need to update the date that it was sent
                else
                {
                    account.DateLastDayBeforeReminderWasSent = now;
                    await AccountsManager.Save(account);
                }

                if (existing == null && fromForeground)
                {
                    return;
                }

                builder = CreateReminderBuilderForDayBefore(context, account.LocalAccountId);
                Bundle b = new Bundle();
                b.PutString(EXTRA_UNIQUE_ID, extraUniqueId);
                builder.SetExtras(b);
                // "Due tomorrow"
                builder.SetContentTitle(PowerPlannerResources.GetDueX(PowerPlannerResources.GetRelativeDateTomorrow().ToLower()));
                PopulateNotificationDayBeforeWithItems(builder, itemsDueTomorrow);
            }

            // Otherwise "due today"
            else
            {
                var itemsDueToday = agendaItems.Items.Where(i => i.Date.Date == now.Date).OrderBy(i => i).ToArray();

                // If nothing left today, we clear
                if (itemsDueToday.Length == 0)
                {
                    notificationManager.Cancel(tag, NotificationIds.DAY_BEFORE_NOTIFICATION);
                    return;
                }

                string extraUniqueId = "DueToday" + string.Join(";", itemsDueToday.Select(i => i.Name)).GetHashCode();

                // If already updated
                if (existing != null && existing.Notification.Extras.GetString(EXTRA_UNIQUE_ID).Equals(extraUniqueId))
                {
                    return;
                }

                // If the notification doesn't currently exist (user potentially dismissed it) and we've already sent either yesterday or today
                if (existing == null && account.DateLastDayBeforeReminderWasSent.Date == DateTime.Today.AddDays(-1) || account.DateLastDayBeforeReminderWasSent.Date == DateTime.Today)
                {
                    return;
                }

                // If all the items have been updated more recently than the reminder time, we won't show a new notification
                if (existing == null && itemsDueToday.All(i => i.Updated.ToLocalTime() > reminderTime))
                {
                    return;
                }

                // If we already sent the notification yesterday
                if (account.DateLastDayBeforeReminderWasSent.Date == now.Date.AddDays(-1))
                {
                    // If the notification has been dismissed, do nothing
                    if (existing == null)
                    {
                        return;
                    }
                }

                // Otherwise we need to update the date that it was sent
                else
                {
                    account.DateLastDayBeforeReminderWasSent = now.Date.AddDays(-1);
                    await AccountsManager.Save(account);
                }

                if (existing == null && fromForeground)
                {
                    return;
                }

                builder = CreateReminderBuilderForDayBefore(context, account.LocalAccountId);
                Bundle b = new Bundle();
                b.PutString(EXTRA_UNIQUE_ID, extraUniqueId);
                builder.SetExtras(b);
                // "Due today"
                builder.SetContentTitle(PowerPlannerResources.GetDueX(PowerPlannerResources.GetRelativeDateToday().ToLower()));
                PopulateNotificationDayBeforeWithItems(builder, itemsDueToday);
            }

            notificationManager.Notify(tag, NotificationIds.DAY_BEFORE_NOTIFICATION, BuildReminder(builder));
        }