/*
 * Copyright 2014 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.samples.apps.iosched.service;

import android.app.*;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.TaskStackBuilder;
import android.util.Log;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.wearable.DataApi;
import com.google.android.gms.wearable.PutDataMapRequest;
import com.google.android.gms.wearable.PutDataRequest;
import com.google.android.gms.wearable.Wearable;
import com.google.samples.apps.iosched.R;
import com.google.samples.apps.iosched.provider.ScheduleContract;
import com.google.samples.apps.iosched.ui.BrowseSessionsActivity;
import com.google.samples.apps.iosched.ui.MapFragment;
import com.google.samples.apps.iosched.ui.MyScheduleActivity;
import com.google.samples.apps.iosched.ui.SessionFeedbackActivity;
import com.google.samples.apps.iosched.ui.phone.MapActivity;
import com.google.samples.apps.iosched.util.FeedbackUtils;
import com.google.samples.apps.iosched.util.PrefUtils;
import com.google.samples.apps.iosched.util.UIUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.google.samples.apps.iosched.util.LogUtils.LOGD;
import static com.google.samples.apps.iosched.util.LogUtils.LOGE;
import static com.google.samples.apps.iosched.util.LogUtils.makeLogTag;

/**
 * Background service to handle scheduling of starred session notification via
 * {@link android.app.AlarmManager}.
 */
public class SessionAlarmService extends IntentService
        implements GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener {

    private static final String TAG = makeLogTag(SessionAlarmService.class);

    public static final String ACTION_NOTIFY_SESSION =
            "com.google.samples.apps.iosched.action.NOTIFY_SESSION";
    public static final String ACTION_NOTIFY_SESSION_FEEDBACK =
            "com.google.samples.apps.iosched.action.NOTIFY_SESSION_FEEDBACK";
    public static final String ACTION_SCHEDULE_FEEDBACK_NOTIFICATION =
            "com.google.samples.apps.iosched.action.SCHEDULE_FEEDBACK_NOTIFICATION";
    public static final String ACTION_SCHEDULE_STARRED_BLOCK =
            "com.google.samples.apps.iosched.action.SCHEDULE_STARRED_BLOCK";
    public static final String ACTION_SCHEDULE_ALL_STARRED_BLOCKS =
            "com.google.samples.apps.iosched.action.SCHEDULE_ALL_STARRED_BLOCKS";
    public static final String EXTRA_SESSION_START =
            "com.google.samples.apps.iosched.extra.SESSION_START";
    public static final String EXTRA_SESSION_END =
            "com.google.samples.apps.iosched.extra.SESSION_END";
    public static final String EXTRA_SESSION_ALARM_OFFSET =
            "com.google.samples.apps.iosched.extra.SESSION_ALARM_OFFSET";
    public static final String EXTRA_SESSION_ID =
            "com.google.samples.apps.iosched.extra.SESSION_ID";
    public static final String EXTRA_SESSION_TITLE =
            "com.google.samples.apps.iosched.extra.SESSION_TITLE";
    public static final String EXTRA_SESSION_ROOM =
            "com.google.samples.apps.iosched.extra.SESSION_ROOM";
    public static final String EXTRA_SESSION_SPEAKERS =
            "com.google.samples.apps.iosched.extra.SESSION_SPEAKERS";

    public static final int NOTIFICATION_ID = 100;
    public static final int FEEDBACK_NOTIFICATION_ID = 101;

    // pulsate every 1 second, indicating a relatively high degree of urgency
    private static final int NOTIFICATION_LED_ON_MS = 100;
    private static final int NOTIFICATION_LED_OFF_MS = 1000;
    private static final int NOTIFICATION_ARGB_COLOR = 0xff0088ff; // cyan

    private static final long MILLI_TEN_MINUTES = 600000;
    private static final long MILLI_FIVE_MINUTES = 300000;
    private static final long MILLI_ONE_MINUTE = 60000;

    private static final long UNDEFINED_ALARM_OFFSET = -1;
    private static final long UNDEFINED_VALUE = -1;
    public static final String ACTION_NOTIFICATION_DISMISSAL
            = "com.google.sample.apps.iosched.ACTION_NOTIFICATION_DISMISSAL";
    private GoogleApiClient mGoogleApiClient;
    public static final String KEY_SESSION_ID = "session-id";
    private static final String KEY_SESSION_NAME = "session-name";
    private static final String KEY_SPEAKER_NAME = "speaker-name";
    private static final String KEY_SESSION_ROOM = "session-room";
    public static final String PATH_FEEDBACK = "/iowear/feedback";

    // special session ID that identifies a debug notification
    public static final String DEBUG_SESSION_ID = "debug-session-id";

    public SessionAlarmService() {
        super(TAG);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(Wearable.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        mGoogleApiClient.blockingConnect(2000, TimeUnit.MILLISECONDS);
        final String action = intent.getAction();

        LOGD(TAG, "SessionAlarmService handling " + action);

        if (ACTION_SCHEDULE_ALL_STARRED_BLOCKS.equals(action)) {
            LOGD(TAG, "Scheduling all starred blocks.");
            scheduleAllStarredBlocks();
            scheduleAllStarredSessionFeedbacks();
            return;
        } else if (ACTION_NOTIFY_SESSION_FEEDBACK.equals(action)) {
            LOGD(TAG, "Showing session feedback notification.");
            notifySessionFeedback(DEBUG_SESSION_ID.equals(intent.getStringExtra(EXTRA_SESSION_ID)));
            return;
        }

        final long sessionEnd = intent.getLongExtra(SessionAlarmService.EXTRA_SESSION_END,
                UNDEFINED_VALUE);
        if (sessionEnd == UNDEFINED_VALUE) {
            LOGD(TAG, "IGNORING ACTION -- missing sessionEnd parameter");
            return;
        }

        final long sessionAlarmOffset =
                intent.getLongExtra(SessionAlarmService.EXTRA_SESSION_ALARM_OFFSET,
                        UNDEFINED_ALARM_OFFSET);
        LOGD(TAG, "Session alarm offset is: " + sessionAlarmOffset);

        // Feedback notifications have a slightly different set of extras.
        if (ACTION_SCHEDULE_FEEDBACK_NOTIFICATION.equals(action)) {
            final String sessionId = intent.getStringExtra(SessionAlarmService.EXTRA_SESSION_ID);
            final String sessionTitle = intent.getStringExtra(
                    SessionAlarmService.EXTRA_SESSION_TITLE);
            if (sessionTitle == null || sessionEnd == UNDEFINED_VALUE ||
                    sessionId == null) {
                LOGE(TAG, "Attempted to schedule for feedback without providing extras.");
                return;
            }
            LOGD(TAG, "Scheduling feedback alarm for session: " + sessionTitle);
            scheduleFeedbackAlarm(sessionEnd, sessionAlarmOffset, sessionTitle);
            return;
        }

        final long sessionStart =
                intent.getLongExtra(SessionAlarmService.EXTRA_SESSION_START, UNDEFINED_VALUE);
        if (sessionStart == UNDEFINED_VALUE) {
            LOGD(TAG, "IGNORING ACTION -- no session start parameter.");
            return;
        }

        if (ACTION_NOTIFY_SESSION.equals(action)) {
            LOGD(TAG, "Notifying about sessions starting at " +
                    sessionStart + " = " + (new Date(sessionStart)).toString());
            LOGD(TAG, "-> Alarm offset: " + sessionAlarmOffset);
            notifySession(sessionStart, sessionAlarmOffset);
        } else if (ACTION_SCHEDULE_STARRED_BLOCK.equals(action)) {
            LOGD(TAG, "Scheduling session alarm.");
            LOGD(TAG, "-> Session start: " + sessionStart + " = " + (new Date(sessionStart))
                    .toString());
            LOGD(TAG, "-> Session end: " + sessionEnd + " = " + (new Date(sessionEnd)).toString());
            LOGD(TAG, "-> Alarm offset: " + sessionAlarmOffset);
            scheduleAlarm(sessionStart, sessionEnd, sessionAlarmOffset);
        }
    }

    public void scheduleFeedbackAlarm(final long sessionEnd,
            final long alarmOffset, final String sessionTitle) {
        // By default, feedback alarms fire 5 minutes before session end time. If alarm offset is
        // provided, alarm is set to go off that much time from now (useful for testing).
        long alarmTime;
        if (alarmOffset == UNDEFINED_ALARM_OFFSET) {
            alarmTime = sessionEnd - MILLI_FIVE_MINUTES;
        } else {
            alarmTime = UIUtils.getCurrentTime(this) + alarmOffset;
        }

        LOGD(TAG, "Scheduling session feedback alarm for session '" + sessionTitle + "'");
        LOGD(TAG, "  -> end time: " + sessionEnd + " = " + (new Date(sessionEnd)).toString());
        LOGD(TAG, "  -> alarm time: " + alarmTime + " = " + (new Date(alarmTime)).toString());

        final Intent feedbackIntent = new Intent(
                ACTION_NOTIFY_SESSION_FEEDBACK,
                null,
                this,
                SessionAlarmService.class);
        PendingIntent pi = PendingIntent.getService(
                this, 1, feedbackIntent, PendingIntent.FLAG_CANCEL_CURRENT);
        final AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        am.set(AlarmManager.RTC_WAKEUP, alarmTime, pi);
    }

    private void scheduleAlarm(final long sessionStart,
            final long sessionEnd, final long alarmOffset) {

        NotificationManager nm =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
        nm.cancel(NOTIFICATION_ID);
        final long currentTime = UIUtils.getCurrentTime(this);
        // If the session is already started, do not schedule system notification.
        if (currentTime > sessionStart) {
            LOGD(TAG, "Not scheduling alarm because target time is in the past: " + sessionStart);
            return;
        }

        // By default, sets alarm to go off at 10 minutes before session start time.  If alarm
        // offset is provided, alarm is set to go off by that much time from now.
        long alarmTime;
        if (alarmOffset == UNDEFINED_ALARM_OFFSET) {
            alarmTime = sessionStart - MILLI_TEN_MINUTES;
        } else {
            alarmTime = currentTime + alarmOffset;
        }

        LOGD(TAG, "Scheduling alarm for " + alarmTime + " = " + (new Date(alarmTime)).toString());

        final Intent notifIntent = new Intent(
                ACTION_NOTIFY_SESSION,
                null,
                this,
                SessionAlarmService.class);
        // Setting data to ensure intent's uniqueness for different session start times.
        notifIntent.setData(
                new Uri.Builder().authority("com.google.samples.apps.iosched")
                        .path(String.valueOf(sessionStart)).build()
        );
        notifIntent.putExtra(SessionAlarmService.EXTRA_SESSION_START, sessionStart);
        LOGD(TAG, "-> Intent extra: session start " + sessionStart);
        notifIntent.putExtra(SessionAlarmService.EXTRA_SESSION_END, sessionEnd);
        LOGD(TAG, "-> Intent extra: session end " + sessionEnd);
        notifIntent.putExtra(SessionAlarmService.EXTRA_SESSION_ALARM_OFFSET, alarmOffset);
        LOGD(TAG, "-> Intent extra: session alarm offset " + alarmOffset);
        PendingIntent pi = PendingIntent.getService(this,
                0,
                notifIntent,
                PendingIntent.FLAG_CANCEL_CURRENT);
        final AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        // Schedule an alarm to be fired to notify user of added sessions are about to begin.
        LOGD(TAG, "-> Scheduling RTC_WAKEUP alarm at " + alarmTime);
        am.set(AlarmManager.RTC_WAKEUP, alarmTime, pi);
    }

    // A starred session is about to end; notify the user to provide session feedback.
    // Constructs and triggers a system notification. Does nothing if the session has already
    // concluded.
    private void notifySessionFeedback(boolean debug) {
        LOGD(TAG, "Considering firing notification for session feedback.");

        if (debug) {
            LOGD(TAG, "Note: this is a debug notification.");
        }

        // Don't fire notification if this feature is disabled in settings
        if (!PrefUtils.shouldShowSessionFeedbackReminders(this)) {
            LOGD(TAG, "Skipping session feedback notification. Disabled in settings.");
            return;
        }

        final Cursor c = getContentResolver().query(
                ScheduleContract.Sessions.CONTENT_MY_SCHEDULE_URI,
                SessionsNeedingFeedbackQuery.PROJECTION,
                SessionsNeedingFeedbackQuery.WHERE_CLAUSE, null, null);
        if (c == null) {
            return;
        }

        List<String> needFeedbackIds = new ArrayList<String>();
        List<String> needFeedbackTitles = new ArrayList<String>();
        while (c.moveToNext()) {
            String sessionId = c.getString(SessionsNeedingFeedbackQuery.SESSION_ID);
            String sessionTitle = c.getString(SessionsNeedingFeedbackQuery.SESSION_TITLE);

            // Avoid repeated notifications.
            if (UIUtils.isFeedbackNotificationFiredForSession(this, sessionId)) {
                LOGD(TAG, "Skipping repeated session feedback notification for session '"
                        + sessionTitle + "'");
                continue;
            }

            needFeedbackIds.add(sessionId);
            needFeedbackTitles.add(sessionTitle);
        }

        if (needFeedbackIds.size() == 0) {
            // the user has already been notified of all sessions needing feedback
            return;
        }

        LOGD(TAG, "Going forward with session feedback notification for "
                + needFeedbackIds.size() + " session(s).");

        final Resources res = getResources();

        // this is used to synchronize deletion of notifications on phone and wear
        Intent dismissalIntent = new Intent(ACTION_NOTIFICATION_DISMISSAL);
        // TODO: fix Wear dismiss integration
        //dismissalIntent.putExtra(KEY_SESSION_ID, sessionId);
        PendingIntent dismissalPendingIntent = PendingIntent
                .getService(this, (int) new Date().getTime(), dismissalIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT);

        String provideFeedbackTicker = res.getString(R.string.session_feedback_notification_ticker);
        NotificationCompat.Builder notifBuilder = new NotificationCompat.Builder(this)
                //.setColor(getResources().getColor(R.color.theme_primary))
                            // Note: setColor() is available in the support lib v21+.
                            // We commented it out because we want the source to compile 
                            // against support lib v20. If you are using support lib
                            // v21 or above on Android L, uncomment this line.
                .setContentText(provideFeedbackTicker)
                .setTicker(provideFeedbackTicker)
                .setLights(
                        SessionAlarmService.NOTIFICATION_ARGB_COLOR,
                        SessionAlarmService.NOTIFICATION_LED_ON_MS,
                        SessionAlarmService.NOTIFICATION_LED_OFF_MS)
                .setSmallIcon(R.drawable.ic_stat_notification)
                .setPriority(Notification.PRIORITY_LOW)
                .setLocalOnly(true) // make it local to the phone
                .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
                .setDeleteIntent(dismissalPendingIntent)
                .setAutoCancel(true);

        if (needFeedbackIds.size() == 1) {
            // Only 1 session needs feedback
            Uri sessionUri = ScheduleContract.Sessions.buildSessionUri(needFeedbackIds.get(0));
            PendingIntent pi = TaskStackBuilder.create(this)
                    .addNextIntent(new Intent(this, MyScheduleActivity.class))
                    .addNextIntent(new Intent(Intent.ACTION_VIEW, sessionUri, this,
                            SessionFeedbackActivity.class))
                    .getPendingIntent(1, PendingIntent.FLAG_CANCEL_CURRENT);

            notifBuilder.setContentTitle(needFeedbackTitles.get(0))
                    .setContentIntent(pi);
        } else {
            // Show information about several sessions that need feedback
            PendingIntent pi = TaskStackBuilder.create(this)
                    .addNextIntent(new Intent(this, MyScheduleActivity.class))
                    .getPendingIntent(1, PendingIntent.FLAG_CANCEL_CURRENT);

            NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
            inboxStyle.setBigContentTitle(provideFeedbackTicker);
            for (String title : needFeedbackTitles) {
                inboxStyle.addLine(title);
            }

            notifBuilder.setContentTitle(
                    getResources().getQuantityString(R.plurals.session_plurals,
                            needFeedbackIds.size(), needFeedbackIds.size()))
                    .setStyle(inboxStyle)
                    .setContentIntent(pi);
        }

        NotificationManager nm = (NotificationManager) getSystemService(
                Context.NOTIFICATION_SERVICE);
        LOGD(TAG, "Now showing session feedback notification!");
        nm.notify(FEEDBACK_NOTIFICATION_ID, notifBuilder.build());

        for (int i = 0; i < needFeedbackIds.size(); i++) {
            setupNotificationOnWear(needFeedbackIds.get(i), null, needFeedbackTitles.get(i), null);
        }
    }

    /**
     * Builds corresponding notification for the Wear device that is paired to this handset. This
     * is done by adding a Data Item to teh Data Store; the Wear device will be notified to build a
     * local notification.
     */
    private void setupNotificationOnWear(String sessionId, String sessionRoom, String sessionName,
            String speaker) {
        if (!mGoogleApiClient.isConnected()) {
            Log.e(TAG, "setupNotificationOnWear(): Failed to send data item since there was no "
                    + "connectivity to Google API Client");
            return;
        }
        PutDataMapRequest putDataMapRequest = PutDataMapRequest
                .create(FeedbackUtils.getFeedbackPath(sessionId));
        putDataMapRequest.getDataMap().putLong("time", new Date().getTime());
        putDataMapRequest.getDataMap().putString(KEY_SESSION_ID, sessionId);
        putDataMapRequest.getDataMap().putString(KEY_SESSION_NAME, sessionName);
        putDataMapRequest.getDataMap().putString(KEY_SPEAKER_NAME, speaker);
        putDataMapRequest.getDataMap().putString(KEY_SESSION_ROOM, sessionRoom);

        PutDataRequest request = putDataMapRequest.asPutDataRequest();

        Wearable.DataApi.putDataItem(mGoogleApiClient, request)
                .setResultCallback(new ResultCallback<DataApi.DataItemResult>() {
                    @Override
                    public void onResult(DataApi.DataItemResult dataItemResult) {
                        LOGD(TAG, "setupNotificationOnWear(): Sending notification result success:"
                                        + dataItemResult.getStatus().isSuccess()
                        );
                    }
                });
    }

    // Starred sessions are about to begin.  Constructs and triggers system notification.
    private void notifySession(final long sessionStart, final long alarmOffset) {
        long currentTime = UIUtils.getCurrentTime(this);
        final long intervalEnd = sessionStart + MILLI_TEN_MINUTES;
        LOGD(TAG, "Considering notifying for time interval.");
        LOGD(TAG, "    Interval start: " + sessionStart + "=" + (new Date(sessionStart)).toString());
        LOGD(TAG, "    Interval end: " + intervalEnd + "=" + (new Date(intervalEnd)).toString());
        LOGD(TAG, "    Current time is: " + currentTime + "=" + (new Date(currentTime)).toString());
        if (sessionStart < currentTime) {
            LOGD(TAG, "Skipping session notification (too late -- time interval already started)");
            return;
        }

        if (!PrefUtils.shouldShowSessionReminders(this)) {
            // skip if disabled in settings
            LOGD(TAG, "Skipping session notification for sessions. Disabled in settings.");
            return;
        }

        // Avoid repeated notifications.
        if (alarmOffset == UNDEFINED_ALARM_OFFSET && UIUtils.isNotificationFiredForBlock(
                this, ScheduleContract.Blocks.generateBlockId(sessionStart, intervalEnd))) {
            LOGD(TAG, "Skipping session notification (already notified)");
            return;
        }

        final ContentResolver cr = getContentResolver();

        LOGD(TAG, "Looking for sessions in interval "  + sessionStart + " - " + intervalEnd);
        Cursor c = cr.query(
                ScheduleContract.Sessions.CONTENT_MY_SCHEDULE_URI,
                SessionDetailQuery.PROJECTION,
                ScheduleContract.Sessions.STARTING_AT_TIME_INTERVAL_SELECTION,
                ScheduleContract.Sessions.buildAtTimeIntervalArgs(sessionStart, intervalEnd),
                null);
        int starredCount = c.getCount();
        LOGD(TAG, "# starred sessions in that interval: " + c.getCount());
        String singleSessionId = null;
        String singleSessionRoomId = null;
        ArrayList<String> starredSessionTitles = new ArrayList<String>();
        while (c.moveToNext()) {
            singleSessionId = c.getString(SessionDetailQuery.SESSION_ID);
            singleSessionRoomId = c.getString(SessionDetailQuery.ROOM_ID);
            starredSessionTitles.add(c.getString(SessionDetailQuery.SESSION_TITLE));
            LOGD(TAG, "-> Title: " + c.getString(SessionDetailQuery.SESSION_TITLE));
        }
        if (starredCount < 1) {
            return;
        }

        // Generates the pending intent which gets fired when the user taps on the notification.
        // NOTE: Use TaskStackBuilder to comply with Android's design guidelines
        // related to navigation from notifications.
        Intent baseIntent = new Intent(this, MyScheduleActivity.class);
        baseIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        TaskStackBuilder taskBuilder = TaskStackBuilder.create(this)
                .addNextIntent(baseIntent);

        // For a single session, tapping the notification should open the session details (b/15350787)
        if (starredCount == 1) {
            taskBuilder.addNextIntent(new Intent(Intent.ACTION_VIEW,
                    ScheduleContract.Sessions.buildSessionUri(singleSessionId)));
        }

        PendingIntent pi = taskBuilder.getPendingIntent(0, PendingIntent.FLAG_CANCEL_CURRENT);

        final Resources res = getResources();
        String contentText;
        int minutesLeft = (int) (sessionStart - currentTime + 59000) / 60000;
        if (minutesLeft < 1) {
            minutesLeft = 1;
        }

        if (starredCount == 1) {
            contentText = res.getString(R.string.session_notification_text_1, minutesLeft);
        } else {
            contentText = res.getQuantityString(R.plurals.session_notification_text,
                    starredCount - 1,
                    minutesLeft,
                    starredCount - 1);
        }

        NotificationCompat.Builder notifBuilder = new NotificationCompat.Builder(this)
                .setContentTitle(starredSessionTitles.get(0))
                .setContentText(contentText)
                //.setColor(getResources().getColor(R.color.theme_primary))
                            // Note: setColor() is available in the support lib v21+.
                            // We commented it out because we want the source to compile 
                            // against support lib v20. If you are using support lib
                            // v21 or above on Android L, uncomment this line.
                .setTicker(res.getQuantityString(R.plurals.session_notification_ticker,
                        starredCount,
                        starredCount))
                .setDefaults(Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
                .setLights(
                        SessionAlarmService.NOTIFICATION_ARGB_COLOR,
                        SessionAlarmService.NOTIFICATION_LED_ON_MS,
                        SessionAlarmService.NOTIFICATION_LED_OFF_MS)
                .setSmallIcon(R.drawable.ic_stat_notification)
                .setContentIntent(pi)
                .setPriority(Notification.PRIORITY_MAX)
                .setAutoCancel(true);
        if (minutesLeft > 5) {
            notifBuilder.addAction(R.drawable.ic_alarm_holo_dark,
                    String.format(res.getString(R.string.snooze_x_min), 5),
                    createSnoozeIntent(sessionStart, intervalEnd, 5));
        }
        if (starredCount == 1 && PrefUtils.isAttendeeAtVenue(this)) {
            notifBuilder.addAction(R.drawable.ic_map_holo_dark,
                    res.getString(R.string.title_map),
                    createRoomMapIntent(singleSessionRoomId));
        }
        String bigContentTitle;
        if (starredCount == 1 && starredSessionTitles.size() > 0) {
            bigContentTitle = starredSessionTitles.get(0);
        } else {
            bigContentTitle = res.getQuantityString(R.plurals.session_notification_title,
                    starredCount,
                    minutesLeft,
                    starredCount);
        }
        NotificationCompat.InboxStyle richNotification = new NotificationCompat.InboxStyle(
                notifBuilder)
                .setBigContentTitle(bigContentTitle);

        // Adds starred sessions starting at this time block to the notification.
        for (int i = 0; i < starredCount; i++) {
            richNotification.addLine(starredSessionTitles.get(i));
        }
        NotificationManager nm = (NotificationManager) getSystemService(
                Context.NOTIFICATION_SERVICE);
        LOGD(TAG, "Now showing notification.");
        nm.notify(NOTIFICATION_ID, richNotification.build());
    }

    private PendingIntent createSnoozeIntent(final long sessionStart, final long sessionEnd,
            final int snoozeMinutes) {
        Intent scheduleIntent = new Intent(
                SessionAlarmService.ACTION_SCHEDULE_STARRED_BLOCK,
                null, this, SessionAlarmService.class);
        scheduleIntent.putExtra(SessionAlarmService.EXTRA_SESSION_START, sessionStart);
        scheduleIntent.putExtra(SessionAlarmService.EXTRA_SESSION_END, sessionEnd);
        scheduleIntent.putExtra(SessionAlarmService.EXTRA_SESSION_ALARM_OFFSET,
                snoozeMinutes * MILLI_ONE_MINUTE);
        return PendingIntent.getService(this, 0, scheduleIntent,
                PendingIntent.FLAG_CANCEL_CURRENT);
    }

    private PendingIntent createRoomMapIntent(final String roomId) {
        Intent mapIntent = new Intent(getApplicationContext(),
                UIUtils.getMapActivityClass(getApplicationContext()));
        mapIntent.putExtra(MapFragment.EXTRA_ROOM, roomId);
        mapIntent.putExtra(MapActivity.EXTRA_DETACHED_MODE, true);
        return TaskStackBuilder
                .create(getApplicationContext())
                .addNextIntent(new Intent(this, BrowseSessionsActivity.class))
                .addNextIntent(mapIntent)
                .getPendingIntent(0, PendingIntent.FLAG_CANCEL_CURRENT);
    }

    private void scheduleAllStarredBlocks() {
        final ContentResolver cr = getContentResolver();
        final Cursor c = cr.query(ScheduleContract.Sessions.CONTENT_MY_SCHEDULE_URI,
                new String[]{"distinct " + ScheduleContract.Sessions.SESSION_START,
                        ScheduleContract.Sessions.SESSION_END,
                        ScheduleContract.Sessions.SESSION_IN_MY_SCHEDULE},
                null,
                null,
                null
        );
        if (c == null) {
            return;
        }

        while (c.moveToNext()) {
            final long sessionStart = c.getLong(0);
            final long sessionEnd = c.getLong(1);
            scheduleAlarm(sessionStart, sessionEnd, UNDEFINED_ALARM_OFFSET);
        }
    }

    // Schedules feedback alarms for all starred sessions.
    private void scheduleAllStarredSessionFeedbacks() {
        final ContentResolver cr = getContentResolver();
        // TODO: Should we also check that SESSION_IN_MY_SCHEDULE is true?
        final Cursor c = cr.query(ScheduleContract.Sessions.CONTENT_MY_SCHEDULE_URI,
                new String[]{
                        ScheduleContract.Sessions.SESSION_TITLE,
                        ScheduleContract.Sessions.SESSION_END,
                        ScheduleContract.Sessions.SESSION_IN_MY_SCHEDULE,
                },
                null,
                null,
                null
        );
        if (c == null) {
            return;
        }
        while (c.moveToNext()) {
            final String sessionTitle = c.getString(0);
            final long sessionEnd = c.getLong(1);
            scheduleFeedbackAlarm(sessionEnd, UNDEFINED_ALARM_OFFSET, sessionTitle);
        }
    }

    public interface SessionDetailQuery {

        String[] PROJECTION = {
                ScheduleContract.Sessions.SESSION_ID,
                ScheduleContract.Sessions.SESSION_TITLE,
                ScheduleContract.Sessions.ROOM_ID,
                ScheduleContract.Sessions.SESSION_IN_MY_SCHEDULE
        };

        int SESSION_ID = 0;
        int SESSION_TITLE = 1;
        int ROOM_ID = 2;
    }

    public interface SessionsNeedingFeedbackQuery {
        String[] PROJECTION = {
                ScheduleContract.Sessions.SESSION_ID,
                ScheduleContract.Sessions.SESSION_TITLE,
                ScheduleContract.Sessions.SESSION_IN_MY_SCHEDULE,
                ScheduleContract.Sessions.HAS_GIVEN_FEEDBACK,
        };

        int SESSION_ID = 0;
        int SESSION_TITLE = 1;

        public static final String WHERE_CLAUSE =
                ScheduleContract.Sessions.HAS_GIVEN_FEEDBACK + "=0";
    }

    @Override
    public void onConnected(Bundle connectionHint) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Connected to Google Api Service");
        }
    }

    @Override
    public void onConnectionSuspended(int cause) {
        // Ignore
    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Disconnected from Google Api Service");
        }
    }

}
