/*
 * Copyright (C) 2010 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.contacts.common.list;

import android.content.Context;
import android.content.CursorLoader;
import android.content.res.Resources;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Directory;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.QuickContactBadge;
import android.widget.SectionIndexer;
import android.widget.TextView;

import com.android.contacts.common.ContactPhotoManager;
import com.android.contacts.common.ContactPhotoManager.DefaultImageRequest;
import com.android.contacts.common.ContactsUtils;
import com.android.contacts.common.R;
import com.android.contacts.common.compat.CompatUtils;
import com.android.contacts.common.compat.DirectoryCompat;
import com.android.contacts.common.util.SearchUtil;

import java.util.HashSet;

/**
 * Common base class for various contact-related lists, e.g. contact list, phone number list
 * etc.
 */
public abstract class ContactEntryListAdapter extends IndexerListAdapter {

    private static final String TAG = "ContactEntryListAdapter";

    /**
     * Indicates whether the {@link Directory#LOCAL_INVISIBLE} directory should
     * be included in the search.
     */
    public static final boolean LOCAL_INVISIBLE_DIRECTORY_ENABLED = false;

    private int mDisplayOrder;
    private int mSortOrder;

    private boolean mDisplayPhotos;
    private boolean mCircularPhotos = true;
    private boolean mQuickContactEnabled;
    private boolean mAdjustSelectionBoundsEnabled;

    /**
     * indicates if contact queries include favorites
     */
    private boolean mIncludeFavorites;

    private int mNumberOfFavorites;

    /**
     * The root view of the fragment that this adapter is associated with.
     */
    private View mFragmentRootView;

    private ContactPhotoManager mPhotoLoader;

    private String mQueryString;
    private String mUpperCaseQueryString;
    private boolean mSearchMode;
    private int mDirectorySearchMode;
    private int mDirectoryResultLimit = Integer.MAX_VALUE;

    private boolean mEmptyListEnabled = true;

    private boolean mSelectionVisible;

    private ContactListFilter mFilter;
    private boolean mDarkTheme = false;

    /** Resource used to provide header-text for default filter. */
    private CharSequence mDefaultFilterHeaderText;

    public ContactEntryListAdapter(Context context) {
        super(context);
        setDefaultFilterHeaderText(R.string.local_search_label);
        addPartitions();
    }

    /**
     * @param fragmentRootView Root view of the fragment. This is used to restrict the scope of
     * image loading requests that get cancelled on cursor changes.
     */
    protected void setFragmentRootView(View fragmentRootView) {
        mFragmentRootView = fragmentRootView;
    }

    protected void setDefaultFilterHeaderText(int resourceId) {
        mDefaultFilterHeaderText = getContext().getResources().getText(resourceId);
    }

    @Override
    protected ContactListItemView newView(
            Context context, int partition, Cursor cursor, int position, ViewGroup parent) {
        final ContactListItemView view = new ContactListItemView(context, null);
        view.setIsSectionHeaderEnabled(isSectionHeaderDisplayEnabled());
        view.setAdjustSelectionBoundsEnabled(isAdjustSelectionBoundsEnabled());
        return view;
    }

    @Override
    protected void bindView(View itemView, int partition, Cursor cursor, int position) {
        final ContactListItemView view = (ContactListItemView) itemView;
        view.setIsSectionHeaderEnabled(isSectionHeaderDisplayEnabled());
        bindWorkProfileIcon(view, partition);
    }

    @Override
    protected View createPinnedSectionHeaderView(Context context, ViewGroup parent) {
        return new ContactListPinnedHeaderView(context, null, parent);
    }

    @Override
    protected void setPinnedSectionTitle(View pinnedHeaderView, String title) {
        ((ContactListPinnedHeaderView) pinnedHeaderView).setSectionHeaderTitle(title);
    }

    protected void addPartitions() {
        addPartition(createDefaultDirectoryPartition());
    }

    protected DirectoryPartition createDefaultDirectoryPartition() {
        DirectoryPartition partition = new DirectoryPartition(true, true);
        partition.setDirectoryId(Directory.DEFAULT);
        partition.setDirectoryType(getContext().getString(R.string.contactsList));
        partition.setPriorityDirectory(true);
        partition.setPhotoSupported(true);
        partition.setLabel(mDefaultFilterHeaderText.toString());
        return partition;
    }

    /**
     * Remove all directories after the default directory. This is typically used when contacts
     * list screens are asked to exit the search mode and thus need to remove all remote directory
     * results for the search.
     *
     * This code assumes that the default directory and directories before that should not be
     * deleted (e.g. Join screen has "suggested contacts" directory before the default director,
     * and we should not remove the directory).
     */
    public void removeDirectoriesAfterDefault() {
        final int partitionCount = getPartitionCount();
        for (int i = partitionCount - 1; i >= 0; i--) {
            final Partition partition = getPartition(i);
            if ((partition instanceof DirectoryPartition)
                    && ((DirectoryPartition) partition).getDirectoryId() == Directory.DEFAULT) {
                break;
            } else {
                removePartition(i);
            }
        }
    }

    protected int getPartitionByDirectoryId(long id) {
        int count = getPartitionCount();
        for (int i = 0; i < count; i++) {
            Partition partition = getPartition(i);
            if (partition instanceof DirectoryPartition) {
                if (((DirectoryPartition)partition).getDirectoryId() == id) {
                    return i;
                }
            }
        }
        return -1;
    }

    protected DirectoryPartition getDirectoryById(long id) {
        int count = getPartitionCount();
        for (int i = 0; i < count; i++) {
            Partition partition = getPartition(i);
            if (partition instanceof DirectoryPartition) {
                final DirectoryPartition directoryPartition = (DirectoryPartition) partition;
                if (directoryPartition.getDirectoryId() == id) {
                    return directoryPartition;
                }
            }
        }
        return null;
    }

    public abstract String getContactDisplayName(int position);
    public abstract void configureLoader(CursorLoader loader, long directoryId);

    /**
     * Marks all partitions as "loading"
     */
    public void onDataReload() {
        boolean notify = false;
        int count = getPartitionCount();
        for (int i = 0; i < count; i++) {
            Partition partition = getPartition(i);
            if (partition instanceof DirectoryPartition) {
                DirectoryPartition directoryPartition = (DirectoryPartition)partition;
                if (!directoryPartition.isLoading()) {
                    notify = true;
                }
                directoryPartition.setStatus(DirectoryPartition.STATUS_NOT_LOADED);
            }
        }
        if (notify) {
            notifyDataSetChanged();
        }
    }

    @Override
    public void clearPartitions() {
        int count = getPartitionCount();
        for (int i = 0; i < count; i++) {
            Partition partition = getPartition(i);
            if (partition instanceof DirectoryPartition) {
                DirectoryPartition directoryPartition = (DirectoryPartition)partition;
                directoryPartition.setStatus(DirectoryPartition.STATUS_NOT_LOADED);
            }
        }
        super.clearPartitions();
    }

    public boolean isSearchMode() {
        return mSearchMode;
    }

    public void setSearchMode(boolean flag) {
        mSearchMode = flag;
    }

    public String getQueryString() {
        return mQueryString;
    }

    public void setQueryString(String queryString) {
        mQueryString = queryString;
        if (TextUtils.isEmpty(queryString)) {
            mUpperCaseQueryString = null;
        } else {
            mUpperCaseQueryString = SearchUtil
                    .cleanStartAndEndOfSearchQuery(queryString.toUpperCase()) ;
        }
    }

    public String getUpperCaseQueryString() {
        return mUpperCaseQueryString;
    }

    public int getDirectorySearchMode() {
        return mDirectorySearchMode;
    }

    public void setDirectorySearchMode(int mode) {
        mDirectorySearchMode = mode;
    }

    public int getDirectoryResultLimit() {
        return mDirectoryResultLimit;
    }

    public int getDirectoryResultLimit(DirectoryPartition directoryPartition) {
        final int limit = directoryPartition.getResultLimit();
        return limit == DirectoryPartition.RESULT_LIMIT_DEFAULT ? mDirectoryResultLimit : limit;
    }

    public void setDirectoryResultLimit(int limit) {
        this.mDirectoryResultLimit = limit;
    }

    public int getContactNameDisplayOrder() {
        return mDisplayOrder;
    }

    public void setContactNameDisplayOrder(int displayOrder) {
        mDisplayOrder = displayOrder;
    }

    public int getSortOrder() {
        return mSortOrder;
    }

    public void setSortOrder(int sortOrder) {
        mSortOrder = sortOrder;
    }

    public void setPhotoLoader(ContactPhotoManager photoLoader) {
        mPhotoLoader = photoLoader;
    }

    protected ContactPhotoManager getPhotoLoader() {
        return mPhotoLoader;
    }

    public boolean getDisplayPhotos() {
        return mDisplayPhotos;
    }

    public void setDisplayPhotos(boolean displayPhotos) {
        mDisplayPhotos = displayPhotos;
    }

    public boolean getCircularPhotos() {
        return mCircularPhotos;
    }

    public void setCircularPhotos(boolean circularPhotos) {
        mCircularPhotos = circularPhotos;
    }

    public boolean isEmptyListEnabled() {
        return mEmptyListEnabled;
    }

    public void setEmptyListEnabled(boolean flag) {
        mEmptyListEnabled = flag;
    }

    public boolean isSelectionVisible() {
        return mSelectionVisible;
    }

    public void setSelectionVisible(boolean flag) {
        this.mSelectionVisible = flag;
    }

    public boolean isQuickContactEnabled() {
        return mQuickContactEnabled;
    }

    public void setQuickContactEnabled(boolean quickContactEnabled) {
        mQuickContactEnabled = quickContactEnabled;
    }

    public boolean isAdjustSelectionBoundsEnabled() {
        return mAdjustSelectionBoundsEnabled;
    }

    public void setAdjustSelectionBoundsEnabled(boolean enabled) {
        mAdjustSelectionBoundsEnabled = enabled;
    }

    public boolean shouldIncludeFavorites() {
        return mIncludeFavorites;
    }

    public void setIncludeFavorites(boolean includeFavorites) {
        mIncludeFavorites = includeFavorites;
    }

    public void setFavoritesSectionHeader(int numberOfFavorites) {
        if (mIncludeFavorites) {
            mNumberOfFavorites = numberOfFavorites;
            setSectionHeader(numberOfFavorites);
        }
    }

    public int getNumberOfFavorites() {
        return mNumberOfFavorites;
    }

    private void setSectionHeader(int numberOfItems) {
        SectionIndexer indexer = getIndexer();
        if (indexer != null) {
            ((ContactsSectionIndexer) indexer).setFavoritesHeader(numberOfItems);
        }
    }

    public void setDarkTheme(boolean value) {
        mDarkTheme = value;
    }

    /**
     * Updates partitions according to the directory meta-data contained in the supplied
     * cursor.
     */
    public void changeDirectories(Cursor cursor) {
        if (cursor.getCount() == 0) {
            // Directory table must have at least local directory, without which this adapter will
            // enter very weird state.
            Log.e(TAG, "Directory search loader returned an empty cursor, which implies we have " +
                    "no directory entries.", new RuntimeException());
            return;
        }
        HashSet<Long> directoryIds = new HashSet<Long>();

        int idColumnIndex = cursor.getColumnIndex(Directory._ID);
        int directoryTypeColumnIndex = cursor.getColumnIndex(DirectoryListLoader.DIRECTORY_TYPE);
        int displayNameColumnIndex = cursor.getColumnIndex(Directory.DISPLAY_NAME);
        int photoSupportColumnIndex = cursor.getColumnIndex(Directory.PHOTO_SUPPORT);

        // TODO preserve the order of partition to match those of the cursor
        // Phase I: add new directories
        cursor.moveToPosition(-1);
        while (cursor.moveToNext()) {
            long id = cursor.getLong(idColumnIndex);
            directoryIds.add(id);
            if (getPartitionByDirectoryId(id) == -1) {
                DirectoryPartition partition = new DirectoryPartition(false, true);
                partition.setDirectoryId(id);
                if (DirectoryCompat.isRemoteDirectoryId(id)) {
                    if (DirectoryCompat.isEnterpriseDirectoryId(id)) {
                        partition.setLabel(mContext.getString(R.string.directory_search_label_work));
                    } else {
                        partition.setLabel(mContext.getString(R.string.directory_search_label));
                    }
                } else {
                    if (DirectoryCompat.isEnterpriseDirectoryId(id)) {
                        partition.setLabel(mContext.getString(R.string.list_filter_phones_work));
                    } else {
                        partition.setLabel(mDefaultFilterHeaderText.toString());
                    }
                }
                partition.setDirectoryType(cursor.getString(directoryTypeColumnIndex));
                partition.setDisplayName(cursor.getString(displayNameColumnIndex));
                int photoSupport = cursor.getInt(photoSupportColumnIndex);
                partition.setPhotoSupported(photoSupport == Directory.PHOTO_SUPPORT_THUMBNAIL_ONLY
                        || photoSupport == Directory.PHOTO_SUPPORT_FULL);
                addPartition(partition);
            }
        }

        // Phase II: remove deleted directories
        int count = getPartitionCount();
        for (int i = count; --i >= 0; ) {
            Partition partition = getPartition(i);
            if (partition instanceof DirectoryPartition) {
                long id = ((DirectoryPartition)partition).getDirectoryId();
                if (!directoryIds.contains(id)) {
                    removePartition(i);
                }
            }
        }

        invalidate();
        notifyDataSetChanged();
    }

    @Override
    public void changeCursor(int partitionIndex, Cursor cursor) {
        if (partitionIndex >= getPartitionCount()) {
            // There is no partition for this data
            return;
        }

        Partition partition = getPartition(partitionIndex);
        if (partition instanceof DirectoryPartition) {
            ((DirectoryPartition)partition).setStatus(DirectoryPartition.STATUS_LOADED);
        }

        if (mDisplayPhotos && mPhotoLoader != null && isPhotoSupported(partitionIndex)) {
            mPhotoLoader.refreshCache();
        }

        super.changeCursor(partitionIndex, cursor);

        if (isSectionHeaderDisplayEnabled() && partitionIndex == getIndexedPartition()) {
            updateIndexer(cursor);
        }

        // When the cursor changes, cancel any pending asynchronous photo loads.
        mPhotoLoader.cancelPendingRequests(mFragmentRootView);
    }

    public void changeCursor(Cursor cursor) {
        changeCursor(0, cursor);
    }

    /**
     * Updates the indexer, which is used to produce section headers.
     */
    private void updateIndexer(Cursor cursor) {
        if (cursor == null || cursor.isClosed()) {
            setIndexer(null);
            return;
        }

        Bundle bundle = cursor.getExtras();
        if (bundle.containsKey(Contacts.EXTRA_ADDRESS_BOOK_INDEX_TITLES) &&
                bundle.containsKey(Contacts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS)) {
            String sections[] =
                    bundle.getStringArray(Contacts.EXTRA_ADDRESS_BOOK_INDEX_TITLES);
            int counts[] = bundle.getIntArray(
                    Contacts.EXTRA_ADDRESS_BOOK_INDEX_COUNTS);

            if (getExtraStartingSection()) {
                // Insert an additional unnamed section at the top of the list.
                String allSections[] = new String[sections.length + 1];
                int allCounts[] = new int[counts.length + 1];
                for (int i = 0; i < sections.length; i++) {
                    allSections[i + 1] = sections[i];
                    allCounts[i + 1] = counts[i];
                }
                allCounts[0] = 1;
                allSections[0] = "";
                setIndexer(new ContactsSectionIndexer(allSections, allCounts));
            } else {
                setIndexer(new ContactsSectionIndexer(sections, counts));
            }
        } else {
            setIndexer(null);
        }
    }

    protected boolean getExtraStartingSection() {
        return false;
    }

    @Override
    public int getViewTypeCount() {
        // We need a separate view type for each item type, plus another one for
        // each type with header, plus one for "other".
        return getItemViewTypeCount() * 2 + 1;
    }

    @Override
    public int getItemViewType(int partitionIndex, int position) {
        int type = super.getItemViewType(partitionIndex, position);
        if (isSectionHeaderDisplayEnabled() && partitionIndex == getIndexedPartition()) {
            Placement placement = getItemPlacementInSection(position);
            return placement.firstInSection ? type : getItemViewTypeCount() + type;
        } else {
            return type;
        }
    }

    @Override
    public boolean isEmpty() {
        // TODO
//        if (contactsListActivity.mProviderStatus != ProviderStatus.STATUS_NORMAL) {
//            return true;
//        }

        if (!mEmptyListEnabled) {
            return false;
        } else if (isSearchMode()) {
            return TextUtils.isEmpty(getQueryString());
        } else {
            return super.isEmpty();
        }
    }

    public boolean isLoading() {
        int count = getPartitionCount();
        for (int i = 0; i < count; i++) {
            Partition partition = getPartition(i);
            if (partition instanceof DirectoryPartition
                    && ((DirectoryPartition) partition).isLoading()) {
                return true;
            }
        }
        return false;
    }

    public boolean areAllPartitionsEmpty() {
        int count = getPartitionCount();
        for (int i = 0; i < count; i++) {
            if (!isPartitionEmpty(i)) {
                return false;
            }
        }
        return true;
    }

    /**
     * Changes visibility parameters for the default directory partition.
     */
    public void configureDefaultPartition(boolean showIfEmpty, boolean hasHeader) {
        int defaultPartitionIndex = -1;
        int count = getPartitionCount();
        for (int i = 0; i < count; i++) {
            Partition partition = getPartition(i);
            if (partition instanceof DirectoryPartition &&
                    ((DirectoryPartition)partition).getDirectoryId() == Directory.DEFAULT) {
                defaultPartitionIndex = i;
                break;
            }
        }
        if (defaultPartitionIndex != -1) {
            setShowIfEmpty(defaultPartitionIndex, showIfEmpty);
            setHasHeader(defaultPartitionIndex, hasHeader);
        }
    }

    @Override
    protected View newHeaderView(Context context, int partition, Cursor cursor,
            ViewGroup parent) {
        LayoutInflater inflater = LayoutInflater.from(context);
        View view = inflater.inflate(R.layout.directory_header, parent, false);
        if (!getPinnedPartitionHeadersEnabled()) {
            // If the headers are unpinned, there is no need for their background
            // color to be non-transparent. Setting this transparent reduces maintenance for
            // non-pinned headers. We don't need to bother synchronizing the activity's
            // background color with the header background color.
            view.setBackground(null);
        }
        return view;
    }

    protected void bindWorkProfileIcon(final ContactListItemView view, int partitionId) {
        final Partition partition = getPartition(partitionId);
        if (partition instanceof DirectoryPartition) {
            final DirectoryPartition directoryPartition = (DirectoryPartition) partition;
            final long directoryId = directoryPartition.getDirectoryId();
            final long userType = ContactsUtils.determineUserType(directoryId, null);
            view.setWorkProfileIconEnabled(userType == ContactsUtils.USER_TYPE_WORK);
        }
    }

    @Override
    protected void bindHeaderView(View view, int partitionIndex, Cursor cursor) {
        Partition partition = getPartition(partitionIndex);
        if (!(partition instanceof DirectoryPartition)) {
            return;
        }

        DirectoryPartition directoryPartition = (DirectoryPartition)partition;
        long directoryId = directoryPartition.getDirectoryId();
        TextView labelTextView = (TextView)view.findViewById(R.id.label);
        TextView displayNameTextView = (TextView)view.findViewById(R.id.display_name);
        labelTextView.setText(directoryPartition.getLabel());
        if (!DirectoryCompat.isRemoteDirectoryId(directoryId)) {
            displayNameTextView.setText(null);
        } else {
            String directoryName = directoryPartition.getDisplayName();
            String displayName = !TextUtils.isEmpty(directoryName)
                    ? directoryName
                    : directoryPartition.getDirectoryType();
            displayNameTextView.setText(displayName);
        }

        final Resources res = getContext().getResources();
        final int headerPaddingTop = partitionIndex == 1 && getPartition(0).isEmpty()?
                0 : res.getDimensionPixelOffset(R.dimen.directory_header_extra_top_padding);
        // There should be no extra padding at the top of the first directory header
        view.setPaddingRelative(view.getPaddingStart(), headerPaddingTop, view.getPaddingEnd(),
                view.getPaddingBottom());
    }

    // Default implementation simply returns number of rows in the cursor.
    // Broken out into its own routine so can be overridden by child classes
    // for eg number of unique contacts for a phone list.
    protected int getResultCount(Cursor cursor) {
        return cursor == null ? 0 : cursor.getCount();
    }

    // TODO: fix PluralRules to handle zero correctly and use Resources.getQuantityText directly
    public String getQuantityText(int count, int zeroResourceId, int pluralResourceId) {
        if (count == 0) {
            return getContext().getString(zeroResourceId);
        } else {
            String format = getContext().getResources()
                    .getQuantityText(pluralResourceId, count).toString();
            return String.format(format, count);
        }
    }

    public boolean isPhotoSupported(int partitionIndex) {
        Partition partition = getPartition(partitionIndex);
        if (partition instanceof DirectoryPartition) {
            return ((DirectoryPartition) partition).isPhotoSupported();
        }
        return true;
    }

    /**
     * Returns the currently selected filter.
     */
    public ContactListFilter getFilter() {
        return mFilter;
    }

    public void setFilter(ContactListFilter filter) {
        mFilter = filter;
    }

    // TODO: move sharable logic (bindXX() methods) to here with extra arguments

    /**
     * Loads the photo for the quick contact view and assigns the contact uri.
     * @param photoIdColumn Index of the photo id column
     * @param photoUriColumn Index of the photo uri column. Optional: Can be -1
     * @param contactIdColumn Index of the contact id column
     * @param lookUpKeyColumn Index of the lookup key column
     * @param displayNameColumn Index of the display name column
     */
    protected void bindQuickContact(final ContactListItemView view, int partitionIndex,
            Cursor cursor, int photoIdColumn, int photoUriColumn, int contactIdColumn,
            int lookUpKeyColumn, int displayNameColumn) {
        long photoId = 0;
        if (!cursor.isNull(photoIdColumn)) {
            photoId = cursor.getLong(photoIdColumn);
        }

        QuickContactBadge quickContact = view.getQuickContact();
        quickContact.assignContactUri(
                getContactUri(partitionIndex, cursor, contactIdColumn, lookUpKeyColumn));
        if (CompatUtils.hasPrioritizedMimeType()) {
            // The Contacts app never uses the QuickContactBadge. Therefore, it is safe to assume
            // that only Dialer will use this QuickContact badge. This means prioritizing the phone
            // mimetype here is reasonable.
            quickContact.setPrioritizedMimeType(Phone.CONTENT_ITEM_TYPE);
        }

        if (photoId != 0 || photoUriColumn == -1) {
            getPhotoLoader().loadThumbnail(quickContact, photoId, mDarkTheme, mCircularPhotos,
                    null);
        } else {
            final String photoUriString = cursor.getString(photoUriColumn);
            final Uri photoUri = photoUriString == null ? null : Uri.parse(photoUriString);
            DefaultImageRequest request = null;
            if (photoUri == null) {
                request = getDefaultImageRequestFromCursor(cursor, displayNameColumn,
                        lookUpKeyColumn);
            }
            getPhotoLoader().loadPhoto(quickContact, photoUri, -1, mDarkTheme, mCircularPhotos,
                    request);
        }

    }

    @Override
    public boolean hasStableIds() {
        // Whenever bindViewId() is called, the values passed into setId() are stable or
        // stable-ish. For example, when one contact is modified we don't expect a second
        // contact's Contact._ID values to change.
        return true;
    }

    protected void bindViewId(final ContactListItemView view, Cursor cursor, int idColumn) {
        // Set a semi-stable id, so that talkback won't get confused when the list gets
        // refreshed. There is little harm in inserting the same ID twice.
        long contactId = cursor.getLong(idColumn);
        view.setId((int) (contactId % Integer.MAX_VALUE));

    }

    protected Uri getContactUri(int partitionIndex, Cursor cursor,
            int contactIdColumn, int lookUpKeyColumn) {
        long contactId = cursor.getLong(contactIdColumn);
        String lookupKey = cursor.getString(lookUpKeyColumn);
        long directoryId = ((DirectoryPartition)getPartition(partitionIndex)).getDirectoryId();
        Uri uri = Contacts.getLookupUri(contactId, lookupKey);
        if (uri != null && directoryId != Directory.DEFAULT) {
            uri = uri.buildUpon().appendQueryParameter(
                    ContactsContract.DIRECTORY_PARAM_KEY, String.valueOf(directoryId)).build();
        }
        return uri;
    }

    /**
     * Retrieves the lookup key and display name from a cursor, and returns a
     * {@link DefaultImageRequest} containing these contact details
     *
     * @param cursor Contacts cursor positioned at the current row to retrieve contact details for
     * @param displayNameColumn Column index of the display name
     * @param lookupKeyColumn Column index of the lookup key
     * @return {@link DefaultImageRequest} with the displayName and identifier fields set to the
     * display name and lookup key of the contact.
     */
    public DefaultImageRequest getDefaultImageRequestFromCursor(Cursor cursor,
            int displayNameColumn, int lookupKeyColumn) {
        final String displayName = cursor.getString(displayNameColumn);
        final String lookupKey = cursor.getString(lookupKeyColumn);
        return new DefaultImageRequest(displayName, lookupKey, mCircularPhotos);
    }
}
