/*
 * 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 DELETE_ALL_ACTION = "com.android.calendar.DELETEALL";
    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 (DELETE_ALL_ACTION.equals(intent.getAction())) {

            /* The user has clicked the "Clear All Notifications"
             * buttons so dismiss all Calendar alerts.
             */
            // TODO Grab a wake lock here?
            Intent serviceIntent = new Intent(context, DismissAlarmsService.class);
            context.startService(serviceIntent);
        } else 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,
                "com.android.calendar.CLICK", true);
    }

    private static PendingIntent createDeleteEventIntent(Context context, long eventId,
            long startMillis, long endMillis, int notificationId) {
        return createDismissAlarmsIntent(context, eventId, startMillis, endMillis, notificationId,
                "com.android.calendar.DELETE", false);
    }

    private static PendingIntent createDismissAlarmsIntent(Context context, long eventId,
            long startMillis, long endMillis, int notificationId, String action,
            boolean showEvent) {
        Intent intent = new Intent();
        intent.setClass(context, DismissAlarmsService.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.SHOW_EVENT_KEY, showEvent);
        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());
        intent.setAction(action);
        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(
                    basicBuilder);
            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);
            notification = expandedBuilder.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()];
        for (int i = 0; i < notificationInfos.size(); i++) {
            eventIds[i] = notificationInfos.get(i).eventId;
        }

        // 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(DELETE_ALL_ACTION);
        deleteIntent.putExtra(AlertUtils.EVENT_IDS_KEY, eventIds);
        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(
                        notificationBuilder);
                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("");

                n = expandedBuilder.build();
            } else {
                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);
        if (locationCursor != null && locationCursor.moveToFirst()) {
            String location = locationCursor.getString(0); // Only one item in this cursor.
            if (location == null || location.isEmpty()) {
                // Return an empty list if we know there was nothing in the location field.
                return new URLSpan[0];
            }

            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.
            URLSpan[] urlSpans = text.getSpans(0, text.length(), URLSpan.class);
            return urlSpans;
        }

        // If no links were found or location was empty, return an empty list.
        return new URLSpan[0];
    }

    /**
     * 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;
    }
}
