/*
 * 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 android.provider;

import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
import com.google.android.collect.Sets;

import android.content.AsyncQueryHandler;
import android.content.ContentQueryMap;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.DataSetObserver;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.text.Html;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
import android.text.style.CharacterStyle;
import android.text.util.Regex;
import android.util.Config;
import android.util.Log;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * A thin wrapper over the content resolver for accessing the gmail provider.
 *
 * @hide
 */
public final class Gmail {
    public static final String GMAIL_AUTH_SERVICE = "mail";
    // These constants come from google3/java/com/google/caribou/backend/MailLabel.java.
    public static final String LABEL_SENT = "^f";
    public static final String LABEL_INBOX = "^i";
    public static final String LABEL_DRAFT = "^r";
    public static final String LABEL_UNREAD = "^u";
    public static final String LABEL_TRASH = "^k";
    public static final String LABEL_SPAM = "^s";
    public static final String LABEL_STARRED = "^t";
    public static final String LABEL_CHAT = "^b"; // 'b' for 'buzz'
    public static final String LABEL_VOICEMAIL = "^vm";
    public static final String LABEL_IGNORED = "^g";
    public static final String LABEL_ALL = "^all";
    // These constants (starting with "^^") are only used locally and are not understood by the
    // server.
    public static final String LABEL_VOICEMAIL_INBOX = "^^vmi";
    public static final String LABEL_CACHED = "^^cached";
    public static final String LABEL_OUTBOX = "^^out";

    public static final String AUTHORITY = "gmail-ls";
    private static final String TAG = "gmail-ls";
    private static final String AUTHORITY_PLUS_CONVERSATIONS =
            "content://" + AUTHORITY + "/conversations/";
    private static final String AUTHORITY_PLUS_LABELS =
            "content://" + AUTHORITY + "/labels/";
    private static final String AUTHORITY_PLUS_MESSAGES =
            "content://" + AUTHORITY + "/messages/";
    private static final String AUTHORITY_PLUS_SETTINGS =
            "content://" + AUTHORITY + "/settings/";

    public static final Uri BASE_URI = Uri.parse(
            "content://" + AUTHORITY);
    private static final Uri LABELS_URI =
            Uri.parse(AUTHORITY_PLUS_LABELS);
    private static final Uri CONVERSATIONS_URI =
            Uri.parse(AUTHORITY_PLUS_CONVERSATIONS);
    private static final Uri SETTINGS_URI =
            Uri.parse(AUTHORITY_PLUS_SETTINGS);

    /** Separates email addresses in strings in the database. */
    public static final String EMAIL_SEPARATOR = "\n";
    public static final Pattern EMAIL_SEPARATOR_PATTERN = Pattern.compile(EMAIL_SEPARATOR);

    /**
     * Space-separated lists have separators only between items.
     */
    private static final char SPACE_SEPARATOR = ' ';
    public static final Pattern SPACE_SEPARATOR_PATTERN = Pattern.compile(" ");

    /**
     * Comma-separated lists have separators between each item, before the first and after the last
     * item. The empty list is <tt>,</tt>.
     *
     * <p>This makes them easier to modify with SQL since it is not a special case to add or
     * remove the last item. Having a separator on each side of each value also makes it safe to use
     * SQL's REPLACE to remove an item from a string by using REPLACE(',value,', ',').
     *
     * <p>We could use the same separator for both lists but this makes it easier to remember which
     * kind of list one is dealing with.
     */
    private static final char COMMA_SEPARATOR = ',';
    public static final Pattern COMMA_SEPARATOR_PATTERN = Pattern.compile(",");

    /** Separates attachment info parts in strings in the database. */
    public static final String ATTACHMENT_INFO_SEPARATOR = "\n";
    public static final Pattern ATTACHMENT_INFO_SEPARATOR_PATTERN =
            Pattern.compile(ATTACHMENT_INFO_SEPARATOR);

    public static final Character SENDER_LIST_SEPARATOR = '\n';
    public static final String SENDER_LIST_TOKEN_ELIDED = "e";
    public static final String SENDER_LIST_TOKEN_NUM_MESSAGES = "n";
    public static final String SENDER_LIST_TOKEN_NUM_DRAFTS = "d";
    public static final String SENDER_LIST_TOKEN_LITERAL = "l";
    public static final String SENDER_LIST_TOKEN_SENDING = "s";
    public static final String SENDER_LIST_TOKEN_SEND_FAILED = "f";

    /** Used for finding status in a cursor's extras. */
    public static final String EXTRA_STATUS = "status";

    public static final String RESPOND_INPUT_COMMAND = "command";
    public static final String COMMAND_RETRY = "retry";
    public static final String COMMAND_ACTIVATE = "activate";
    public static final String COMMAND_SET_VISIBLE = "setVisible";
    public static final String SET_VISIBLE_PARAM_VISIBLE = "visible";
    public static final String RESPOND_OUTPUT_COMMAND_RESPONSE = "commandResponse";
    public static final String COMMAND_RESPONSE_OK =  "ok";
    public static final String COMMAND_RESPONSE_UNKNOWN =  "unknownCommand";

    public static final String INSERT_PARAM_ATTACHMENT_ORIGIN = "origin";
    public static final String INSERT_PARAM_ATTACHMENT_ORIGIN_EXTRAS = "originExtras";

    private static final Pattern NAME_ADDRESS_PATTERN = Pattern.compile("\"(.*)\"");
    private static final Pattern UNNAMED_ADDRESS_PATTERN = Pattern.compile("([^<]+)@");

    private static final Map<Integer, Integer> sPriorityToLength = Maps.newHashMap();
    public static final SimpleStringSplitter sSenderListSplitter = 
            new SimpleStringSplitter(SENDER_LIST_SEPARATOR);
    public static String[] sSenderFragments = new String[8];

    /**
     * Returns the name in an address string
     * @param addressString such as &quot;bobby&quot; &lt;bob@example.com&gt;
     * @return returns the quoted name in the addressString, otherwise the username from the email
     *   address
     */
    public static String getNameFromAddressString(String addressString) {
        Matcher namedAddressMatch = NAME_ADDRESS_PATTERN.matcher(addressString);
        if (namedAddressMatch.find()) {
            String name = namedAddressMatch.group(1);
            if (name.length() > 0) return name;
            addressString =
                    addressString.substring(namedAddressMatch.end(), addressString.length());
        }

        Matcher unnamedAddressMatch = UNNAMED_ADDRESS_PATTERN.matcher(addressString);
        if (unnamedAddressMatch.find()) {
            return unnamedAddressMatch.group(1);
        }

        return addressString;
    }

    /**
     * Returns the email address in an address string
     * @param addressString such as &quot;bobby&quot; &lt;bob@example.com&gt;
     * @return returns the email address, such as bob@example.com from the example above
     */
    public static String getEmailFromAddressString(String addressString) {
        String result = addressString;
        Matcher match = Regex.EMAIL_ADDRESS_PATTERN.matcher(addressString);
        if (match.find()) {
            result = addressString.substring(match.start(), match.end());
        }

        return result;
    }

    /**
     * Returns whether the label is user-defined (versus system-defined labels such as inbox, whose
     * names start with "^").
     */
    public static boolean isLabelUserDefined(String label) {
        // TODO: label should never be empty so we should be able to say [label.charAt(0) != '^'].
        // However, it's a release week and I'm too scared to make that change.
        return !label.startsWith("^");
    }

    private static final Set<String> USER_SETTABLE_BUILTIN_LABELS = Sets.newHashSet(
            Gmail.LABEL_INBOX,
            Gmail.LABEL_UNREAD,
            Gmail.LABEL_TRASH,
            Gmail.LABEL_SPAM,
            Gmail.LABEL_STARRED,
            Gmail.LABEL_IGNORED);

    /**
     * Returns whether the label is user-settable. For example, labels such as LABEL_DRAFT should
     * only be set internally.
     */
    public static boolean isLabelUserSettable(String label) {
        return USER_SETTABLE_BUILTIN_LABELS.contains(label) || isLabelUserDefined(label);
    }

    /**
     * Returns the set of labels using the raw labels from a previous getRawLabels()
     * as input.
     * @return a copy of the set of labels. To add or remove labels call
     * MessageCursor.addOrRemoveLabel on each message in the conversation.
     */
    public static Set<Long> getLabelIdsFromLabelIdsString(
            TextUtils.StringSplitter splitter) {
        Set<Long> labelIds = Sets.newHashSet();
        for (String labelIdString : splitter) {
            labelIds.add(Long.valueOf(labelIdString));
        }
        return labelIds;
    }

    /**
     * @deprecated remove when the activities stop using canonical names to identify labels
     */
    public static Set<String> getCanonicalNamesFromLabelIdsString(
            LabelMap labelMap, TextUtils.StringSplitter splitter) {
        Set<String> canonicalNames = Sets.newHashSet();
        for (long labelId : getLabelIdsFromLabelIdsString(splitter)) {
            final String canonicalName = labelMap.getCanonicalName(labelId);
            // We will sometimes see labels that the label map does not yet know about or that
            // do not have names yet.
            if (!TextUtils.isEmpty(canonicalName)) {
                canonicalNames.add(canonicalName);
            } else {
                Log.w(TAG, "getCanonicalNamesFromLabelIdsString skipping label id: " + labelId);
            }
        }
        return canonicalNames;
    }

    /**
     * @return a StringSplitter that is configured to split message label id strings
     */
    public static TextUtils.StringSplitter newMessageLabelIdsSplitter() {
        return new TextUtils.SimpleStringSplitter(SPACE_SEPARATOR);
    }

    /**
     * @return a StringSplitter that is configured to split conversation label id strings
     */
    public static TextUtils.StringSplitter newConversationLabelIdsSplitter() {
        return new CommaStringSplitter();
    }

    /**
     * A splitter for strings of the form described in the docs for COMMA_SEPARATOR.
     */
    private static class CommaStringSplitter extends TextUtils.SimpleStringSplitter {

        public CommaStringSplitter() {
            super(COMMA_SEPARATOR);
        }

        @Override
        public void setString(String string) {
            // The string should always be at least a single comma.
            super.setString(string.substring(1));
        }
    }

    /**
     * Creates a single string of the form that getLabelIdsFromLabelIdsString can split.
     */
    public static String getLabelIdsStringFromLabelIds(Set<Long> labelIds) {
        StringBuilder sb = new StringBuilder();
        sb.append(COMMA_SEPARATOR);
        for (Long labelId : labelIds) {
            sb.append(labelId);
            sb.append(COMMA_SEPARATOR);
        }
        return sb.toString();
    }

    public static final class ConversationColumns {
        public static final String ID = "_id";
        public static final String SUBJECT = "subject";
        public static final String SNIPPET = "snippet";
        public static final String FROM = "fromAddress";
        public static final String DATE = "date";
        public static final String PERSONAL_LEVEL = "personalLevel";
        /** A list of label names with a space after each one (including the last one). This makes
         * it easier remove individual labels from this list using SQL. */
        public static final String LABEL_IDS = "labelIds";
        public static final String NUM_MESSAGES = "numMessages";
        public static final String MAX_MESSAGE_ID = "maxMessageId";
        public static final String HAS_ATTACHMENTS = "hasAttachments";
        public static final String HAS_MESSAGES_WITH_ERRORS = "hasMessagesWithErrors";
        public static final String FORCE_ALL_UNREAD = "forceAllUnread";

        private ConversationColumns() {}
    }

    public static final class MessageColumns {

        public static final String ID = "_id";
        public static final String MESSAGE_ID = "messageId";
        public static final String CONVERSATION_ID = "conversation";
        public static final String SUBJECT = "subject";
        public static final String SNIPPET = "snippet";
        public static final String FROM = "fromAddress";
        public static final String TO = "toAddresses";
        public static final String CC = "ccAddresses";
        public static final String BCC = "bccAddresses";
        public static final String REPLY_TO = "replyToAddresses";
        public static final String DATE_SENT_MS = "dateSentMs";
        public static final String DATE_RECEIVED_MS = "dateReceivedMs";
        public static final String LIST_INFO = "listInfo";
        public static final String PERSONAL_LEVEL = "personalLevel";
        public static final String BODY = "body";
        public static final String EMBEDS_EXTERNAL_RESOURCES = "bodyEmbedsExternalResources";
        public static final String LABEL_IDS = "labelIds";
        public static final String JOINED_ATTACHMENT_INFOS = "joinedAttachmentInfos";
        public static final String ERROR = "error";
        // TODO: add a method for accessing this
        public static final String REF_MESSAGE_ID = "refMessageId";

        // Fake columns used only for saving or sending messages.
        public static final String FAKE_SAVE = "save";
        public static final String FAKE_REF_MESSAGE_ID = "refMessageId";

        private MessageColumns() {}
    }

    public static final class LabelColumns {
        public static final String CANONICAL_NAME = "canonicalName";
        public static final String NAME = "name";
        public static final String NUM_CONVERSATIONS = "numConversations";
        public static final String NUM_UNREAD_CONVERSATIONS =
                "numUnreadConversations";

        private LabelColumns() {}
    }

    public static final class SettingsColumns {
        public static final String LABELS_INCLUDED = "labelsIncluded";
        public static final String LABELS_PARTIAL = "labelsPartial";
        public static final String CONVERSATION_AGE_DAYS =
                "conversationAgeDays";
        public static final String MAX_ATTACHMENET_SIZE_MB =
                "maxAttachmentSize";
    }

    // These are the projections that we need when getting cursors from the
    // content provider.
    private static String[] CONVERSATION_PROJECTION = {
            ConversationColumns.ID,
            ConversationColumns.SUBJECT,
            ConversationColumns.SNIPPET,
            ConversationColumns.FROM,
            ConversationColumns.DATE,
            ConversationColumns.PERSONAL_LEVEL,
            ConversationColumns.LABEL_IDS,
            ConversationColumns.NUM_MESSAGES,
            ConversationColumns.MAX_MESSAGE_ID,
            ConversationColumns.HAS_ATTACHMENTS,
            ConversationColumns.HAS_MESSAGES_WITH_ERRORS,
            ConversationColumns.FORCE_ALL_UNREAD};
    private static String[] MESSAGE_PROJECTION = {
            MessageColumns.ID,
            MessageColumns.MESSAGE_ID,
            MessageColumns.CONVERSATION_ID,
            MessageColumns.SUBJECT,
            MessageColumns.SNIPPET,
            MessageColumns.FROM,
            MessageColumns.TO,
            MessageColumns.CC,
            MessageColumns.BCC,
            MessageColumns.REPLY_TO,
            MessageColumns.DATE_SENT_MS,
            MessageColumns.DATE_RECEIVED_MS,
            MessageColumns.LIST_INFO,
            MessageColumns.PERSONAL_LEVEL,
            MessageColumns.BODY,
            MessageColumns.EMBEDS_EXTERNAL_RESOURCES,
            MessageColumns.LABEL_IDS,
            MessageColumns.JOINED_ATTACHMENT_INFOS,
            MessageColumns.ERROR};
    private static String[] LABEL_PROJECTION = {
            BaseColumns._ID,
            LabelColumns.CANONICAL_NAME,
            LabelColumns.NAME,
            LabelColumns.NUM_CONVERSATIONS,
            LabelColumns.NUM_UNREAD_CONVERSATIONS};
    private static String[] SETTINGS_PROJECTION = {
            SettingsColumns.LABELS_INCLUDED,
            SettingsColumns.LABELS_PARTIAL,
            SettingsColumns.CONVERSATION_AGE_DAYS,
            SettingsColumns.MAX_ATTACHMENET_SIZE_MB,
    };

    private ContentResolver mContentResolver;

    public Gmail(ContentResolver contentResolver) {
        mContentResolver = contentResolver;
    }

    /**
     * Returns source if source is non-null. Returns the empty string otherwise.
     */
    private static String toNonnullString(String source) {
        if (source == null) {
            return "";
        } else {
            return source;
        }
    }

    /**
     * Wraps a Cursor in a ConversationCursor
     *
     * @param account the account the cursor is associated with
     * @param cursor The Cursor to wrap
     * @return a new ConversationCursor
     */
    public ConversationCursor getConversationCursorForCursor(String account, Cursor cursor) {
        if (TextUtils.isEmpty(account)) {
            throw new IllegalArgumentException("account is empty");
        }
        return new ConversationCursor(this, account, cursor);
    }

    /**
     * Asynchronously gets a cursor over all conversations matching a query. The
     * query is in Gmail's query syntax. When the operation is complete the handler's
     * onQueryComplete() method is called with the resulting Cursor.
     *
     * @param account run the query on this account
     * @param handler An AsyncQueryHanlder that will be used to run the query
     * @param token The token to pass to startQuery, which will be passed back to onQueryComplete
     * @param query a query in Gmail's query syntax
     */
    public void runQueryForConversations(String account, AsyncQueryHandler handler, int token,
            String query) {
        if (TextUtils.isEmpty(account)) {
            throw new IllegalArgumentException("account is empty");
        }
        handler.startQuery(token, null, Uri.withAppendedPath(CONVERSATIONS_URI, account),
                CONVERSATION_PROJECTION, query, null, null);
    }

    /**
     * Synchronously gets a cursor over all conversations matching a query. The
     * query is in Gmail's query syntax.
     *
     * @param account run the query on this account
     * @param query a query in Gmail's query syntax
     */
    public ConversationCursor getConversationCursorForQuery(String account, String query) {
        Cursor cursor = mContentResolver.query(
                Uri.withAppendedPath(CONVERSATIONS_URI, account), CONVERSATION_PROJECTION,
                query, null, null);
        return new ConversationCursor(this, account, cursor);
    }

    /**
     * Gets a message cursor over the single message with the given id.
     *
     * @param account get the cursor for messages in this account
     * @param messageId the id of the message
     * @return a cursor over the message
     */
    public MessageCursor getMessageCursorForMessageId(String account, long messageId) {
        if (TextUtils.isEmpty(account)) {
            throw new IllegalArgumentException("account is empty");
        }
        Uri uri = Uri.parse(AUTHORITY_PLUS_MESSAGES + account + "/" + messageId);
        Cursor cursor = mContentResolver.query(uri, MESSAGE_PROJECTION, null, null, null);
        return new MessageCursor(this, mContentResolver, account, cursor);
    }

    /**
     * Gets a message cursor over the messages that match the query. Note that
     * this simply finds all of the messages that match and returns them. It
     * does not return all messages in conversations where any message matches.
     *
     * @param account get the cursor for messages in this account
     * @param query a query in GMail's query syntax. Currently only queries of
     *     the form [label:<label>] are supported
     * @return a cursor over the messages
     */
    public MessageCursor getLocalMessageCursorForQuery(String account, String query) {
        if (TextUtils.isEmpty(account)) {
            throw new IllegalArgumentException("account is empty");
        }
        Uri uri = Uri.parse(AUTHORITY_PLUS_MESSAGES + account + "/");
        Cursor cursor = mContentResolver.query(uri, MESSAGE_PROJECTION, query, null, null);
        return new MessageCursor(this, mContentResolver, account, cursor);
    }

    /**
     * Gets a cursor over all of the messages in a conversation.
     *
     * @param account get the cursor for messages in this account
     * @param conversationId the id of the converstion to fetch messages for
     * @return a cursor over messages in the conversation
     */
    public MessageCursor getMessageCursorForConversationId(String account, long conversationId) {
        if (TextUtils.isEmpty(account)) {
            throw new IllegalArgumentException("account is empty");
        }
        Uri uri = Uri.parse(
                AUTHORITY_PLUS_CONVERSATIONS + account + "/" + conversationId + "/messages");
        Cursor cursor = mContentResolver.query(
                uri, MESSAGE_PROJECTION, null, null, null);
        return new MessageCursor(this, mContentResolver, account, cursor);
    }

    /**
     * Expunge the indicated message. One use of this is to discard drafts.
     *
     * @param account the account of the message id
     * @param messageId the id of the message to expunge
     */
    public void expungeMessage(String account, long messageId) {
        if (TextUtils.isEmpty(account)) {
            throw new IllegalArgumentException("account is empty");
        }
        Uri uri = Uri.parse(AUTHORITY_PLUS_MESSAGES + account + "/" + messageId);
        mContentResolver.delete(uri, null, null);
    }

    /**
     * Adds or removes the label on the conversation.
     *
     * @param account the account of the conversation
     * @param conversationId the conversation
     * @param maxServerMessageId the highest message id to whose labels should be changed. Note that
     *   everywhere else in this file messageId means local message id but here you need to use a
     *   server message id.
     * @param label the label to add or remove
     * @param add true to add the label, false to remove it
     * @throws NonexistentLabelException thrown if the label does not exist
     */
    public void addOrRemoveLabelOnConversation(
            String account, long conversationId, long maxServerMessageId, String label,
            boolean add)
            throws NonexistentLabelException {
        if (TextUtils.isEmpty(account)) {
            throw new IllegalArgumentException("account is empty");
        }
        if (add) {
            Uri uri = Uri.parse(
                    AUTHORITY_PLUS_CONVERSATIONS + account + "/" + conversationId + "/labels");
            ContentValues values = new ContentValues();
            values.put(LabelColumns.CANONICAL_NAME, label);
            values.put(ConversationColumns.MAX_MESSAGE_ID, maxServerMessageId);
            mContentResolver.insert(uri, values);
        } else {
            String encodedLabel;
            try {
                encodedLabel = URLEncoder.encode(label, "utf-8");
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
            Uri uri = Uri.parse(
                    AUTHORITY_PLUS_CONVERSATIONS + account + "/"
                            + conversationId + "/labels/" + encodedLabel);
            mContentResolver.delete(
                    uri, ConversationColumns.MAX_MESSAGE_ID, new String[]{"" + maxServerMessageId});
        }
    }

    /**
     * Adds or removes the label on the message.
     *
     * @param contentResolver the content resolver.
     * @param account the account of the message
     * @param conversationId the conversation containing the message
     * @param messageId the id of the message to whose labels should be changed
     * @param label the label to add or remove
     * @param add true to add the label, false to remove it
     * @throws NonexistentLabelException thrown if the label does not exist
     */
    public static void addOrRemoveLabelOnMessage(ContentResolver contentResolver, String account,
            long conversationId, long messageId, String label, boolean add) {

        // conversationId is unused but we want to start passing it whereever we pass a message id.
        if (add) {
            Uri uri = Uri.parse(
                    AUTHORITY_PLUS_MESSAGES + account + "/" + messageId + "/labels");
            ContentValues values = new ContentValues();
            values.put(LabelColumns.CANONICAL_NAME, label);
            contentResolver.insert(uri, values);
        } else {
            String encodedLabel;
            try {
                encodedLabel = URLEncoder.encode(label, "utf-8");
            } catch (UnsupportedEncodingException e) {
                throw new RuntimeException(e);
            }
            Uri uri = Uri.parse(
                    AUTHORITY_PLUS_MESSAGES + account + "/" + messageId
                    + "/labels/" + encodedLabel);
            contentResolver.delete(uri, null, null);
        }
    }

    /**
     * The mail provider will send an intent when certain changes happen in certain labels.
     * Currently those labels are inbox and voicemail.
     *
     * <p>The intent will have the action ACTION_PROVIDER_CHANGED and the extras mentioned below.
     * The data for the intent will be content://gmail-ls/unread/<name of label>.
     *
     * <p>The goal is to support the following user experience:<ul>
     *   <li>When present the new mail indicator reports the number of unread conversations in the
     *   inbox (or some other label).</li>
     *   <li>When the user views the inbox the indicator is removed immediately. They do not have to
     *   read all of the conversations.</li>
     *   <li>If more mail arrives the indicator reappears and shows the total number of unread
     *   conversations in the inbox.</li>
     *   <li>If the user reads the new conversations on the web the indicator disappears on the
     *   phone since there is no unread mail in the inbox that the user hasn't seen.</li>
     *   <li>The phone should vibrate/etc when it transitions from having no unseen unread inbox
     *   mail to having some.</li>
     */

    /** The account in which the change occurred. */
    static public final String PROVIDER_CHANGED_EXTRA_ACCOUNT = "account";

    /** The number of unread conversations matching the label. */
    static public final String PROVIDER_CHANGED_EXTRA_COUNT = "count";

    /** Whether to get the user's attention, perhaps by vibrating. */
    static public final String PROVIDER_CHANGED_EXTRA_GET_ATTENTION = "getAttention";

    /**
     * A label that is attached to all of the conversations being notified about. This enables the
     * receiver of a notification to get a list of matching conversations.
     */
    static public final String PROVIDER_CHANGED_EXTRA_TAG_LABEL = "tagLabel";

    /**
     * Settings for which conversations should be synced to the phone.
     * Conversations are synced if any message matches any of the following
     * criteria:
     *
     * <ul>
     *   <li>the message has a label in the include set</li>
     *   <li>the message is no older than conversationAgeDays and has a label in the partial set.
     *   </li>
     *   <li>also, pending changes on the server: the message has no user-controllable labels.</li>
     * </ul>
     *
     * <p>A user-controllable label is a user-defined label or star, inbox,
     * trash, spam, etc. LABEL_UNREAD is not considered user-controllable.
     */
    public static class Settings {
        public long conversationAgeDays;
        public long maxAttachmentSizeMb;
        public String[] labelsIncluded;
        public String[] labelsPartial;
    }

    /**
     * Returns the settings.
     * @param account the account whose setting should be retrieved
     */
    public Settings getSettings(String account) {
        if (TextUtils.isEmpty(account)) {
            throw new IllegalArgumentException("account is empty");
        }
        Settings settings = new Settings();
        Cursor cursor = mContentResolver.query(
                Uri.withAppendedPath(SETTINGS_URI, account), SETTINGS_PROJECTION, null, null, null);
        cursor.moveToNext();
        settings.labelsIncluded = TextUtils.split(cursor.getString(0), SPACE_SEPARATOR_PATTERN);
        settings.labelsPartial = TextUtils.split(cursor.getString(1), SPACE_SEPARATOR_PATTERN);
        settings.conversationAgeDays = Long.parseLong(cursor.getString(2));
        settings.maxAttachmentSizeMb = Long.parseLong(cursor.getString(3));
        cursor.close();
        return settings;
    }

    /**
     * Sets the settings. A sync will be scheduled automatically.
     */
    public void setSettings(String account, Settings settings) {
        if (TextUtils.isEmpty(account)) {
            throw new IllegalArgumentException("account is empty");
        }
        ContentValues values = new ContentValues();
        values.put(
                SettingsColumns.LABELS_INCLUDED,
                TextUtils.join(" ", settings.labelsIncluded));
        values.put(
                SettingsColumns.LABELS_PARTIAL,
                TextUtils.join(" ", settings.labelsPartial));
        values.put(
                SettingsColumns.CONVERSATION_AGE_DAYS,
                settings.conversationAgeDays);
        values.put(
                SettingsColumns.MAX_ATTACHMENET_SIZE_MB,
                settings.maxAttachmentSizeMb);
        mContentResolver.update(Uri.withAppendedPath(SETTINGS_URI, account), values, null, null);
    }

    /**
     * Uses sender instructions to build a formatted string.
     *
     * <p>Sender list instructions contain compact information about the sender list. Most work that
     * can be done without knowing how much room will be availble for the sender list is done when
     * creating the instructions.
     *
     * <p>The instructions string consists of tokens separated by SENDER_LIST_SEPARATOR. Here are
     * the tokens, one per line:<ul>
     * <li><tt>n</tt></li>
     * <li><em>int</em>, the number of non-draft messages in the conversation</li>
     * <li><tt>d</tt</li>
     * <li><em>int</em>, the number of drafts in the conversation</li>
     * <li><tt>l</tt></li>
     * <li><em>literal html to be included in the output</em></li>
     * <li><tt>s</tt> indicates that the message is sending (in the outbox without errors)</li>
     * <li><tt>f</tt> indicates that the message failed to send (in the outbox with errors)</li>
     * <li><em>for each message</em><ul>
     *   <li><em>int</em>, 0 for read, 1 for unread</li>
     *   <li><em>int</em>, the priority of the message. Zero is the most important</li>
     *   <li><em>text</em>, the sender text or blank for messages from 'me'</li>
     * </ul></li>
     * <li><tt>e</tt> to indicate that one or more messages have been elided</li>
     *
     * <p>The instructions indicate how many messages and drafts are in the conversation and then
     * describe the most important messages in order, indicating the priority of each message and
     * whether the message is unread.
     *
     * @param instructions instructions as described above
     * @param sb the SpannableStringBuilder to append to
     * @param maxChars the number of characters available to display the text
     * @param unreadStyle the CharacterStyle for unread messages, or null
     * @param draftsStyle the CharacterStyle for draft messages, or null
     * @param sendingString the string to use when there are messages scheduled to be sent
     * @param sendFailedString the string to use when there are messages that mailed to send
     * @param meString the string to use for messages sent by this user
     * @param draftString the string to use for "Draft"
     * @param draftPluralString the string to use for "Drafts" 
     */
    public static void getSenderSnippet(
            String instructions, SpannableStringBuilder sb, int maxChars,
            CharacterStyle unreadStyle,
            CharacterStyle draftsStyle,
            CharSequence meString, CharSequence draftString, CharSequence draftPluralString,
            CharSequence sendingString, CharSequence sendFailedString,
            boolean forceAllUnread, boolean forceAllRead) {
        assert !(forceAllUnread && forceAllRead);
        boolean unreadStatusIsForced = forceAllUnread || forceAllRead;
        boolean forcedUnreadStatus = forceAllUnread;

        // Measure each fragment. It's ok to iterate over the entire set of fragments because it is
        // never a long list, even if there are many senders.
        final Map<Integer, Integer> priorityToLength = sPriorityToLength;
        priorityToLength.clear();

        int maxFoundPriority = Integer.MIN_VALUE;
        int numMessages = 0;
        int numDrafts = 0;
        CharSequence draftsFragment = "";
        CharSequence sendingFragment = "";
        CharSequence sendFailedFragment = "";
        
        sSenderListSplitter.setString(instructions);
        int numFragments = 0;
        String[] fragments = sSenderFragments;
        int currentSize = fragments.length;
        while (sSenderListSplitter.hasNext()) {
            fragments[numFragments++] = sSenderListSplitter.next();
            if (numFragments == currentSize) {
                sSenderFragments = new String[2 * currentSize];
                System.arraycopy(fragments, 0, sSenderFragments, 0, currentSize);
                currentSize *= 2;
                fragments = sSenderFragments;
            }
        }
        
        for (int i = 0; i < numFragments;) {
            String fragment0 = fragments[i++];
            if ("".equals(fragment0)) {
                // This should be the final fragment.
            } else if (Gmail.SENDER_LIST_TOKEN_ELIDED.equals(fragment0)) {
                // ignore
            } else if (Gmail.SENDER_LIST_TOKEN_NUM_MESSAGES.equals(fragment0)) {
                numMessages = Integer.valueOf(fragments[i++]);
            } else if (Gmail.SENDER_LIST_TOKEN_NUM_DRAFTS.equals(fragment0)) {
                String numDraftsString = fragments[i++];
                numDrafts = Integer.parseInt(numDraftsString);
                draftsFragment = numDrafts == 1 ? draftString :
                        draftPluralString + " (" + numDraftsString + ")";
            } else if (Gmail.SENDER_LIST_TOKEN_LITERAL.equals(fragment0)) {
                sb.append(Html.fromHtml(fragments[i++]));
                return;
            } else if (Gmail.SENDER_LIST_TOKEN_SENDING.equals(fragment0)) {
                sendingFragment = sendingString;
            } else if (Gmail.SENDER_LIST_TOKEN_SEND_FAILED.equals(fragment0)) {
                sendFailedFragment = sendFailedString;
            } else {
                String priorityString = fragments[i++];
                CharSequence nameString = fragments[i++];
                if (nameString.length() == 0) nameString = meString;
                int priority = Integer.parseInt(priorityString);
                priorityToLength.put(priority, nameString.length());
                maxFoundPriority = Math.max(maxFoundPriority, priority);
            }
        }
        String numMessagesFragment =
                (numMessages != 0) ? " (" + Integer.toString(numMessages + numDrafts) + ")" : "";

        // Don't allocate fixedFragment unless we need it
        SpannableStringBuilder fixedFragment = null;
        int fixedFragmentLength = 0;
        if (draftsFragment.length() != 0) {
            if (fixedFragment == null) {
                fixedFragment = new SpannableStringBuilder();
            }
            fixedFragment.append(draftsFragment);
            if (draftsStyle != null) {
                fixedFragment.setSpan(
                        CharacterStyle.wrap(draftsStyle),
                        0, fixedFragment.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
        if (sendingFragment.length() != 0) {
            if (fixedFragment == null) {
                fixedFragment = new SpannableStringBuilder();
            }
            if (fixedFragment.length() != 0) fixedFragment.append(", ");
            fixedFragment.append(sendingFragment);
        }
        if (sendFailedFragment.length() != 0) {
            if (fixedFragment == null) {
                fixedFragment = new SpannableStringBuilder();
            }
            if (fixedFragment.length() != 0) fixedFragment.append(", ");
            fixedFragment.append(sendFailedFragment);
        }

        if (fixedFragment != null) {
            fixedFragmentLength = fixedFragment.length();
        }

        final boolean normalMessagesExist =
                numMessagesFragment.length() != 0 || maxFoundPriority != Integer.MIN_VALUE;
        String preFixedFragement = "";
        if (normalMessagesExist && fixedFragmentLength != 0) {
            preFixedFragement = ", ";
        }
        int maxPriorityToInclude = -1; // inclusive
        int numCharsUsed =
                numMessagesFragment.length() + preFixedFragement.length() + fixedFragmentLength;
        int numSendersUsed = 0;
        while (maxPriorityToInclude < maxFoundPriority) {
            if (priorityToLength.containsKey(maxPriorityToInclude + 1)) {
                int length = numCharsUsed + priorityToLength.get(maxPriorityToInclude + 1);
                if (numCharsUsed > 0) length += 2;
                // We must show at least two senders if they exist. If we don't have space for both
                // then we will truncate names.
                if (length > maxChars && numSendersUsed >= 2) {
                    break;
                }
                numCharsUsed = length;
                numSendersUsed++;
            }
            maxPriorityToInclude++;
        }

        int numCharsToRemovePerWord = 0;
        if (numCharsUsed > maxChars) {
            numCharsToRemovePerWord = (numCharsUsed - maxChars) / numSendersUsed;
        }

        boolean elided = false;
        for (int i = 0; i < numFragments;) {
            String fragment0 = fragments[i++];
            if ("".equals(fragment0)) {
                // This should be the final fragment.
            } else if (SENDER_LIST_TOKEN_ELIDED.equals(fragment0)) {
                elided = true;
            } else if (SENDER_LIST_TOKEN_NUM_MESSAGES.equals(fragment0)) {
                i++;
            } else if (SENDER_LIST_TOKEN_NUM_DRAFTS.equals(fragment0)) {
                i++;
            } else if (SENDER_LIST_TOKEN_SENDING.equals(fragment0)) {
            } else if (SENDER_LIST_TOKEN_SEND_FAILED.equals(fragment0)) {
            } else {
                final String unreadString = fragment0;
                final String priorityString = fragments[i++];
                String nameString = fragments[i++];
                if (nameString.length() == 0) nameString = meString.toString();
                if (numCharsToRemovePerWord != 0) {
                    nameString = nameString.substring(
                            0, Math.max(nameString.length() - numCharsToRemovePerWord, 0));
                }
                final boolean unread = unreadStatusIsForced
                        ? forcedUnreadStatus : Integer.parseInt(unreadString) != 0;
                final int priority = Integer.parseInt(priorityString);
                if (priority <= maxPriorityToInclude) {
                    if (sb.length() != 0) {
                        sb.append(elided ? " .. " : ", ");
                    }
                    elided = false;
                    int pos = sb.length();
                    sb.append(nameString);
                    if (unread && unreadStyle != null) {
                        sb.setSpan(CharacterStyle.wrap(unreadStyle),
                                pos, sb.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
                    }
                } else {
                    elided = true;
                }
            }
        }
        sb.append(numMessagesFragment);
        if (fixedFragmentLength != 0) {
            sb.append(preFixedFragement);
            sb.append(fixedFragment);
        }
    }

    /**
     * This is a cursor that only defines methods to move throught the results
     * and register to hear about changes. All access to the data is left to
     * subinterfaces.
     */
    public static class MailCursor extends ContentObserver {

        // A list of observers of this cursor.
        private Set<MailCursorObserver> mObservers;

        // Updated values are accumulated here before being written out if the
        // cursor is asked to persist the changes.
        private ContentValues mUpdateValues;

        protected Cursor mCursor;
        protected String mAccount;

        public Cursor getCursor() {
            return mCursor;
        }

        /**
         * Constructs the MailCursor given a regular cursor, registering as a
         * change observer of the cursor.
         * @param account the account the cursor is associated with
         * @param cursor the underlying cursor
         */
        protected MailCursor(String account, Cursor cursor) {
            super(new Handler());
            mObservers = new HashSet<MailCursorObserver>();
            mCursor = cursor;
            mAccount = account;
            if (mCursor != null) mCursor.registerContentObserver(this);
        }

        /**
         * Gets the account associated with this cursor.
         * @return the account.
         */
        public String getAccount() {
            return mAccount;
        }

        protected void checkThread() {
            // Turn this on when activity code no longer runs in the sync thread
            // after notifications of changes.
//            Thread currentThread = Thread.currentThread();
//            if (currentThread != mThread) {
//                throw new RuntimeException("Accessed from the wrong thread");
//            }
        }

        /**
         * Lazily constructs a map of update values to apply to the database
         * if requested. This map is cleared out when we move to a different
         * item in the result set.
         *
         * @return a map of values to be applied by an update.
         */
        protected ContentValues getUpdateValues() {
            if (mUpdateValues == null) {
                mUpdateValues = new ContentValues();
            }
            return mUpdateValues;
        }

        /**
         * Called whenever mCursor is changed to point to a different row.
         * Subclasses should override this if they need to clear out state
         * when this happens.
         *
         * Subclasses must call the inherited version if they override this.
         */
        protected void onCursorPositionChanged() {
            mUpdateValues = null;
        }

        // ********* MailCursor

        /**
         * Returns the numbers of rows in the cursor.
         *
         * @return the number of rows in the cursor.
         */
        final public int count() {
            if (mCursor != null) {
                return mCursor.getCount();
            } else {
                return 0;
            }
        }

        /**
         * @return the current position of this cursor, or -1 if this cursor
         * has not been initialized.
         */
        final public int position() {
            if (mCursor != null) {
                return mCursor.getPosition();
            } else {
                return -1;
            }
        }

        /**
         * Move the cursor to an absolute position. The valid
         * range of vaues is -1 &lt;= position &lt;= count.
         *
         * <p>This method will return true if the request destination was
         * reachable, otherwise it returns false.
         *
         * @param position the zero-based position to move to.
         * @return whether the requested move fully succeeded.
         */
        final public boolean moveTo(int position) {
            checkCursor();
            checkThread();
            boolean moved = mCursor.moveToPosition(position);
            if (moved) onCursorPositionChanged();
            return moved;
        }

        /**
         * Move the cursor to the next row.
         *
         * <p>This method will return false if the cursor is already past the
         * last entry in the result set.
         *
         * @return whether the move succeeded.
         */
        final public boolean next() {
            checkCursor();
            checkThread();
            boolean moved = mCursor.moveToNext();
            if (moved) onCursorPositionChanged();
            return moved;
        }

        /**
         * Release all resources and locks associated with the cursor. The
         * cursor will not be valid after this function is called.
         */
        final public void release() {
            if (mCursor != null) {
                mCursor.unregisterContentObserver(this);
                mCursor.deactivate();
            }
        }

        final public void registerContentObserver(ContentObserver observer) {
            mCursor.registerContentObserver(observer);
        }

        final public void unregisterContentObserver(ContentObserver observer) {
            mCursor.unregisterContentObserver(observer);
        }

        final public void registerDataSetObserver(DataSetObserver observer) {
            mCursor.registerDataSetObserver(observer);
        }

        final public void unregisterDataSetObserver(DataSetObserver observer) {
            mCursor.unregisterDataSetObserver(observer);
        }

        /**
         * Register an observer to hear about changes to the cursor.
         *
         * @param observer the observer to register
         */
        final public void registerObserver(MailCursorObserver observer) {
            mObservers.add(observer);
        }

        /**
         * Unregister an observer.
         *
         * @param observer the observer to unregister
         */
        final public void unregisterObserver(MailCursorObserver observer) {
            mObservers.remove(observer);
        }

        // ********* ContentObserver

        @Override
        final public boolean deliverSelfNotifications() {
            return false;
        }

        @Override
        public void onChange(boolean selfChange) {
            if (Config.DEBUG) {
                Log.d(TAG, "MailCursor is notifying " + mObservers.size() + " observers");
            }
            for (MailCursorObserver o: mObservers) {
                o.onCursorChanged(this);
            }
        }

        protected void checkCursor() {
            if (mCursor == null) {
                throw new IllegalStateException(
                        "cannot read from an insertion cursor");
            }
        }

        /**
         * Returns the string value of the column, or "" if the value is null.
         */
        protected String getStringInColumn(int columnIndex) {
            checkCursor();
            return toNonnullString(mCursor.getString(columnIndex));
        }
    }

    /**
     * A MailCursor observer is notified of changes to the result set of a
     * cursor.
     */
    public interface MailCursorObserver {

        /**
         * Called when the result set of a cursor has changed.
         *
         * @param cursor the cursor whose result set has changed.
         */
        void onCursorChanged(MailCursor cursor);
    }

    /**
     * Thrown when an operation is requested with a label that does not exist.
     *
     * TODO: this is here because I wanted a checked exception. However, I don't
     * think that that is appropriate. In fact, I don't think that we should
     * throw an exception at all because the label might have been valid when
     * the caller presented it to the user but removed as a result of a sync.
     * Maybe we should kill this and eat the errors.
     */
    public static class NonexistentLabelException extends Exception {
        // TODO: Add label name?
    }

    /**
     * A cursor over labels.
     */
    public final class LabelCursor extends MailCursor {

        private int mNameIndex;
        private int mNumConversationsIndex;
        private int mNumUnreadConversationsIndex;

        private LabelCursor(String account, Cursor cursor) {
            super(account, cursor);

            mNameIndex = mCursor.getColumnIndexOrThrow(LabelColumns.CANONICAL_NAME);
            mNumConversationsIndex =
                    mCursor.getColumnIndexOrThrow(LabelColumns.NUM_CONVERSATIONS);
            mNumUnreadConversationsIndex = mCursor.getColumnIndexOrThrow(
                    LabelColumns.NUM_UNREAD_CONVERSATIONS);
        }

        /**
         * Gets the canonical name of the current label.
         *
         * @return the current label's name.
         */
        public String getName() {
            return getStringInColumn(mNameIndex);
        }

        /**
         * Gets the number of conversations with this label.
         *
         * @return the number of conversations with this label.
         */
        public int getNumConversations() {
            return mCursor.getInt(mNumConversationsIndex);
        }

        /**
         * Gets the number of unread conversations with this label.
         *
         * @return the number of unread conversations with this label.
         */
        public int getNumUnreadConversations() {
            return mCursor.getInt(mNumUnreadConversationsIndex);
        }
    }

    /**
     * This is a map of labels. TODO: make it observable.
     */
    public static final class LabelMap extends Observable {
        private final static ContentValues EMPTY_CONTENT_VALUES = new ContentValues();

        private ContentQueryMap mQueryMap;
        private SortedSet<String> mSortedUserLabels;
        private Map<String, Long> mCanonicalNameToId;

        private long mLabelIdSent;
        private long mLabelIdInbox;
        private long mLabelIdDraft;
        private long mLabelIdUnread;
        private long mLabelIdTrash;
        private long mLabelIdSpam;
        private long mLabelIdStarred;
        private long mLabelIdChat;
        private long mLabelIdVoicemail;
        private long mLabelIdIgnored;
        private long mLabelIdVoicemailInbox;
        private long mLabelIdCached;
        private long mLabelIdOutbox;

        private boolean mLabelsSynced = false;

        public LabelMap(ContentResolver contentResolver, String account, boolean keepUpdated) {
            if (TextUtils.isEmpty(account)) {
                throw new IllegalArgumentException("account is empty");
            }
            Cursor cursor = contentResolver.query(
                    Uri.withAppendedPath(LABELS_URI, account), LABEL_PROJECTION, null, null, null);
            init(cursor, keepUpdated);
        }

        public LabelMap(Cursor cursor, boolean keepUpdated) {
            init(cursor, keepUpdated);
        }

        private void init(Cursor cursor, boolean keepUpdated) {
            mQueryMap = new ContentQueryMap(cursor, BaseColumns._ID, keepUpdated, null);
            mSortedUserLabels = new TreeSet<String>(java.text.Collator.getInstance());
            mCanonicalNameToId = Maps.newHashMap();
            updateDataStructures();
            mQueryMap.addObserver(new Observer() {
                public void update(Observable observable, Object data) {
                    updateDataStructures();
                    setChanged();
                    notifyObservers();
                }
            });
        }

        /**
         * @return whether at least some labels have been synced.
         */
        public boolean labelsSynced() {
            return mLabelsSynced;
        }

        /**
         * Updates the data structures that are maintained separately from mQueryMap after the query
         * map has changed.
         */
        private void updateDataStructures() {
            mSortedUserLabels.clear();
            mCanonicalNameToId.clear();
            for (Map.Entry<String, ContentValues> row : mQueryMap.getRows().entrySet()) {
                long labelId = Long.valueOf(row.getKey());
                String canonicalName = row.getValue().getAsString(LabelColumns.CANONICAL_NAME);
                if (isLabelUserDefined(canonicalName)) {
                    mSortedUserLabels.add(canonicalName);
                }
                mCanonicalNameToId.put(canonicalName, labelId);

                if (LABEL_SENT.equals(canonicalName)) {
                    mLabelIdSent = labelId;
                } else if (LABEL_INBOX.equals(canonicalName)) {
                    mLabelIdInbox = labelId;
                } else if (LABEL_DRAFT.equals(canonicalName)) {
                    mLabelIdDraft = labelId;
                } else if (LABEL_UNREAD.equals(canonicalName)) {
                    mLabelIdUnread = labelId;
                } else if (LABEL_TRASH.equals(canonicalName)) {
                    mLabelIdTrash = labelId;
                } else if (LABEL_SPAM.equals(canonicalName)) {
                    mLabelIdSpam = labelId;
                } else if (LABEL_STARRED.equals(canonicalName)) {
                    mLabelIdStarred = labelId;
                } else if (LABEL_CHAT.equals(canonicalName)) {
                    mLabelIdChat = labelId;
                } else if (LABEL_IGNORED.equals(canonicalName)) {
                    mLabelIdIgnored = labelId;
                } else if (LABEL_VOICEMAIL.equals(canonicalName)) {
                    mLabelIdVoicemail = labelId;
                } else if (LABEL_VOICEMAIL_INBOX.equals(canonicalName)) {
                    mLabelIdVoicemailInbox = labelId;
                } else if (LABEL_CACHED.equals(canonicalName)) {
                    mLabelIdCached = labelId;
                } else if (LABEL_OUTBOX.equals(canonicalName)) {
                    mLabelIdOutbox = labelId;
                }
                mLabelsSynced = mLabelIdSent != 0
                    && mLabelIdInbox != 0
                    && mLabelIdDraft != 0
                    && mLabelIdUnread != 0
                    && mLabelIdTrash != 0
                    && mLabelIdSpam != 0
                    && mLabelIdStarred != 0
                    && mLabelIdChat != 0
                    && mLabelIdIgnored != 0
                    && mLabelIdVoicemail != 0;
            }
        }

        public long getLabelIdSent() {
            checkLabelsSynced();
            return mLabelIdSent;
        }

        public long getLabelIdInbox() {
            checkLabelsSynced();
            return mLabelIdInbox;
        }

        public long getLabelIdDraft() {
            checkLabelsSynced();
            return mLabelIdDraft;
        }

        public long getLabelIdUnread() {
            checkLabelsSynced();
            return mLabelIdUnread;
        }

        public long getLabelIdTrash() {
            checkLabelsSynced();
            return mLabelIdTrash;
        }

        public long getLabelIdSpam() {
            checkLabelsSynced();
            return mLabelIdSpam;
        }

        public long getLabelIdStarred() {
            checkLabelsSynced();
            return mLabelIdStarred;
        }

        public long getLabelIdChat() {
            checkLabelsSynced();
            return mLabelIdChat;
        }

        public long getLabelIdIgnored() {
            checkLabelsSynced();
            return mLabelIdIgnored;
        }

        public long getLabelIdVoicemail() {
            checkLabelsSynced();
            return mLabelIdVoicemail;
        }

        public long getLabelIdVoicemailInbox() {
            checkLabelsSynced();
            return mLabelIdVoicemailInbox;
        }

        public long getLabelIdCached() {
            checkLabelsSynced();
            return mLabelIdCached;
        }

        public long getLabelIdOutbox() {
            checkLabelsSynced();
            return mLabelIdOutbox;
        }

        private void checkLabelsSynced() {
            if (!labelsSynced()) {
                throw new IllegalStateException("LabelMap not initalized");
            }
        }

        /** Returns the list of user-defined labels in alphabetical order. */
        public SortedSet<String> getSortedUserLabels() {
            return mSortedUserLabels;
        }

        private static final List<String> SORTED_USER_MEANINGFUL_SYSTEM_LABELS =
                Lists.newArrayList(
                        LABEL_INBOX, LABEL_STARRED, LABEL_CHAT, LABEL_SENT,
                        LABEL_OUTBOX, LABEL_DRAFT, LABEL_ALL,
                        LABEL_SPAM, LABEL_TRASH);

        public static List<String> getSortedUserMeaningfulSystemLabels() {
            return SORTED_USER_MEANINGFUL_SYSTEM_LABELS;
        }

        /**
         * If you are ever tempted to remove outbox or draft from this set make sure you have a
         * way to stop draft and outbox messages from getting purged before they are sent to the
         * server.
         */
        private static final Set<String> FORCED_INCLUDED_LABELS =
                Sets.newHashSet(LABEL_OUTBOX, LABEL_DRAFT);

        public static Set<String> getForcedIncludedLabels() {
            return FORCED_INCLUDED_LABELS;
        }

        private static final Set<String> FORCED_INCLUDED_OR_PARTIAL_LABELS =
                Sets.newHashSet(LABEL_INBOX);

        public static Set<String> getForcedIncludedOrPartialLabels() {
            return FORCED_INCLUDED_OR_PARTIAL_LABELS;
        }

        private static final Set<String> FORCED_UNSYNCED_LABELS =
                Sets.newHashSet(LABEL_ALL, LABEL_CHAT, LABEL_SPAM, LABEL_TRASH);

        public static Set<String> getForcedUnsyncedLabels() {
            return FORCED_UNSYNCED_LABELS;
        }

        /**
         * Returns the number of conversation with a given label.
         * @deprecated
         */
        public int getNumConversations(String label) {
            return getNumConversations(getLabelId(label));
        }

        /** Returns the number of conversation with a given label. */
        public int getNumConversations(long labelId) {
            return getLabelIdValues(labelId).getAsInteger(LabelColumns.NUM_CONVERSATIONS);
        }

        /**
         * Returns the number of unread conversation with a given label.
         * @deprecated
         */
        public int getNumUnreadConversations(String label) {
            return getNumUnreadConversations(getLabelId(label));
        }

        /** Returns the number of unread conversation with a given label. */
        public int getNumUnreadConversations(long labelId) {
            return getLabelIdValues(labelId).getAsInteger(LabelColumns.NUM_UNREAD_CONVERSATIONS);
        }

        /**
         * @return the canonical name for a label
         */
        public String getCanonicalName(long labelId) {
            return getLabelIdValues(labelId).getAsString(LabelColumns.CANONICAL_NAME);
        }

        /**
         * @return the human name for a label
         */
        public String getName(long labelId) {
            return getLabelIdValues(labelId).getAsString(LabelColumns.NAME);
        }

        /**
         * @return whether a given label is known
         */
        public boolean hasLabel(long labelId) {
            return mQueryMap.getRows().containsKey(Long.toString(labelId));
        }

        /**
         * @return returns the id of a label given the canonical name
         * @deprecated this is only needed because most of the UI uses label names instead of ids
         */
        public long getLabelId(String canonicalName) {
            if (mCanonicalNameToId.containsKey(canonicalName)) {
                return mCanonicalNameToId.get(canonicalName);
            } else {
                throw new IllegalArgumentException("Unknown canonical name: " + canonicalName);
            }
        }

        private ContentValues getLabelIdValues(long labelId) {
            final ContentValues values = mQueryMap.getValues(Long.toString(labelId));
            if (values != null) {
                return values;
            } else {
                return EMPTY_CONTENT_VALUES;
            }
        }

        /** Force the map to requery. This should not be necessary outside tests. */
        public void requery() {
            mQueryMap.requery();
        }

        public void close() {
            mQueryMap.close();
        }
    }

    private Map<String, Gmail.LabelMap> mLabelMaps = Maps.newHashMap();

    public LabelMap getLabelMap(String account) {
        Gmail.LabelMap labelMap = mLabelMaps.get(account);
        if (labelMap == null) {
            labelMap = new Gmail.LabelMap(mContentResolver, account, true /* keepUpdated */);
            mLabelMaps.put(account, labelMap);
        }
        return labelMap;
    }

    public enum PersonalLevel {
        NOT_TO_ME(0),
        TO_ME_AND_OTHERS(1),
        ONLY_TO_ME(2);

        private int mLevel;

        PersonalLevel(int level) {
            mLevel = level;
        }

        public int toInt() {
            return mLevel;
        }

        public static PersonalLevel fromInt(int level) {
            switch (level) {
                case 0: return NOT_TO_ME;
                case 1: return TO_ME_AND_OTHERS;
                case 2: return ONLY_TO_ME;
                default:
                    throw new IllegalArgumentException(
                            level + " is not a personal level");
            }
        }
    }

    /**
     * Indicates a version of an attachment.
     */
    public enum AttachmentRendition {
        /**
         * The full version of an attachment if it can be handled on the device, otherwise the
         * preview.
         */
        BEST,

        /** A smaller or simpler version of the attachment, such as a scaled-down image or an HTML
         * version of a document. Not always available.
         */
        SIMPLE,
    }

    /**
     * The columns that can be requested when querying an attachment's download URI. See
     * getAttachmentDownloadUri.
     */
    public static final class AttachmentColumns implements BaseColumns {

        /** Contains a STATUS value from {@link android.provider.Downloads} */
        public static final String STATUS = "status";

        /**
         * The name of the file to open (with ContentProvider.open). If this is empty then continue
         * to use the attachment's URI.
         *
         * TODO: I'm not sure that we need this. See the note in CL 66853-p9.
         */
        public static final String FILENAME = "filename";
    }

    /**
     * We track where an attachment came from so that we know how to download it and include it
     * in new messages.
     */
    public enum AttachmentOrigin {
        /** Extras are "<conversationId>-<messageId>-<partId>". */
        SERVER_ATTACHMENT,
        /** Extras are "<path>". */
        LOCAL_FILE;

        private static final String SERVER_EXTRAS_SEPARATOR = "_";

        public static String serverExtras(
                long conversationId, long messageId, String partId) {
            return conversationId + SERVER_EXTRAS_SEPARATOR
                    + messageId + SERVER_EXTRAS_SEPARATOR + partId;
        }

        /**
         * @param extras extras as returned by serverExtras
         * @return an array of conversationId, messageId, partId (all as strings)
         */
        public static String[] splitServerExtras(String extras) {
            return TextUtils.split(extras, SERVER_EXTRAS_SEPARATOR);
        }

        public static String localFileExtras(Uri path) {
            return path.toString();
        }
    }

    public static final class Attachment {
        /** Identifies the attachment uniquely when combined wih a message id.*/
        public String partId;

        /** The intended filename of the attachment.*/
        public String name;

        /** The native content type.*/
        public String contentType;

        /** The size of the attachment in its native form.*/
        public int size;

        /**
         * The content type of the simple version of the attachment. Blank if no simple version is
         * available.
         */
        public String simpleContentType;

        public AttachmentOrigin origin;

        public String originExtras;

        public String toJoinedString() {
            return TextUtils.join(
                "|", Lists.newArrayList(partId == null ? "" : partId,
                                        name.replace("|", ""), contentType,
                                        size, simpleContentType,
                                        origin.toString(), originExtras));
        }

        public static Attachment parseJoinedString(String joinedString) {
            String[] fragments = TextUtils.split(joinedString, "\\|");
            int i = 0;
            Attachment attachment = new Attachment();
            attachment.partId = fragments[i++];
            if (TextUtils.isEmpty(attachment.partId)) {
                attachment.partId = null;
            }
            attachment.name = fragments[i++];
            attachment.contentType = fragments[i++];
            attachment.size = Integer.parseInt(fragments[i++]);
            attachment.simpleContentType = fragments[i++];
            attachment.origin = AttachmentOrigin.valueOf(fragments[i++]);
            attachment.originExtras = fragments[i++];
            return attachment;
        }
    }

    /**
     * Any given attachment can come in two different renditions (see
     * {@link android.provider.Gmail.AttachmentRendition}) and can be saved to the sd card or to a
     * cache. The gmail provider automatically syncs some attachments to the cache. Other
     * attachments can be downloaded on demand. Attachments in the cache will be purged as needed to
     * save space. Attachments on the SD card must be managed by the user or other software.
     *
     * @param account which account to use
     * @param messageId the id of the mesage with the attachment
     * @param attachment the attachment
     * @param rendition the desired rendition
     * @param saveToSd whether the attachment should be saved to (or loaded from) the sd card or
     * @return the URI to ask the content provider to open in order to open an attachment.
     */
    public static Uri getAttachmentUri(
            String account, long messageId, Attachment attachment,
            AttachmentRendition rendition, boolean saveToSd) {
        if (TextUtils.isEmpty(account)) {
            throw new IllegalArgumentException("account is empty");
        }
        if (attachment.origin == AttachmentOrigin.LOCAL_FILE) {
            return Uri.parse(attachment.originExtras);
        } else {
            return Uri.parse(
                    AUTHORITY_PLUS_MESSAGES).buildUpon()
                    .appendPath(account).appendPath(Long.toString(messageId))
                    .appendPath("attachments").appendPath(attachment.partId)
                    .appendPath(rendition.toString())
                    .appendPath(Boolean.toString(saveToSd))
                    .build();
        }
    }

    /**
     * Return the URI to query in order to find out whether an attachment is downloaded.
     *
     * <p>Querying this will also start a download if necessary. The cursor returned by querying
     * this URI can contain the columns in {@link android.provider.Gmail.AttachmentColumns}.
     *
     * <p>Deleting this URI will cancel the download if it was not started automatically by the
     * provider. It will also remove bookkeeping for saveToSd downloads.
     *
     * @param attachmentUri the attachment URI as returned by getAttachmentUri. The URI's authority
     *   Gmail.AUTHORITY. If it is not then you should open the file directly.
     */
    public static Uri getAttachmentDownloadUri(Uri attachmentUri) {
        if (!"content".equals(attachmentUri.getScheme())) {
            throw new IllegalArgumentException("Uri's scheme must be 'content': " + attachmentUri);
        }
        return attachmentUri.buildUpon().appendPath("download").build();
    }

    public enum CursorStatus {
        LOADED,
        LOADING,
        ERROR, // A network error occurred.
    }

    /**
     * A cursor over messages.
     */
    public static final class MessageCursor extends MailCursor {

        private LabelMap mLabelMap;

        private ContentResolver mContentResolver;

        /**
         * Only valid if mCursor == null, in which case we are inserting a new
         * message.
         */
        long mInReplyToLocalMessageId;
        boolean mPreserveAttachments;

        private int mIdIndex;
        private int mConversationIdIndex;
        private int mSubjectIndex;
        private int mSnippetIndex;
        private int mFromIndex;
        private int mToIndex;
        private int mCcIndex;
        private int mBccIndex;
        private int mReplyToIndex;
        private int mDateSentMsIndex;
        private int mDateReceivedMsIndex;
        private int mListInfoIndex;
        private int mPersonalLevelIndex;
        private int mBodyIndex;
        private int mBodyEmbedsExternalResourcesIndex;
        private int mLabelIdsIndex;
        private int mJoinedAttachmentInfosIndex;
        private int mErrorIndex;

        private TextUtils.StringSplitter mLabelIdsSplitter = newMessageLabelIdsSplitter();

        public MessageCursor(Gmail gmail, ContentResolver cr, String account, Cursor cursor) {
            super(account, cursor);
            mLabelMap = gmail.getLabelMap(account);
            if (cursor == null) {
                throw new IllegalArgumentException(
                        "null cursor passed to MessageCursor()");
            }

            mContentResolver = cr;

            mIdIndex = mCursor.getColumnIndexOrThrow(MessageColumns.ID);
            mConversationIdIndex =
                    mCursor.getColumnIndexOrThrow(MessageColumns.CONVERSATION_ID);
            mSubjectIndex = mCursor.getColumnIndexOrThrow(MessageColumns.SUBJECT);
            mSnippetIndex = mCursor.getColumnIndexOrThrow(MessageColumns.SNIPPET);
            mFromIndex = mCursor.getColumnIndexOrThrow(MessageColumns.FROM);
            mToIndex = mCursor.getColumnIndexOrThrow(MessageColumns.TO);
            mCcIndex = mCursor.getColumnIndexOrThrow(MessageColumns.CC);
            mBccIndex = mCursor.getColumnIndexOrThrow(MessageColumns.BCC);
            mReplyToIndex = mCursor.getColumnIndexOrThrow(MessageColumns.REPLY_TO);
            mDateSentMsIndex =
                    mCursor.getColumnIndexOrThrow(MessageColumns.DATE_SENT_MS);
            mDateReceivedMsIndex =
                    mCursor.getColumnIndexOrThrow(MessageColumns.DATE_RECEIVED_MS);
            mListInfoIndex = mCursor.getColumnIndexOrThrow(MessageColumns.LIST_INFO);
            mPersonalLevelIndex =
                    mCursor.getColumnIndexOrThrow(MessageColumns.PERSONAL_LEVEL);
            mBodyIndex = mCursor.getColumnIndexOrThrow(MessageColumns.BODY);
            mBodyEmbedsExternalResourcesIndex =
                    mCursor.getColumnIndexOrThrow(MessageColumns.EMBEDS_EXTERNAL_RESOURCES);
            mLabelIdsIndex = mCursor.getColumnIndexOrThrow(MessageColumns.LABEL_IDS);
            mJoinedAttachmentInfosIndex =
                    mCursor.getColumnIndexOrThrow(MessageColumns.JOINED_ATTACHMENT_INFOS);
            mErrorIndex = mCursor.getColumnIndexOrThrow(MessageColumns.ERROR);

            mInReplyToLocalMessageId = 0;
            mPreserveAttachments = false;
        }

        protected MessageCursor(ContentResolver cr, String account, long inReplyToMessageId,
                boolean preserveAttachments) {
            super(account, null);
            mContentResolver = cr;
            mInReplyToLocalMessageId = inReplyToMessageId;
            mPreserveAttachments = preserveAttachments;
        }

        @Override
        protected void onCursorPositionChanged() {
            super.onCursorPositionChanged();
        }

        public CursorStatus getStatus() {
            Bundle extras = mCursor.getExtras();
            String stringStatus = extras.getString(EXTRA_STATUS);
            return CursorStatus.valueOf(stringStatus);
        }

        /** Retry a network request after errors. */
        public void retry() {
            Bundle input = new Bundle();
            input.putString(RESPOND_INPUT_COMMAND, COMMAND_RETRY);
            Bundle output = mCursor.respond(input);
            String response = output.getString(RESPOND_OUTPUT_COMMAND_RESPONSE);
            assert COMMAND_RESPONSE_OK.equals(response);
        }

        /**
         * Gets the message id of the current message. Note that this is an
         * immutable local message (not, for example, GMail's message id, which
         * is immutable).
         *
         * @return the message's id
         */
        public long getMessageId() {
            checkCursor();
            return mCursor.getLong(mIdIndex);
        }

        /**
         * Gets the message's conversation id. This must be immutable. (For
         * example, with GMail this should be the original conversation id
         * rather than the default notion of converation id.)
         *
         * @return the message's conversation id
         */
        public long getConversationId() {
            checkCursor();
            return mCursor.getLong(mConversationIdIndex);
        }

        /**
         * Gets the message's subject.
         *
         * @return the message's subject
         */
        public String getSubject() {
            return getStringInColumn(mSubjectIndex);
        }

        /**
         * Gets the message's snippet (the short piece of the body). The snippet
         * is generated from the body and cannot be set directly.
         *
         * @return the message's snippet
         */
        public String getSnippet() {
            return getStringInColumn(mSnippetIndex);
        }

        /**
         * Gets the message's from address.
         *
         * @return the message's from address
         */
        public String getFromAddress() {
            return getStringInColumn(mFromIndex);
        }

        /**
         * Returns the addresses for the key, if it has been updated, or index otherwise.
         */
        private String[] getAddresses(String key, int index) {
            ContentValues updated = getUpdateValues();
            String addresses;
            if (updated.containsKey(key)) {
                addresses = (String)getUpdateValues().get(key);
            } else {
                addresses = getStringInColumn(index);
            }

            return TextUtils.split(addresses, EMAIL_SEPARATOR_PATTERN);
        }

        /**
         * Gets the message's to addresses.
         * @return the message's to addresses
         */
        public String[] getToAddresses() {
           return getAddresses(MessageColumns.TO, mToIndex);
        }

        /**
         * Gets the message's cc addresses.
         * @return the message's cc addresses
         */
        public String[] getCcAddresses() {
            return getAddresses(MessageColumns.CC, mCcIndex);
        }

        /**
         * Gets the message's bcc addresses.
         * @return the message's bcc addresses
         */
        public String[] getBccAddresses() {
            return getAddresses(MessageColumns.BCC, mBccIndex);
        }

        /**
         * Gets the message's replyTo address.
         *
         * @return the message's replyTo address
         */
        public String[] getReplyToAddress() {
            return TextUtils.split(getStringInColumn(mReplyToIndex), EMAIL_SEPARATOR_PATTERN);
        }

        public long getDateSentMs() {
            checkCursor();
            return mCursor.getLong(mDateSentMsIndex);
        }

        public long getDateReceivedMs() {
            checkCursor();
            return mCursor.getLong(mDateReceivedMsIndex);
        }

        public String getListInfo() {
            return getStringInColumn(mListInfoIndex);
        }

        public PersonalLevel getPersonalLevel() {
            checkCursor();
            int personalLevelInt = mCursor.getInt(mPersonalLevelIndex);
            return PersonalLevel.fromInt(personalLevelInt);
        }

        /**
         * @deprecated
         */
        public boolean getExpanded() {
            return true;
        }

        /**
         * Gets the message's body.
         *
         * @return the message's body
         */
        public String getBody() {
            return getStringInColumn(mBodyIndex);
        }

        /**
         * @return whether the message's body contains embedded references to external resources. In
         * that case the resources should only be displayed if the user explicitly asks for them to
         * be
         */
        public boolean getBodyEmbedsExternalResources() {
            checkCursor();
            return mCursor.getInt(mBodyEmbedsExternalResourcesIndex) != 0;
        }

        /**
         * @return a copy of the set of label ids
         */
        public Set<Long> getLabelIds() {
            String labelNames = mCursor.getString(mLabelIdsIndex);
            mLabelIdsSplitter.setString(labelNames);
            return getLabelIdsFromLabelIdsString(mLabelIdsSplitter);
        }

        /**
         * @return a joined string of labels separated by spaces.
         */
        public String getRawLabelIds() {
            return mCursor.getString(mLabelIdsIndex);
        }

        /**
         * Adds a label to a message (if add is true) or removes it (if add is
         * false).
         *
         * @param label the label to add or remove
         * @param add whether to add or remove the label
         * @throws NonexistentLabelException thrown if the named label does not
         *         exist
         */
        public void addOrRemoveLabel(String label, boolean add) throws NonexistentLabelException {
            addOrRemoveLabelOnMessage(mContentResolver, mAccount, getConversationId(),
                    getMessageId(), label, add);
        }

        public ArrayList<Attachment> getAttachmentInfos() {
            ArrayList<Attachment> attachments = Lists.newArrayList();

            String joinedAttachmentInfos = mCursor.getString(mJoinedAttachmentInfosIndex);
            if (joinedAttachmentInfos != null) {
                for (String joinedAttachmentInfo :
                        TextUtils.split(joinedAttachmentInfos, ATTACHMENT_INFO_SEPARATOR_PATTERN)) {

                    Attachment attachment = Attachment.parseJoinedString(joinedAttachmentInfo);
                    attachments.add(attachment);
                }
            }
            return attachments;
        }

        /**
         * @return the error text for the message. Error text gets set if the server rejects a
         * message that we try to save or send. If there is error text then the message is no longer
         * scheduled to be saved or sent. Calling save() or send() will clear any error as well as
         * scheduling another atempt to save or send the message.
         */
        public String getErrorText() {
            return mCursor.getString(mErrorIndex);
        }
    }

    /**
     * A helper class for creating or updating messags. Use the putXxx methods to provide initial or
     * new values for the message. Then save or send the message. To save or send an existing
     * message without making other changes to it simply provide an emty ContentValues.
     */
    public static class MessageModification {

        /**
         * Sets the message's subject. Only valid for drafts.
         *
         * @param values the ContentValues that will be used to create or update the message
         * @param subject the new subject
         */
        public static void putSubject(ContentValues values, String subject) {
            values.put(MessageColumns.SUBJECT, subject);
        }

        /**
         * Sets the message's to address. Only valid for drafts.
         *
         * @param values the ContentValues that will be used to create or update the message
         * @param toAddresses the new to addresses
         */
        public static void putToAddresses(ContentValues values, String[] toAddresses) {
            values.put(MessageColumns.TO, TextUtils.join(EMAIL_SEPARATOR, toAddresses));
        }

        /**
         * Sets the message's cc address. Only valid for drafts.
         *
         * @param values the ContentValues that will be used to create or update the message
         * @param ccAddresses the new cc addresses
         */
        public static void putCcAddresses(ContentValues values, String[] ccAddresses) {
            values.put(MessageColumns.CC, TextUtils.join(EMAIL_SEPARATOR, ccAddresses));
        }

        /**
         * Sets the message's bcc address. Only valid for drafts.
         *
         * @param values the ContentValues that will be used to create or update the message
         * @param bccAddresses the new bcc addresses
         */
        public static void putBccAddresses(ContentValues values, String[] bccAddresses) {
            values.put(MessageColumns.BCC, TextUtils.join(EMAIL_SEPARATOR, bccAddresses));
        }

        /**
         * Saves a new body for the message. Only valid for drafts.
         *
         * @param values the ContentValues that will be used to create or update the message
         * @param body the new body of the message
         */
        public static void putBody(ContentValues values, String body) {
            values.put(MessageColumns.BODY, body);
        }

        /**
         * Sets the attachments on a message. Only valid for drafts.
         *
         * @param values the ContentValues that will be used to create or update the message
         * @param attachments
         */
        public static void putAttachments(ContentValues values, List<Attachment> attachments) {
            values.put(
                    MessageColumns.JOINED_ATTACHMENT_INFOS, joinedAttachmentsString(attachments));
        }

        /**
         * Create a new message and save it as a draft or send it.
         *
         * @param contentResolver the content resolver to use
         * @param account the account to use
         * @param values the values for the new message
         * @param refMessageId the message that is being replied to or forwarded
         * @param save whether to save or send the message
         * @return the id of the new message
         */
        public static long sendOrSaveNewMessage(
                ContentResolver contentResolver, String account,
                ContentValues values, long refMessageId, boolean save) {
            values.put(MessageColumns.FAKE_SAVE, save);
            values.put(MessageColumns.FAKE_REF_MESSAGE_ID, refMessageId);
            Uri uri = Uri.parse(AUTHORITY_PLUS_MESSAGES + account + "/");
            Uri result = contentResolver.insert(uri, values);
            return ContentUris.parseId(result);
        }

        /**
         * Update an existing draft and save it as a new draft or send it.
         *
         * @param contentResolver the content resolver to use
         * @param account the account to use
         * @param messageId the id of the message to update
         * @param updateValues the values to change. Unspecified fields will not be altered
         * @param save whether to resave the message as a draft or send it
         */
        public static void sendOrSaveExistingMessage(
                ContentResolver contentResolver, String account, long messageId,
                ContentValues updateValues, boolean save) {
            updateValues.put(MessageColumns.FAKE_SAVE, save);
            updateValues.put(MessageColumns.FAKE_REF_MESSAGE_ID, 0);
            Uri uri = Uri.parse(
                    AUTHORITY_PLUS_MESSAGES + account + "/" + messageId);
            contentResolver.update(uri, updateValues, null, null);
        }

        /**
         * The string produced here is parsed by Gmail.MessageCursor#getAttachmentInfos.
         */
        public static String joinedAttachmentsString(List<Gmail.Attachment> attachments) {
            StringBuilder attachmentsSb = new StringBuilder();
            for (Gmail.Attachment attachment : attachments) {
                if (attachmentsSb.length() != 0) {
                    attachmentsSb.append(Gmail.ATTACHMENT_INFO_SEPARATOR);
                }
                attachmentsSb.append(attachment.toJoinedString());
            }
            return attachmentsSb.toString();
        }

    }

    /**
     * A cursor over conversations.
     *
     * "Conversation" refers to the information needed to populate a list of
     * conversations, not all of the messages in a conversation.
     */
    public static final class ConversationCursor extends MailCursor {

        private LabelMap mLabelMap;

        private int mConversationIdIndex;
        private int mSubjectIndex;
        private int mSnippetIndex;
        private int mFromIndex;
        private int mDateIndex;
        private int mPersonalLevelIndex;
        private int mLabelIdsIndex;
        private int mNumMessagesIndex;
        private int mMaxMessageIdIndex;
        private int mHasAttachmentsIndex;
        private int mHasMessagesWithErrorsIndex;
        private int mForceAllUnreadIndex;

        private TextUtils.StringSplitter mLabelIdsSplitter = newConversationLabelIdsSplitter();

        private ConversationCursor(Gmail gmail, String account, Cursor cursor) {
            super(account, cursor);
            mLabelMap = gmail.getLabelMap(account);

            mConversationIdIndex =
                    mCursor.getColumnIndexOrThrow(ConversationColumns.ID);
            mSubjectIndex = mCursor.getColumnIndexOrThrow(ConversationColumns.SUBJECT);
            mSnippetIndex = mCursor.getColumnIndexOrThrow(ConversationColumns.SNIPPET);
            mFromIndex = mCursor.getColumnIndexOrThrow(ConversationColumns.FROM);
            mDateIndex = mCursor.getColumnIndexOrThrow(ConversationColumns.DATE);
            mPersonalLevelIndex =
                    mCursor.getColumnIndexOrThrow(ConversationColumns.PERSONAL_LEVEL);
            mLabelIdsIndex =
                    mCursor.getColumnIndexOrThrow(ConversationColumns.LABEL_IDS);
            mNumMessagesIndex = mCursor.getColumnIndexOrThrow(ConversationColumns.NUM_MESSAGES);
            mMaxMessageIdIndex = mCursor.getColumnIndexOrThrow(ConversationColumns.MAX_MESSAGE_ID);
            mHasAttachmentsIndex =
                    mCursor.getColumnIndexOrThrow(ConversationColumns.HAS_ATTACHMENTS);
            mHasMessagesWithErrorsIndex =
                    mCursor.getColumnIndexOrThrow(ConversationColumns.HAS_MESSAGES_WITH_ERRORS);
            mForceAllUnreadIndex =
                    mCursor.getColumnIndexOrThrow(ConversationColumns.FORCE_ALL_UNREAD);
        }

        @Override
        protected void onCursorPositionChanged() {
            super.onCursorPositionChanged();
        }

        public CursorStatus getStatus() {
            Bundle extras = mCursor.getExtras();
            String stringStatus = extras.getString(EXTRA_STATUS);
            return CursorStatus.valueOf(stringStatus);
        }

        /** Retry a network request after errors. */
        public void retry() {
            Bundle input = new Bundle();
            input.putString(RESPOND_INPUT_COMMAND, COMMAND_RETRY);
            Bundle output = mCursor.respond(input);
            String response = output.getString(RESPOND_OUTPUT_COMMAND_RESPONSE);
            assert COMMAND_RESPONSE_OK.equals(response);
        }

        /**
         * When a conversation cursor is created it becomes the active network cursor, which means
         * that it will fetch results from the network if it needs to in order to show all mail that
         * matches its query. If you later want to requery an older cursor and would like that
         * cursor to be the active cursor you need to call this method before requerying.
         */
        public void becomeActiveNetworkCursor() {
            Bundle input = new Bundle();
            input.putString(RESPOND_INPUT_COMMAND, COMMAND_ACTIVATE);
            Bundle output = mCursor.respond(input);
            String response = output.getString(RESPOND_OUTPUT_COMMAND_RESPONSE);
            assert COMMAND_RESPONSE_OK.equals(response);
        }

        /**
         * Tells the cursor whether its contents are visible to the user. The cursor will
         * automatically broadcast intents to remove any matching new-mail notifications when this
         * cursor's results become visible and, if they are visible, when the cursor is requeried.
         *
         * Note that contents shown in an activity that is resumed but not focused
         * (onWindowFocusChanged/hasWindowFocus) then results shown in that activity do not count
         * as visible. (This happens when the activity is behind the lock screen or a dialog.)
         *
         * @param visible whether the contents of this cursor are visible to the user.
         */
        public void setContentsVisibleToUser(boolean visible) {
            Bundle input = new Bundle();
            input.putString(RESPOND_INPUT_COMMAND, COMMAND_SET_VISIBLE);
            input.putBoolean(SET_VISIBLE_PARAM_VISIBLE, visible);
            Bundle output = mCursor.respond(input);
            String response = output.getString(RESPOND_OUTPUT_COMMAND_RESPONSE);
            assert COMMAND_RESPONSE_OK.equals(response);
        }

        /**
         * Gets the conversation id. This is immutable. (The server calls it the original
         * conversation id.)
         *
         * @return the conversation id
         */
        public long getConversationId() {
            return mCursor.getLong(mConversationIdIndex);
        }

        /**
         * Returns the instructions for building from snippets. Pass this to getFromSnippetHtml
         * in order to actually build the snippets.
         * @return snippet instructions for use by getFromSnippetHtml()
         */
        public String getFromSnippetInstructions() {
            return getStringInColumn(mFromIndex);
        }

        /**
         * Gets the conversation's subject.
         *
         * @return the subject
         */
        public String getSubject() {
            return getStringInColumn(mSubjectIndex);
        }

        /**
         * Gets the conversation's snippet.
         *
         * @return the snippet
         */
        public String getSnippet() {
            return getStringInColumn(mSnippetIndex);
        }

        /**
         * Get's the conversation's personal level.
         *
         * @return the personal level.
         */
        public PersonalLevel getPersonalLevel() {
            int personalLevelInt = mCursor.getInt(mPersonalLevelIndex);
            return PersonalLevel.fromInt(personalLevelInt);
        }

        /**
         * @return a copy of the set of labels. To add or remove labels call
         *         MessageCursor.addOrRemoveLabel on each message in the conversation.
         * @deprecated use getLabelIds
         */
        public Set<String> getLabels() {
            return getLabels(getRawLabelIds(), mLabelMap);
        }

        /**
         * @return a copy of the set of labels. To add or remove labels call
         *         MessageCursor.addOrRemoveLabel on each message in the conversation.
         */
        public Set<Long> getLabelIds() {
            mLabelIdsSplitter.setString(getRawLabelIds());
            return getLabelIdsFromLabelIdsString(mLabelIdsSplitter);
        }

        /**
         * Returns the set of labels using the raw labels from a previous getRawLabels()
         * as input.
         * @return a copy of the set of labels. To add or remove labels call
         * MessageCursor.addOrRemoveLabel on each message in the conversation.
         */
        public Set<String> getLabels(String rawLabelIds, LabelMap labelMap) {
            mLabelIdsSplitter.setString(rawLabelIds);
            return getCanonicalNamesFromLabelIdsString(labelMap, mLabelIdsSplitter);
        }

        /**
         * @return a joined string of labels separated by spaces. Use
         * getLabels(rawLabels) to convert this to a Set of labels.
         */
        public String getRawLabelIds() {
            return mCursor.getString(mLabelIdsIndex);
        }

        /**
         * @return the number of messages in the conversation
         */
        public int getNumMessages() {
            return mCursor.getInt(mNumMessagesIndex);
        }

        /**
         * @return the max message id in the conversation
         */
        public long getMaxServerMessageId() {
            return mCursor.getLong(mMaxMessageIdIndex);
        }

        public long getDateMs() {
            return mCursor.getLong(mDateIndex);
        }

        public boolean hasAttachments() {
            return mCursor.getInt(mHasAttachmentsIndex) != 0;
        }

        public boolean hasMessagesWithErrors() {
            return mCursor.getInt(mHasMessagesWithErrorsIndex) != 0;
        }

        public boolean getForceAllUnread() {
            return !mCursor.isNull(mForceAllUnreadIndex)
                    && mCursor.getInt(mForceAllUnreadIndex) != 0;
        }
    }
}
