/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * 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.android.calendar.alerts;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.ContentUris;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.PowerManager;
import android.provider.CalendarContract.Attendees;
import android.provider.CalendarContract.Calendars;
import android.provider.CalendarContract.Events;
import android.telephony.TelephonyManager;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.RelativeSizeSpan;
import android.text.style.TextAppearanceSpan;
import android.text.style.URLSpan;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews;

import com.android.calendar.R;
import com.android.calendar.Utils;
import com.android.calendar.alerts.AlertService.NotificationWrapper;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * Receives android.intent.action.EVENT_REMINDER intents and handles
 * event reminders.  The intent URI specifies an alert id in the
 * CalendarAlerts database table.  This class also receives the
 * BOOT_COMPLETED intent so that it can add a status bar notification
 * if there are Calendar event alarms that have not been dismissed.
 * It also receives the TIME_CHANGED action so that it can fire off
 * snoozed alarms that have become ready.  The real work is done in
 * the AlertService class.
 *
 * To trigger this code after pushing the apk to device:
 * adb shell am broadcast -a "android.intent.action.EVENT_REMINDER"
 *    -n "com.android.calendar/.alerts.AlertReceiver"
 */
public class AlertReceiver extends BroadcastReceiver {
    private static final String TAG = "AlertReceiver";

    private static final String MAP_ACTION = "com.android.calendar.MAP";
    private static final String CALL_ACTION = "com.android.calendar.CALL";
    private static final String MAIL_ACTION = "com.android.calendar.MAIL";
    private static final String EXTRA_EVENT_ID = "eventid";

    // The broadcast for notification refreshes scheduled by the app. This is to
    // distinguish the EVENT_REMINDER broadcast sent by the provider.
    public static final String EVENT_REMINDER_APP_ACTION =
            "com.android.calendar.EVENT_REMINDER_APP";

    static final Object mStartingServiceSync = new Object();
    static PowerManager.WakeLock mStartingService;
    private static final Pattern mBlankLinePattern = Pattern.compile("^\\s*$[\n\r]",
            Pattern.MULTILINE);

    public static final String ACTION_DISMISS_OLD_REMINDERS = "removeOldReminders";
    private static final int NOTIFICATION_DIGEST_MAX_LENGTH = 3;

    private static final String GEO_PREFIX = "geo:";
    private static final String TEL_PREFIX = "tel:";
    private static final int MAX_NOTIF_ACTIONS = 3;

    private static Handler sAsyncHandler;
    static {
        HandlerThread thr = new HandlerThread("AlertReceiver async");
        thr.start();
        sAsyncHandler = new Handler(thr.getLooper());
    }

    @Override
    public void onReceive(final Context context, final Intent intent) {
        if (AlertService.DEBUG) {
            Log.d(TAG, "onReceive: a=" + intent.getAction() + " " + intent.toString());
        }
        if (MAP_ACTION.equals(intent.getAction())) {
            // Try starting the map action.
            // If no map location is found (something changed since the notification was originally
            // fired), update the notifications to express this change.
            final long eventId = intent.getLongExtra(EXTRA_EVENT_ID, -1);
            if (eventId != -1) {
                URLSpan[] urlSpans = getURLSpans(context, eventId);
                Intent geoIntent = createMapActivityIntent(context, urlSpans);
                if (geoIntent != null) {
                    // Location was successfully found, so dismiss the shade and start maps.
                    context.startActivity(geoIntent);
                    closeNotificationShade(context);
                } else {
                    // No location was found, so update all notifications.
                    // Our alert service does not currently allow us to specify only one
                    // specific notification to refresh.
                    AlertService.updateAlertNotification(context);
                }
            }
        } else if (CALL_ACTION.equals(intent.getAction())) {
            // Try starting the call action.
            // If no call location is found (something changed since the notification was originally
            // fired), update the notifications to express this change.
            final long eventId = intent.getLongExtra(EXTRA_EVENT_ID, -1);
            if (eventId != -1) {
                URLSpan[] urlSpans = getURLSpans(context, eventId);
                Intent callIntent = createCallActivityIntent(context, urlSpans);
                if (callIntent != null) {
                    // Call location was successfully found, so dismiss the shade and start dialer.
                    context.startActivity(callIntent);
                    closeNotificationShade(context);
                } else {
                    // No call location was found, so update all notifications.
                    // Our alert service does not currently allow us to specify only one
                    // specific notification to refresh.
                    AlertService.updateAlertNotification(context);
                }
            }
        } else if (MAIL_ACTION.equals(intent.getAction())) {
            closeNotificationShade(context);

            // Now start the email intent.
            final long eventId = intent.getLongExtra(EXTRA_EVENT_ID, -1);
            if (eventId != -1) {
                Intent i = new Intent(context, QuickResponseActivity.class);
                i.putExtra(QuickResponseActivity.EXTRA_EVENT_ID, eventId);
                i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(i);
            }
        } else {
            Intent i = new Intent();
            i.setClass(context, AlertService.class);
            i.putExtras(intent);
            i.putExtra("action", intent.getAction());
            Uri uri = intent.getData();

            // This intent might be a BOOT_COMPLETED so it might not have a Uri.
            if (uri != null) {
                i.putExtra("uri", uri.toString());
            }
            beginStartingService(context, i);
        }
    }

    /**
     * Start the service to process the current event notifications, acquiring
     * the wake lock before returning to ensure that the service will run.
     */
    public static void beginStartingService(Context context, Intent intent) {
        synchronized (mStartingServiceSync) {
            if (mStartingService == null) {
                PowerManager pm =
                    (PowerManager)context.getSystemService(Context.POWER_SERVICE);
                mStartingService = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                        "StartingAlertService");
                mStartingService.setReferenceCounted(false);
            }
            mStartingService.acquire();
            context.startService(intent);
        }
    }

    /**
     * Called back by the service when it has finished processing notifications,
     * releasing the wake lock if the service is now stopping.
     */
    public static void finishStartingService(Service service, int startId) {
        synchronized (mStartingServiceSync) {
            if (mStartingService != null) {
                if (service.stopSelfResult(startId)) {
                    mStartingService.release();
                }
            }
        }
    }

    private static PendingIntent createClickEventIntent(Context context, long eventId,
            long startMillis, long endMillis, int notificationId) {
        return createDismissAlarmsIntent(context, eventId, startMillis, endMillis, notificationId,
                DismissAlarmsService.SHOW_ACTION);
    }

    private static PendingIntent createDeleteEventIntent(Context context, long eventId,
            long startMillis, long endMillis, int notificationId) {
        return createDismissAlarmsIntent(context, eventId, startMillis, endMillis, notificationId,
                DismissAlarmsService.DISMISS_ACTION);
    }

    private static PendingIntent createDismissAlarmsIntent(Context context, long eventId,
            long startMillis, long endMillis, int notificationId, String action) {
        Intent intent = new Intent();
        intent.setClass(context, DismissAlarmsService.class);
        intent.setAction(action);
        intent.putExtra(AlertUtils.EVENT_ID_KEY, eventId);
        intent.putExtra(AlertUtils.EVENT_START_KEY, startMillis);
        intent.putExtra(AlertUtils.EVENT_END_KEY, endMillis);
        intent.putExtra(AlertUtils.NOTIFICATION_ID_KEY, notificationId);

        // Must set a field that affects Intent.filterEquals so that the resulting
        // PendingIntent will be a unique instance (the 'extras' don't achieve this).
        // This must be unique for the click event across all reminders (so using
        // event ID + startTime should be unique).  This also must be unique from
        // the delete event (which also uses DismissAlarmsService).
        Uri.Builder builder = Events.CONTENT_URI.buildUpon();
        ContentUris.appendId(builder, eventId);
        ContentUris.appendId(builder, startMillis);
        intent.setData(builder.build());
        return PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    }

    private static PendingIntent createSnoozeIntent(Context context, long eventId,
            long startMillis, long endMillis, int notificationId) {
        Intent intent = new Intent();
        intent.setClass(context, SnoozeAlarmsService.class);
        intent.putExtra(AlertUtils.EVENT_ID_KEY, eventId);
        intent.putExtra(AlertUtils.EVENT_START_KEY, startMillis);
        intent.putExtra(AlertUtils.EVENT_END_KEY, endMillis);
        intent.putExtra(AlertUtils.NOTIFICATION_ID_KEY, notificationId);

        Uri.Builder builder = Events.CONTENT_URI.buildUpon();
        ContentUris.appendId(builder, eventId);
        ContentUris.appendId(builder, startMillis);
        intent.setData(builder.build());
        return PendingIntent.getService(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
    }

    private static PendingIntent createAlertActivityIntent(Context context) {
        Intent clickIntent = new Intent();
        clickIntent.setClass(context, AlertActivity.class);
        clickIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        return PendingIntent.getActivity(context, 0, clickIntent,
                    PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
    }

    public static NotificationWrapper makeBasicNotification(Context context, String title,
            String summaryText, long startMillis, long endMillis, long eventId,
            int notificationId, boolean doPopup, int priority) {
        Notification n = buildBasicNotification(new Notification.Builder(context),
                context, title, summaryText, startMillis, endMillis, eventId, notificationId,
                doPopup, priority, false);
        return new NotificationWrapper(n, notificationId, eventId, startMillis, endMillis, doPopup);
    }

    private static Notification buildBasicNotification(Notification.Builder notificationBuilder,
            Context context, String title, String summaryText, long startMillis, long endMillis,
            long eventId, int notificationId, boolean doPopup, int priority,
            boolean addActionButtons) {
        Resources resources = context.getResources();
        if (title == null || title.length() == 0) {
            title = resources.getString(R.string.no_title_label);
        }

        // Create an intent triggered by clicking on the status icon, that dismisses the
        // notification and shows the event.
        PendingIntent clickIntent = createClickEventIntent(context, eventId, startMillis,
                endMillis, notificationId);

        // Create a delete intent triggered by dismissing the notification.
        PendingIntent deleteIntent = createDeleteEventIntent(context, eventId, startMillis,
            endMillis, notificationId);

        // Create the base notification.
        notificationBuilder.setContentTitle(title);
        notificationBuilder.setContentText(summaryText);
        notificationBuilder.setSmallIcon(R.drawable.stat_notify_calendar);
        notificationBuilder.setContentIntent(clickIntent);
        notificationBuilder.setDeleteIntent(deleteIntent);
        if (doPopup) {
            notificationBuilder.setFullScreenIntent(createAlertActivityIntent(context), true);
        }

        PendingIntent mapIntent = null, callIntent = null, snoozeIntent = null, emailIntent = null;
        if (addActionButtons) {
            // Send map, call, and email intent back to ourself first for a couple reasons:
            // 1) Workaround issue where clicking action button in notification does
            //    not automatically close the notification shade.
            // 2) Event information will always be up to date.

            // Create map and/or call intents.
            URLSpan[] urlSpans = getURLSpans(context, eventId);
            mapIntent = createMapBroadcastIntent(context, urlSpans, eventId);
            callIntent = createCallBroadcastIntent(context, urlSpans, eventId);

            // Create email intent for emailing attendees.
            emailIntent = createBroadcastMailIntent(context, eventId, title);

            // Create snooze intent.  TODO: change snooze to 10 minutes.
            snoozeIntent = createSnoozeIntent(context, eventId, startMillis, endMillis,
                    notificationId);
        }

        if (Utils.isJellybeanOrLater()) {
            // Turn off timestamp.
            notificationBuilder.setWhen(0);

            // Should be one of the values in Notification (ie. Notification.PRIORITY_HIGH, etc).
            // A higher priority will encourage notification manager to expand it.
            notificationBuilder.setPriority(priority);

            // Add action buttons. Show at most three, using the following priority ordering:
            // 1. Map
            // 2. Call
            // 3. Email
            // 4. Snooze
            // Actions will only be shown if they are applicable; i.e. with no location, map will
            // not be shown, and with no recipients, snooze will not be shown.
            // TODO: Get icons, get strings. Maybe show preview of actual location/number?
            int numActions = 0;
            if (mapIntent != null && numActions < MAX_NOTIF_ACTIONS) {
                notificationBuilder.addAction(R.drawable.ic_map,
                        resources.getString(R.string.map_label), mapIntent);
                numActions++;
            }
            if (callIntent != null && numActions < MAX_NOTIF_ACTIONS) {
                notificationBuilder.addAction(R.drawable.ic_call,
                        resources.getString(R.string.call_label), callIntent);
                numActions++;
            }
            if (emailIntent != null && numActions < MAX_NOTIF_ACTIONS) {
                notificationBuilder.addAction(R.drawable.ic_menu_email_holo_dark,
                        resources.getString(R.string.email_guests_label), emailIntent);
                numActions++;
            }
            if (snoozeIntent != null && numActions < MAX_NOTIF_ACTIONS) {
                notificationBuilder.addAction(R.drawable.ic_alarm_holo_dark,
                        resources.getString(R.string.snooze_label), snoozeIntent);
                numActions++;
            }
            return notificationBuilder.getNotification();

        } else {
            // Old-style notification (pre-JB).  Use custom view with buttons to provide
            // JB-like functionality (snooze/email).
            Notification n = notificationBuilder.getNotification();

            // Use custom view with buttons to provide JB-like functionality (snooze/email).
            RemoteViews contentView = new RemoteViews(context.getPackageName(),
                    R.layout.notification);
            contentView.setImageViewResource(R.id.image, R.drawable.stat_notify_calendar);
            contentView.setTextViewText(R.id.title,  title);
            contentView.setTextViewText(R.id.text, summaryText);

            int numActions = 0;
            if (mapIntent == null || numActions >= MAX_NOTIF_ACTIONS) {
                contentView.setViewVisibility(R.id.map_button, View.GONE);
            } else {
                contentView.setViewVisibility(R.id.map_button, View.VISIBLE);
                contentView.setOnClickPendingIntent(R.id.map_button, mapIntent);
                contentView.setViewVisibility(R.id.end_padding, View.GONE);
                numActions++;
            }
            if (callIntent == null || numActions >= MAX_NOTIF_ACTIONS) {
                contentView.setViewVisibility(R.id.call_button, View.GONE);
            } else {
                contentView.setViewVisibility(R.id.call_button, View.VISIBLE);
                contentView.setOnClickPendingIntent(R.id.call_button, callIntent);
                contentView.setViewVisibility(R.id.end_padding, View.GONE);
                numActions++;
            }
            if (emailIntent == null || numActions >= MAX_NOTIF_ACTIONS) {
                contentView.setViewVisibility(R.id.email_button, View.GONE);
            } else {
                contentView.setViewVisibility(R.id.email_button, View.VISIBLE);
                contentView.setOnClickPendingIntent(R.id.email_button, emailIntent);
                contentView.setViewVisibility(R.id.end_padding, View.GONE);
                numActions++;
            }
            if (snoozeIntent == null || numActions >= MAX_NOTIF_ACTIONS) {
                contentView.setViewVisibility(R.id.snooze_button, View.GONE);
            } else {
                contentView.setViewVisibility(R.id.snooze_button, View.VISIBLE);
                contentView.setOnClickPendingIntent(R.id.snooze_button, snoozeIntent);
                contentView.setViewVisibility(R.id.end_padding, View.GONE);
                numActions++;
            }

            n.contentView = contentView;

            return n;
        }
    }

    /**
     * Creates an expanding notification.  The initial expanded state is decided by
     * the notification manager based on the priority.
     */
    public static NotificationWrapper makeExpandingNotification(Context context, String title,
            String summaryText, String description, long startMillis, long endMillis, long eventId,
            int notificationId, boolean doPopup, int priority) {
        Notification.Builder basicBuilder = new Notification.Builder(context);
        Notification notification = buildBasicNotification(basicBuilder, context, title,
                summaryText, startMillis, endMillis, eventId, notificationId, doPopup,
                priority, true);
        if (Utils.isJellybeanOrLater()) {
            // Create a new-style expanded notification
            Notification.BigTextStyle expandedBuilder = new Notification.BigTextStyle();
            if (description != null) {
                description = mBlankLinePattern.matcher(description).replaceAll("");
                description = description.trim();
            }
            CharSequence text;
            if (TextUtils.isEmpty(description)) {
                text = summaryText;
            } else {
                SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
                stringBuilder.append(summaryText);
                stringBuilder.append("\n\n");
                stringBuilder.setSpan(new RelativeSizeSpan(0.5f), summaryText.length(),
                        stringBuilder.length(), 0);
                stringBuilder.append(description);
                text = stringBuilder;
            }
            expandedBuilder.bigText(text);
            basicBuilder.setStyle(expandedBuilder);
            notification = basicBuilder.build();
        }
        return new NotificationWrapper(notification, notificationId, eventId, startMillis,
                endMillis, doPopup);
    }

    /**
     * Creates an expanding digest notification for expired events.
     */
    public static NotificationWrapper makeDigestNotification(Context context,
            ArrayList<AlertService.NotificationInfo> notificationInfos, String digestTitle,
            boolean expandable) {
        if (notificationInfos == null || notificationInfos.size() < 1) {
            return null;
        }

        Resources res = context.getResources();
        int numEvents = notificationInfos.size();
        long[] eventIds = new long[notificationInfos.size()];
        long[] startMillis = new long[notificationInfos.size()];
        for (int i = 0; i < notificationInfos.size(); i++) {
            eventIds[i] = notificationInfos.get(i).eventId;
            startMillis[i] = notificationInfos.get(i).startMillis;
        }

        // Create an intent triggered by clicking on the status icon that shows the alerts list.
        PendingIntent pendingClickIntent = createAlertActivityIntent(context);

        // Create an intent triggered by dismissing the digest notification that clears all
        // expired events.
        Intent deleteIntent = new Intent();
        deleteIntent.setClass(context, DismissAlarmsService.class);
        deleteIntent.setAction(DismissAlarmsService.DISMISS_ACTION);
        deleteIntent.putExtra(AlertUtils.EVENT_IDS_KEY, eventIds);
        deleteIntent.putExtra(AlertUtils.EVENT_STARTS_KEY, startMillis);
        PendingIntent pendingDeleteIntent = PendingIntent.getService(context, 0, deleteIntent,
                PendingIntent.FLAG_UPDATE_CURRENT);

        if (digestTitle == null || digestTitle.length() == 0) {
            digestTitle = res.getString(R.string.no_title_label);
        }

        Notification.Builder notificationBuilder = new Notification.Builder(context);
        notificationBuilder.setContentText(digestTitle);
        notificationBuilder.setSmallIcon(R.drawable.stat_notify_calendar_multiple);
        notificationBuilder.setContentIntent(pendingClickIntent);
        notificationBuilder.setDeleteIntent(pendingDeleteIntent);
        String nEventsStr = res.getQuantityString(R.plurals.Nevents, numEvents, numEvents);
        notificationBuilder.setContentTitle(nEventsStr);

        Notification n;
        if (Utils.isJellybeanOrLater()) {
            // New-style notification...

            // Set to min priority to encourage the notification manager to collapse it.
            notificationBuilder.setPriority(Notification.PRIORITY_MIN);

            if (expandable) {
                // Multiple reminders.  Combine into an expanded digest notification.
                Notification.InboxStyle expandedBuilder = new Notification.InboxStyle();
                int i = 0;
                for (AlertService.NotificationInfo info : notificationInfos) {
                    if (i < NOTIFICATION_DIGEST_MAX_LENGTH) {
                        String name = info.eventName;
                        if (TextUtils.isEmpty(name)) {
                            name = context.getResources().getString(R.string.no_title_label);
                        }
                        String timeLocation = AlertUtils.formatTimeLocation(context,
                                info.startMillis, info.allDay, info.location);

                        TextAppearanceSpan primaryTextSpan = new TextAppearanceSpan(context,
                                R.style.NotificationPrimaryText);
                        TextAppearanceSpan secondaryTextSpan = new TextAppearanceSpan(context,
                                R.style.NotificationSecondaryText);

                        // Event title in bold.
                        SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
                        stringBuilder.append(name);
                        stringBuilder.setSpan(primaryTextSpan, 0, stringBuilder.length(), 0);
                        stringBuilder.append("  ");

                        // Followed by time and location.
                        int secondaryIndex = stringBuilder.length();
                        stringBuilder.append(timeLocation);
                        stringBuilder.setSpan(secondaryTextSpan, secondaryIndex,
                                stringBuilder.length(), 0);
                        expandedBuilder.addLine(stringBuilder);
                        i++;
                    } else {
                        break;
                    }
                }

                // If there are too many to display, add "+X missed events" for the last line.
                int remaining = numEvents - i;
                if (remaining > 0) {
                    String nMoreEventsStr = res.getQuantityString(R.plurals.N_remaining_events,
                            remaining, remaining);
                    // TODO: Add highlighting and icon to this last entry once framework allows it.
                    expandedBuilder.setSummaryText(nMoreEventsStr);
                }

                // Remove the title in the expanded form (redundant with the listed items).
                expandedBuilder.setBigContentTitle("");
                notificationBuilder.setStyle(expandedBuilder);
            }

            n = notificationBuilder.build();
        } else {
            // Old-style notification (pre-JB).  We only need a standard notification (no
            // buttons) but use a custom view so it is consistent with the others.
            n = notificationBuilder.getNotification();

            // Use custom view with buttons to provide JB-like functionality (snooze/email).
            RemoteViews contentView = new RemoteViews(context.getPackageName(),
                    R.layout.notification);
            contentView.setImageViewResource(R.id.image, R.drawable.stat_notify_calendar_multiple);
            contentView.setTextViewText(R.id.title, nEventsStr);
            contentView.setTextViewText(R.id.text, digestTitle);
            contentView.setViewVisibility(R.id.time, View.VISIBLE);
            contentView.setViewVisibility(R.id.map_button, View.GONE);
            contentView.setViewVisibility(R.id.call_button, View.GONE);
            contentView.setViewVisibility(R.id.email_button, View.GONE);
            contentView.setViewVisibility(R.id.snooze_button, View.GONE);
            contentView.setViewVisibility(R.id.end_padding, View.VISIBLE);
            n.contentView = contentView;

            // Use timestamp to force expired digest notification to the bottom (there is no
            // priority setting before JB release).  This is hidden by the custom view.
            n.when = 1;
        }

        NotificationWrapper nw = new NotificationWrapper(n);
        if (AlertService.DEBUG) {
            for (AlertService.NotificationInfo info : notificationInfos) {
                nw.add(new NotificationWrapper(null, 0, info.eventId, info.startMillis,
                        info.endMillis, false));
            }
        }
        return nw;
    }

    private void closeNotificationShade(Context context) {
        Intent closeNotificationShadeIntent = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
        context.sendBroadcast(closeNotificationShadeIntent);
    }

    private static final String[] ATTENDEES_PROJECTION = new String[] {
        Attendees.ATTENDEE_EMAIL,           // 0
        Attendees.ATTENDEE_STATUS,          // 1
    };
    private static final int ATTENDEES_INDEX_EMAIL = 0;
    private static final int ATTENDEES_INDEX_STATUS = 1;
    private static final String ATTENDEES_WHERE = Attendees.EVENT_ID + "=?";
    private static final String ATTENDEES_SORT_ORDER = Attendees.ATTENDEE_NAME + " ASC, "
            + Attendees.ATTENDEE_EMAIL + " ASC";

    private static final String[] EVENT_PROJECTION = new String[] {
        Calendars.OWNER_ACCOUNT, // 0
        Calendars.ACCOUNT_NAME,  // 1
        Events.TITLE,            // 2
        Events.ORGANIZER,        // 3
    };
    private static final int EVENT_INDEX_OWNER_ACCOUNT = 0;
    private static final int EVENT_INDEX_ACCOUNT_NAME = 1;
    private static final int EVENT_INDEX_TITLE = 2;
    private static final int EVENT_INDEX_ORGANIZER = 3;

    private static Cursor getEventCursor(Context context, long eventId) {
        return context.getContentResolver().query(
                ContentUris.withAppendedId(Events.CONTENT_URI, eventId), EVENT_PROJECTION,
                null, null, null);
    }

    private static Cursor getAttendeesCursor(Context context, long eventId) {
        return context.getContentResolver().query(Attendees.CONTENT_URI,
                ATTENDEES_PROJECTION, ATTENDEES_WHERE, new String[] { Long.toString(eventId) },
                ATTENDEES_SORT_ORDER);
    }

    private static Cursor getLocationCursor(Context context, long eventId) {
        return context.getContentResolver().query(
                ContentUris.withAppendedId(Events.CONTENT_URI, eventId),
                new String[] { Events.EVENT_LOCATION }, null, null, null);
    }

    /**
     * Creates a broadcast pending intent that fires to AlertReceiver when the email button
     * is clicked.
     */
    private static PendingIntent createBroadcastMailIntent(Context context, long eventId,
            String eventTitle) {
        // Query for viewer account.
        String syncAccount = null;
        Cursor eventCursor = getEventCursor(context, eventId);
        try {
            if (eventCursor != null && eventCursor.moveToFirst()) {
                syncAccount = eventCursor.getString(EVENT_INDEX_ACCOUNT_NAME);
            }
        } finally {
            if (eventCursor != null) {
                eventCursor.close();
            }
        }

        // Query attendees to see if there are any to email.
        Cursor attendeesCursor = getAttendeesCursor(context, eventId);
        try {
            if (attendeesCursor != null && attendeesCursor.moveToFirst()) {
                do {
                    String email = attendeesCursor.getString(ATTENDEES_INDEX_EMAIL);
                    if (Utils.isEmailableFrom(email, syncAccount)) {
                        Intent broadcastIntent = new Intent(MAIL_ACTION);
                        broadcastIntent.setClass(context, AlertReceiver.class);
                        broadcastIntent.putExtra(EXTRA_EVENT_ID, eventId);
                        return PendingIntent.getBroadcast(context,
                                Long.valueOf(eventId).hashCode(), broadcastIntent,
                                PendingIntent.FLAG_CANCEL_CURRENT);
                    }
                } while (attendeesCursor.moveToNext());
            }
            return null;

        } finally {
            if (attendeesCursor != null) {
                attendeesCursor.close();
            }
        }
    }

    /**
     * Creates an Intent for emailing the attendees of the event.  Returns null if there
     * are no emailable attendees.
     */
    static Intent createEmailIntent(Context context, long eventId, String body) {
        // TODO: Refactor to move query part into Utils.createEmailAttendeeIntent, to
        // be shared with EventInfoFragment.

        // Query for the owner account(s).
        String ownerAccount = null;
        String syncAccount = null;
        String eventTitle = null;
        String eventOrganizer = null;
        Cursor eventCursor = getEventCursor(context, eventId);
        try {
            if (eventCursor != null && eventCursor.moveToFirst()) {
                ownerAccount = eventCursor.getString(EVENT_INDEX_OWNER_ACCOUNT);
                syncAccount = eventCursor.getString(EVENT_INDEX_ACCOUNT_NAME);
                eventTitle = eventCursor.getString(EVENT_INDEX_TITLE);
                eventOrganizer = eventCursor.getString(EVENT_INDEX_ORGANIZER);
            }
        } finally {
            if (eventCursor != null) {
                eventCursor.close();
            }
        }
        if (TextUtils.isEmpty(eventTitle)) {
            eventTitle = context.getResources().getString(R.string.no_title_label);
        }

        // Query for the attendees.
        List<String> toEmails = new ArrayList<String>();
        List<String> ccEmails = new ArrayList<String>();
        Cursor attendeesCursor = getAttendeesCursor(context, eventId);
        try {
            if (attendeesCursor != null && attendeesCursor.moveToFirst()) {
                do {
                    int status = attendeesCursor.getInt(ATTENDEES_INDEX_STATUS);
                    String email = attendeesCursor.getString(ATTENDEES_INDEX_EMAIL);
                    switch(status) {
                        case Attendees.ATTENDEE_STATUS_DECLINED:
                            addIfEmailable(ccEmails, email, syncAccount);
                            break;
                        default:
                            addIfEmailable(toEmails, email, syncAccount);
                    }
                } while (attendeesCursor.moveToNext());
            }
        } finally {
            if (attendeesCursor != null) {
                attendeesCursor.close();
            }
        }

        // Add organizer only if no attendees to email (the case when too many attendees
        // in the event to sync or show).
        if (toEmails.size() == 0 && ccEmails.size() == 0 && eventOrganizer != null) {
            addIfEmailable(toEmails, eventOrganizer, syncAccount);
        }

        Intent intent = null;
        if (ownerAccount != null && (toEmails.size() > 0 || ccEmails.size() > 0)) {
            intent = Utils.createEmailAttendeesIntent(context.getResources(), eventTitle, body,
                    toEmails, ccEmails, ownerAccount);
        }

        if (intent == null) {
            return null;
        }
        else {
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
            return intent;
        }
    }

    private static void addIfEmailable(List<String> emailList, String email, String syncAccount) {
        if (Utils.isEmailableFrom(email, syncAccount)) {
            emailList.add(email);
        }
    }

    /**
     * Using the linkify magic, get a list of URLs from the event's location. If no such links
     * are found, we should end up with a single geo link of the entire string.
     */
    private static URLSpan[] getURLSpans(Context context, long eventId) {
        Cursor locationCursor = getLocationCursor(context, eventId);

        // Default to empty list
        URLSpan[] urlSpans = new URLSpan[0];
        if (locationCursor != null && locationCursor.moveToFirst()) {
            String location = locationCursor.getString(0); // Only one item in this cursor.
            if (location != null && !location.isEmpty()) {
                Spannable text = Utils.extendedLinkify(location, true);
                // The linkify method should have found at least one link, at the very least.
                // If no smart links were found, it should have set the whole string as a geo link.
                urlSpans = text.getSpans(0, text.length(), URLSpan.class);
            }
            locationCursor.close();
        }

        return urlSpans;
    }

    /**
     * Create a pending intent to send ourself a broadcast to start maps, using the first map
     * link available.
     * If no links are found, return null.
     */
    private static PendingIntent createMapBroadcastIntent(Context context, URLSpan[] urlSpans,
            long eventId) {
        for (int span_i = 0; span_i < urlSpans.length; span_i++) {
            URLSpan urlSpan = urlSpans[span_i];
            String urlString = urlSpan.getURL();
            if (urlString.startsWith(GEO_PREFIX)) {
                Intent broadcastIntent = new Intent(MAP_ACTION);
                broadcastIntent.setClass(context, AlertReceiver.class);
                broadcastIntent.putExtra(EXTRA_EVENT_ID, eventId);
                return PendingIntent.getBroadcast(context,
                        Long.valueOf(eventId).hashCode(), broadcastIntent,
                        PendingIntent.FLAG_CANCEL_CURRENT);
            }
        }

        // No geo link was found, so return null;
        return null;
    }

    /**
     * Create an intent to take the user to maps, using the first map link available.
     * If no links are found, return null.
     */
    private static Intent createMapActivityIntent(Context context, URLSpan[] urlSpans) {
        for (int span_i = 0; span_i < urlSpans.length; span_i++) {
            URLSpan urlSpan = urlSpans[span_i];
            String urlString = urlSpan.getURL();
            if (urlString.startsWith(GEO_PREFIX)) {
                Intent geoIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(urlString));
                geoIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                return geoIntent;
            }
        }

        // No geo link was found, so return null;
        return null;
    }

    /**
     * Create a pending intent to send ourself a broadcast to take the user to dialer, or any other
     * app capable of making phone calls. Use the first phone number available. If no phone number
     * is found, or if the device is not capable of making phone calls (i.e. a tablet), return null.
     */
    private static PendingIntent createCallBroadcastIntent(Context context, URLSpan[] urlSpans,
            long eventId) {
        // Return null if the device is unable to make phone calls.
        TelephonyManager tm =
                (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        if (tm.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE) {
            return null;
        }

        for (int span_i = 0; span_i < urlSpans.length; span_i++) {
            URLSpan urlSpan = urlSpans[span_i];
            String urlString = urlSpan.getURL();
            if (urlString.startsWith(TEL_PREFIX)) {
                Intent broadcastIntent = new Intent(CALL_ACTION);
                broadcastIntent.setClass(context, AlertReceiver.class);
                broadcastIntent.putExtra(EXTRA_EVENT_ID, eventId);
                return PendingIntent.getBroadcast(context,
                        Long.valueOf(eventId).hashCode(), broadcastIntent,
                        PendingIntent.FLAG_CANCEL_CURRENT);
            }
        }

        // No tel link was found, so return null;
        return null;
    }

    /**
     * Create an intent to take the user to dialer, or any other app capable of making phone calls.
     * Use the first phone number available. If no phone number is found, or if the device is
     * not capable of making phone calls (i.e. a tablet), return null.
     */
    private static Intent createCallActivityIntent(Context context, URLSpan[] urlSpans) {
        // Return null if the device is unable to make phone calls.
        TelephonyManager tm =
                (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        if (tm.getPhoneType() == TelephonyManager.PHONE_TYPE_NONE) {
            return null;
        }

        for (int span_i = 0; span_i < urlSpans.length; span_i++) {
            URLSpan urlSpan = urlSpans[span_i];
            String urlString = urlSpan.getURL();
            if (urlString.startsWith(TEL_PREFIX)) {
                Intent callIntent = new Intent(Intent.ACTION_DIAL, Uri.parse(urlString));
                callIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                return callIntent;
            }
        }

        // No tel link was found, so return null;
        return null;
    }
}
