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

package com.android.messaging.datamodel;

import android.content.ContentValues;
import android.database.ContentObserver;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.graphics.Color;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.support.v4.util.ArrayMap;
import android.telephony.SubscriptionInfo;
import android.text.TextUtils;

import com.android.messaging.Factory;
import com.android.messaging.datamodel.DatabaseHelper.ConversationColumns;
import com.android.messaging.datamodel.DatabaseHelper.ConversationParticipantsColumns;
import com.android.messaging.datamodel.DatabaseHelper.ParticipantColumns;
import com.android.messaging.datamodel.data.ParticipantData;
import com.android.messaging.datamodel.data.ParticipantData.ParticipantsQuery;
import com.android.messaging.ui.UIIntents;
import com.android.messaging.util.Assert;
import com.android.messaging.util.ContactUtil;
import com.android.messaging.util.LogUtil;
import com.android.messaging.util.OsUtil;
import com.android.messaging.util.PhoneUtils;
import com.android.messaging.util.SafeAsyncTask;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Joiner;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * Utility class for refreshing participant information based on matching contact. This updates
 *     1. name, photo_uri, matching contact_id of participants.
 *     2. generated_name of conversations.
 *
 * There are two kinds of participant refreshes,
 *     1. Full refresh, this is triggered at application start or activity resumes after contact
 *        change is detected.
 *     2. Partial refresh, this is triggered when a participant is added to a conversation. This
 *        normally happens during SMS sync.
 */
@VisibleForTesting
public class ParticipantRefresh {
    private static final String TAG = LogUtil.BUGLE_DATAMODEL_TAG;

    /**
     * Refresh all participants including ones that were resolved before.
     */
    public static final int REFRESH_MODE_FULL = 0;

    /**
     * Refresh all unresolved participants.
     */
    public static final int REFRESH_MODE_INCREMENTAL = 1;

    /**
     * Force refresh all self participants.
     */
    public static final int REFRESH_MODE_SELF_ONLY = 2;

    public static class ConversationParticipantsQuery {
        public static final String[] PROJECTION = new String[] {
            ConversationParticipantsColumns._ID,
            ConversationParticipantsColumns.CONVERSATION_ID,
            ConversationParticipantsColumns.PARTICIPANT_ID
        };

        public static final int INDEX_ID                        = 0;
        public static final int INDEX_CONVERSATION_ID           = 1;
        public static final int INDEX_PARTICIPANT_ID            = 2;
    }

    // Track whether observer is initialized or not.
    private static volatile boolean sObserverInitialized = false;
    private static final Object sLock = new Object();
    private static final AtomicBoolean sFullRefreshScheduled = new AtomicBoolean(false);
    private static final Runnable sFullRefreshRunnable = new Runnable() {
        @Override
        public void run() {
            final boolean oldScheduled = sFullRefreshScheduled.getAndSet(false);
            Assert.isTrue(oldScheduled);
            refreshParticipants(REFRESH_MODE_FULL);
        }
    };
    private static final Runnable sSelfOnlyRefreshRunnable = new Runnable() {
        @Override
        public void run() {
            refreshParticipants(REFRESH_MODE_SELF_ONLY);
        }
    };

    /**
     * A customized content resolver to track contact changes.
     */
    public static class ContactContentObserver extends ContentObserver {
        private volatile boolean mContactChanged = false;

        public ContactContentObserver() {
            super(null);
        }

        @Override
        public void onChange(final boolean selfChange) {
            super.onChange(selfChange);
            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
                LogUtil.v(TAG, "Contacts changed");
            }
            mContactChanged = true;
        }

        public boolean getContactChanged() {
            return mContactChanged;
        }

        public void resetContactChanged() {
            mContactChanged = false;
        }

        public void initialize() {
            // TODO: Handle enterprise contacts post M once contacts provider supports it
            Factory.get().getApplicationContext().getContentResolver().registerContentObserver(
                    Phone.CONTENT_URI, true, this);
            mContactChanged = true; // Force a full refresh on initialization.
        }
    }

    /**
     * Refresh participants only if needed, i.e., application start or contact changed.
     */
    public static void refreshParticipantsIfNeeded() {
        if (ParticipantRefresh.getNeedFullRefresh() &&
                sFullRefreshScheduled.compareAndSet(false, true)) {
            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
                LogUtil.v(TAG, "Started full participant refresh");
            }
            SafeAsyncTask.executeOnThreadPool(sFullRefreshRunnable);
        } else if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
            LogUtil.v(TAG, "Skipped full participant refresh");
        }
    }

    /**
     * Refresh self participants on subscription or settings change.
     */
    public static void refreshSelfParticipants() {
        SafeAsyncTask.executeOnThreadPool(sSelfOnlyRefreshRunnable);
    }

    private static boolean getNeedFullRefresh() {
        final ContactContentObserver observer = Factory.get().getContactContentObserver();
        if (observer == null) {
            // If there is no observer (for unittest cases), we don't need to refresh participants.
            return false;
        }

        if (!sObserverInitialized) {
            synchronized (sLock) {
                if (!sObserverInitialized) {
                    observer.initialize();
                    sObserverInitialized = true;
                }
            }
        }

        return observer.getContactChanged();
    }

    private static void resetNeedFullRefresh() {
        final ContactContentObserver observer = Factory.get().getContactContentObserver();
        if (observer != null) {
            observer.resetContactChanged();
        }
    }

    /**
     * This class is totally static. Make constructor to be private so that an instance
     * of this class would not be created by by mistake.
     */
    private ParticipantRefresh() {
    }

    /**
     * Refresh participants in Bugle.
     *
     * @param refreshMode the refresh mode desired. See {@link #REFRESH_MODE_FULL},
     *        {@link #REFRESH_MODE_INCREMENTAL}, and {@link #REFRESH_MODE_SELF_ONLY}
     */
     @VisibleForTesting
     static void refreshParticipants(final int refreshMode) {
        Assert.inRange(refreshMode, REFRESH_MODE_FULL, REFRESH_MODE_SELF_ONLY);
        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
            switch (refreshMode) {
                case REFRESH_MODE_FULL:
                    LogUtil.v(TAG, "Start full participant refresh");
                    break;
                case REFRESH_MODE_INCREMENTAL:
                    LogUtil.v(TAG, "Start partial participant refresh");
                    break;
                case REFRESH_MODE_SELF_ONLY:
                    LogUtil.v(TAG, "Start self participant refresh");
                    break;
            }
        }

        if (!ContactUtil.hasReadContactsPermission() || !OsUtil.hasPhonePermission()) {
            if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
                LogUtil.v(TAG, "Skipping participant referesh because of permissions");
            }
            return;
        }

        if (refreshMode == REFRESH_MODE_FULL) {
            // resetNeedFullRefresh right away so that we will skip duplicated full refresh
            // requests.
            resetNeedFullRefresh();
        }

        if (refreshMode == REFRESH_MODE_FULL || refreshMode == REFRESH_MODE_SELF_ONLY) {
            refreshSelfParticipantList();
        }

        final ArrayList<String> changedParticipants = new ArrayList<String>();

        String selection = null;
        String[] selectionArgs = null;

        if (refreshMode == REFRESH_MODE_INCREMENTAL) {
            // In case of incremental refresh, filter out participants that are already resolved.
            selection = ParticipantColumns.CONTACT_ID + "=?";
            selectionArgs = new String[] {
                    String.valueOf(ParticipantData.PARTICIPANT_CONTACT_ID_NOT_RESOLVED) };
        } else if (refreshMode == REFRESH_MODE_SELF_ONLY) {
            // In case of self-only refresh, filter out non-self participants.
            selection = SELF_PARTICIPANTS_CLAUSE;
            selectionArgs = null;
        }

        final DatabaseWrapper db = DataModel.get().getDatabase();
        Cursor cursor = null;
        boolean selfUpdated = false;
        try {
            cursor = db.query(DatabaseHelper.PARTICIPANTS_TABLE,
                    ParticipantsQuery.PROJECTION, selection, selectionArgs, null, null, null);

            if (cursor != null) {
                while (cursor.moveToNext()) {
                    try {
                        final ParticipantData participantData =
                                ParticipantData.getFromCursor(cursor);
                        if (refreshParticipant(db, participantData)) {
                            if (participantData.isSelf()) {
                                selfUpdated = true;
                            }
                            updateParticipant(db, participantData);
                            final String id = participantData.getId();
                            changedParticipants.add(id);
                        }
                    } catch (final Exception exception) {
                        // Failure to update one participant shouldn't cancel the entire refresh.
                        // Log the failure so we know what's going on and resume the loop.
                        LogUtil.e(LogUtil.BUGLE_DATAMODEL_TAG, "ParticipantRefresh: Failed to " +
                                "update participant", exception);
                    }
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }

        if (LogUtil.isLoggable(TAG, LogUtil.VERBOSE)) {
            LogUtil.v(TAG, "Number of participants refreshed:" + changedParticipants.size());
        }

        // Refresh conversations for participants that are changed.
        if (changedParticipants.size() > 0) {
            BugleDatabaseOperations.refreshConversationsForParticipants(changedParticipants);
        }
        if (selfUpdated) {
            // Boom
            MessagingContentProvider.notifyAllParticipantsChanged();
            MessagingContentProvider.notifyAllMessagesChanged();
        }
    }

    private static final String SELF_PARTICIPANTS_CLAUSE = ParticipantColumns.SUB_ID
            + " NOT IN ( "
            + ParticipantData.OTHER_THAN_SELF_SUB_ID
            + " )";

    private static final Set<Integer> getExistingSubIds() {
        final DatabaseWrapper db = DataModel.get().getDatabase();
        final HashSet<Integer> existingSubIds = new HashSet<Integer>();

        Cursor cursor = null;
        try {
            cursor = db.query(DatabaseHelper.PARTICIPANTS_TABLE,
                    ParticipantsQuery.PROJECTION,
                    SELF_PARTICIPANTS_CLAUSE, null, null, null, null);

            if (cursor != null) {
                while (cursor.moveToNext()) {
                    final int subId = cursor.getInt(ParticipantsQuery.INDEX_SUB_ID);
                    existingSubIds.add(subId);
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return existingSubIds;
    }

    private static final String UPDATE_SELF_PARTICIPANT_SUBSCRIPTION_SQL =
            "UPDATE " + DatabaseHelper.PARTICIPANTS_TABLE + " SET "
            +  ParticipantColumns.SIM_SLOT_ID + " = %d, "
            +  ParticipantColumns.SUBSCRIPTION_COLOR + " = %d, "
            +  ParticipantColumns.SUBSCRIPTION_NAME + " = %s "
            + " WHERE %s";

    static String getUpdateSelfParticipantSubscriptionInfoSql(final int slotId,
            final int subscriptionColor, final String subscriptionName, final String where) {
        return String.format((Locale) null /* construct SQL string without localization */,
                UPDATE_SELF_PARTICIPANT_SUBSCRIPTION_SQL,
                slotId, subscriptionColor, subscriptionName, where);
    }

    /**
     * Ensure that there is a self participant corresponding to every active SIM. Also, ensure
     * that any other older SIM self participants are marked as inactive.
     */
    private static void refreshSelfParticipantList() {
        if (!OsUtil.isAtLeastL_MR1()) {
            return;
        }

        final DatabaseWrapper db = DataModel.get().getDatabase();

        final List<SubscriptionInfo> subInfoRecords =
                PhoneUtils.getDefault().toLMr1().getActiveSubscriptionInfoList();
        final ArrayMap<Integer, SubscriptionInfo> activeSubscriptionIdToRecordMap =
                new ArrayMap<Integer, SubscriptionInfo>();
        db.beginTransaction();
        final Set<Integer> existingSubIds = getExistingSubIds();

        try {
            if (subInfoRecords != null) {
                for (final SubscriptionInfo subInfoRecord : subInfoRecords) {
                    final int subId = subInfoRecord.getSubscriptionId();
                    // If its a new subscription, add it to the database.
                    if (!existingSubIds.contains(subId)) {
                        db.execSQL(DatabaseHelper.getCreateSelfParticipantSql(subId));
                        // Add it to the local set to guard against duplicated entries returned
                        // by subscription manager.
                        existingSubIds.add(subId);
                    }
                    activeSubscriptionIdToRecordMap.put(subId, subInfoRecord);

                    if (subId == PhoneUtils.getDefault().getDefaultSmsSubscriptionId()) {
                        // This is the system default subscription, so update the default self.
                        activeSubscriptionIdToRecordMap.put(ParticipantData.DEFAULT_SELF_SUB_ID,
                                subInfoRecord);
                    }
                }
            }

            // For subscriptions already in the database, refresh ParticipantColumns.SIM_SLOT_ID.
            for (final Integer subId : activeSubscriptionIdToRecordMap.keySet()) {
                final SubscriptionInfo record = activeSubscriptionIdToRecordMap.get(subId);
                final String displayName =
                        DatabaseUtils.sqlEscapeString(record.getDisplayName().toString());
                db.execSQL(getUpdateSelfParticipantSubscriptionInfoSql(record.getSimSlotIndex(),
                        record.getIconTint(), displayName,
                        ParticipantColumns.SUB_ID + " = " + subId));
            }
            db.execSQL(getUpdateSelfParticipantSubscriptionInfoSql(
                    ParticipantData.INVALID_SLOT_ID, Color.TRANSPARENT, "''",
                    ParticipantColumns.SUB_ID + " NOT IN (" +
                    Joiner.on(", ").join(activeSubscriptionIdToRecordMap.keySet()) + ")"));
            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();
        }
        // Fix up conversation self ids by reverting to default self for conversations whose self
        // ids are no longer active.
        refreshConversationSelfIds();
    }

    /**
     * Refresh one participant.
     * @return true if the ParticipantData was changed
     */
    public static boolean refreshParticipant(final DatabaseWrapper db,
            final ParticipantData participantData) {
        boolean updated = false;

        if (participantData.isSelf()) {
            final int selfChange = refreshFromSelfProfile(db, participantData);

            if (selfChange == SELF_PROFILE_EXISTS) {
                // If a self-profile exists, it takes precedence over Contacts data. So we are done.
                return true;
            }

            updated = (selfChange == SELF_PHONE_NUMBER_OR_SUBSCRIPTION_CHANGED);

            // Fall-through and try to update based on Contacts data
        }

        updated |= refreshFromContacts(db, participantData);
        return updated;
    }

    private static final int SELF_PHONE_NUMBER_OR_SUBSCRIPTION_CHANGED = 1;
    private static final int SELF_PROFILE_EXISTS = 2;

    private static int refreshFromSelfProfile(final DatabaseWrapper db,
            final ParticipantData participantData) {
        int changed = 0;
        // Refresh the phone number based on information from telephony
        if (participantData.updatePhoneNumberForSelfIfChanged()) {
            changed = SELF_PHONE_NUMBER_OR_SUBSCRIPTION_CHANGED;
        }

        if (OsUtil.isAtLeastL_MR1()) {
            // Refresh the subscription info based on information from SubscriptionManager.
            final SubscriptionInfo subscriptionInfo =
                    PhoneUtils.get(participantData.getSubId()).toLMr1().getActiveSubscriptionInfo();
            if (participantData.updateSubscriptionInfoForSelfIfChanged(subscriptionInfo)) {
                changed = SELF_PHONE_NUMBER_OR_SUBSCRIPTION_CHANGED;
            }
        }

        // For self participant, try getting name/avatar from self profile in CP2 first.
        // TODO: in case of multi-sim, profile would not be able to be used for
        // different numbers. Need to figure out that.
        Cursor selfCursor = null;
        try {
            selfCursor = ContactUtil.getSelf(db.getContext()).performSynchronousQuery();
            if (selfCursor != null && selfCursor.getCount() > 0) {
                selfCursor.moveToNext();
                final long selfContactId = selfCursor.getLong(ContactUtil.INDEX_CONTACT_ID);
                participantData.setContactId(selfContactId);
                participantData.setFullName(selfCursor.getString(
                        ContactUtil.INDEX_DISPLAY_NAME));
                participantData.setFirstName(
                        ContactUtil.lookupFirstName(db.getContext(), selfContactId));
                participantData.setProfilePhotoUri(selfCursor.getString(
                        ContactUtil.INDEX_PHOTO_URI));
                participantData.setLookupKey(selfCursor.getString(
                        ContactUtil.INDEX_SELF_QUERY_LOOKUP_KEY));
                return SELF_PROFILE_EXISTS;
            }
        } catch (final Exception exception) {
            // It's possible for contact query to fail and we don't want that to crash our app.
            // However, we need to at least log the exception so we know something was wrong.
            LogUtil.e(LogUtil.BUGLE_DATAMODEL_TAG, "Participant refresh: failed to refresh " +
                    "participant. exception=" + exception);
        } finally {
            if (selfCursor != null) {
                selfCursor.close();
            }
        }
        return changed;
    }

    private static boolean refreshFromContacts(final DatabaseWrapper db,
            final ParticipantData participantData) {
        final String normalizedDestination = participantData.getNormalizedDestination();
        final long currentContactId = participantData.getContactId();
        final String currentDisplayName = participantData.getFullName();
        final String currentFirstName = participantData.getFirstName();
        final String currentPhotoUri = participantData.getProfilePhotoUri();
        final String currentContactDestination = participantData.getContactDestination();

        Cursor matchingContactCursor = null;
        long matchingContactId = -1;
        String matchingDisplayName = null;
        String matchingFirstName = null;
        String matchingPhotoUri = null;
        String matchingLookupKey = null;
        String matchingDestination = null;
        boolean updated = false;

        if (TextUtils.isEmpty(normalizedDestination)) {
            // The normalized destination can be "" for the self id if we can't get it from the
            // SIM.  Some contact providers throw an IllegalArgumentException if you lookup "",
            // so we early out.
            return false;
        }

        try {
            matchingContactCursor = ContactUtil.lookupDestination(db.getContext(),
                    normalizedDestination).performSynchronousQuery();
            if (matchingContactCursor == null || matchingContactCursor.getCount() == 0) {
                // If there is no match, mark the participant as contact not found.
                if (currentContactId != ParticipantData.PARTICIPANT_CONTACT_ID_NOT_FOUND) {
                    participantData.setContactId(ParticipantData.PARTICIPANT_CONTACT_ID_NOT_FOUND);
                    participantData.setFullName(null);
                    participantData.setFirstName(null);
                    participantData.setProfilePhotoUri(null);
                    participantData.setLookupKey(null);
                    updated = true;
                }
                return updated;
            }

            while (matchingContactCursor.moveToNext()) {
                final long contactId = matchingContactCursor.getLong(ContactUtil.INDEX_CONTACT_ID);
                // Pick either the first contact or the contact with same id as previous matched
                // contact id.
                if (matchingContactId == -1 || currentContactId == contactId) {
                    matchingContactId = contactId;
                    matchingDisplayName = matchingContactCursor.getString(
                            ContactUtil.INDEX_DISPLAY_NAME);
                    matchingFirstName = ContactUtil.lookupFirstName(db.getContext(), contactId);
                    matchingPhotoUri = matchingContactCursor.getString(
                            ContactUtil.INDEX_PHOTO_URI);
                    matchingLookupKey = matchingContactCursor.getString(
                            ContactUtil.INDEX_LOOKUP_KEY);
                    matchingDestination = matchingContactCursor.getString(
                            ContactUtil.INDEX_PHONE_EMAIL);
                }

                // There is no need to try other contacts if the current contactId was not filled...
                if (currentContactId < 0
                        // or we found the matching contact id
                        || currentContactId == contactId) {
                    break;
                }
            }
        } catch (final Exception exception) {
            // It's possible for contact query to fail and we don't want that to crash our app.
            // However, we need to at least log the exception so we know something was wrong.
            LogUtil.e(LogUtil.BUGLE_DATAMODEL_TAG, "Participant refresh: failed to refresh " +
                    "participant. exception=" + exception);
            return false;
        } finally {
            if (matchingContactCursor != null) {
                matchingContactCursor.close();
            }
        }

        // Update participant only if something changed.
        final boolean isContactIdChanged = (matchingContactId != currentContactId);
        final boolean isDisplayNameChanged =
                !TextUtils.equals(matchingDisplayName, currentDisplayName);
        final boolean isFirstNameChanged = !TextUtils.equals(matchingFirstName, currentFirstName);
        final boolean isPhotoUrlChanged = !TextUtils.equals(matchingPhotoUri, currentPhotoUri);
        final boolean isDestinationChanged = !TextUtils.equals(matchingDestination,
                currentContactDestination);

        if (isContactIdChanged || isDisplayNameChanged || isFirstNameChanged || isPhotoUrlChanged
                || isDestinationChanged) {
            participantData.setContactId(matchingContactId);
            participantData.setFullName(matchingDisplayName);
            participantData.setFirstName(matchingFirstName);
            participantData.setProfilePhotoUri(matchingPhotoUri);
            participantData.setLookupKey(matchingLookupKey);
            participantData.setContactDestination(matchingDestination);
            if (isDestinationChanged) {
                // Update the send destination to the new one entered by user in Contacts.
                participantData.setSendDestination(matchingDestination);
            }
            updated = true;
        }

        return updated;
    }

    /**
     * Update participant with matching contact's contactId, displayName and photoUri.
     */
    private static void updateParticipant(final DatabaseWrapper db,
            final ParticipantData participantData) {
        final ContentValues values = new ContentValues();
        if (participantData.isSelf()) {
            // Self participants can refresh their normalized phone numbers
            values.put(ParticipantColumns.NORMALIZED_DESTINATION,
                    participantData.getNormalizedDestination());
            values.put(ParticipantColumns.DISPLAY_DESTINATION,
                    participantData.getDisplayDestination());
        }
        values.put(ParticipantColumns.CONTACT_ID, participantData.getContactId());
        values.put(ParticipantColumns.LOOKUP_KEY, participantData.getLookupKey());
        values.put(ParticipantColumns.FULL_NAME, participantData.getFullName());
        values.put(ParticipantColumns.FIRST_NAME, participantData.getFirstName());
        values.put(ParticipantColumns.PROFILE_PHOTO_URI, participantData.getProfilePhotoUri());
        values.put(ParticipantColumns.CONTACT_DESTINATION, participantData.getContactDestination());
        values.put(ParticipantColumns.SEND_DESTINATION, participantData.getSendDestination());

        db.beginTransaction();
        try {
            db.update(DatabaseHelper.PARTICIPANTS_TABLE, values, ParticipantColumns._ID + "=?",
                    new String[] { participantData.getId() });
            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();
        }
    }

    /**
     * Get a list of inactive self ids in the participants table.
     */
    private static List<String> getInactiveSelfParticipantIds() {
        final DatabaseWrapper db = DataModel.get().getDatabase();
        final List<String> inactiveSelf = new ArrayList<String>();

        final String selection = ParticipantColumns.SIM_SLOT_ID + "=? AND " +
                SELF_PARTICIPANTS_CLAUSE;
        Cursor cursor = null;
        try {
            cursor = db.query(DatabaseHelper.PARTICIPANTS_TABLE,
                    new String[] { ParticipantColumns._ID },
                    selection, new String[] { String.valueOf(ParticipantData.INVALID_SLOT_ID) },
                    null, null, null);

            if (cursor != null) {
                while (cursor.moveToNext()) {
                    final String participantId = cursor.getString(0);
                    inactiveSelf.add(participantId);
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }

        return inactiveSelf;
    }

    /**
     * Gets a list of conversations with the given self ids.
     */
    private static List<String> getConversationsWithSelfParticipantIds(final List<String> selfIds) {
        final DatabaseWrapper db = DataModel.get().getDatabase();
        final List<String> conversationIds = new ArrayList<String>();

        Cursor cursor = null;
        try {
            final StringBuilder selectionList = new StringBuilder();
            for (int i = 0; i < selfIds.size(); i++) {
                selectionList.append('?');
                if (i < selfIds.size() - 1) {
                    selectionList.append(',');
                }
            }
            final String selection =
                    ConversationColumns.CURRENT_SELF_ID + " IN (" + selectionList + ")";
            cursor = db.query(DatabaseHelper.CONVERSATIONS_TABLE,
                    new String[] { ConversationColumns._ID },
                    selection, selfIds.toArray(new String[0]),
                    null, null, null);

            if (cursor != null) {
                while (cursor.moveToNext()) {
                    final String conversationId = cursor.getString(0);
                    conversationIds.add(conversationId);
                }
            }
        } finally {
            if (cursor != null) {
                cursor.close();
            }
        }
        return conversationIds;
    }

    /**
     * Refresh one conversation's self id.
     */
    private static void updateConversationSelfId(final String conversationId,
            final String selfId) {
        final DatabaseWrapper db = DataModel.get().getDatabase();

        db.beginTransaction();
        try {
            BugleDatabaseOperations.updateConversationSelfIdInTransaction(db, conversationId,
                    selfId);
            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();
        }

        MessagingContentProvider.notifyMessagesChanged(conversationId);
        MessagingContentProvider.notifyConversationMetadataChanged(conversationId);
        UIIntents.get().broadcastConversationSelfIdChange(db.getContext(), conversationId, selfId);
    }

    /**
     * After refreshing the self participant list, find all conversations with inactive self ids,
     * and switch them back to system default.
     */
    private static void refreshConversationSelfIds() {
        final List<String> inactiveSelfs = getInactiveSelfParticipantIds();
        if (inactiveSelfs.size() == 0) {
            return;
        }
        final List<String> conversationsToRefresh =
                getConversationsWithSelfParticipantIds(inactiveSelfs);
        if (conversationsToRefresh.size() == 0) {
            return;
        }
        final DatabaseWrapper db = DataModel.get().getDatabase();
        final ParticipantData defaultSelf =
                BugleDatabaseOperations.getOrCreateSelf(db, ParticipantData.DEFAULT_SELF_SUB_ID);

        if (defaultSelf != null) {
            for (final String conversationId : conversationsToRefresh) {
                updateConversationSelfId(conversationId, defaultSelf.getId());
            }
        }
    }
}
