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

import android.accounts.AccountManager;
import android.content.ContentProvider;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Contacts.Data;
import android.provider.ContactsContract.Directory;
import android.provider.ContactsContract.DisplayNameSources;
import android.provider.ContactsContract.RawContacts;
import android.text.TextUtils;
import android.util.Log;
import android.util.Pair;

import com.android.emailcommon.Configuration;
import com.android.emailcommon.mail.PackedString;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.AccountColumns;
import com.android.emailcommon.service.AccountServiceProxy;
import com.android.emailcommon.utility.Utility;
import com.android.exchange.Eas;
import com.android.exchange.R;
import com.android.exchange.provider.GalResult.GalData;
import com.android.exchange.service.EasService;
import com.android.mail.utils.LogUtils;

import java.text.Collator;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeMap;

/**
 * ExchangeDirectoryProvider provides real-time data from the Exchange server; at the moment, it is
 * used solely to provide GAL (Global Address Lookup) service to email address adapters
 */
public class ExchangeDirectoryProvider extends ContentProvider {
    private static final String TAG = Eas.LOG_TAG;

    public static final String EXCHANGE_GAL_AUTHORITY =
            com.android.exchange.Configuration.EXCHANGE_GAL_AUTHORITY;

    private static final int DEFAULT_CONTACT_ID = 1;

    private static final int DEFAULT_LOOKUP_LIMIT = 20;
    private static final int MAX_LOOKUP_LIMIT = 100;

    private static final int GAL_BASE = 0;
    private static final int GAL_DIRECTORIES = GAL_BASE;
    private static final int GAL_FILTER = GAL_BASE + 1;
    private static final int GAL_CONTACT = GAL_BASE + 2;
    private static final int GAL_CONTACT_WITH_ID = GAL_BASE + 3;
    private static final int GAL_EMAIL_FILTER = GAL_BASE + 4;
    private static final int GAL_PHONE_FILTER = GAL_BASE + 5;

    private static final UriMatcher sURIMatcher = new UriMatcher(UriMatcher.NO_MATCH);
    /*package*/ final HashMap<String, Long> mAccountIdMap = new HashMap<String, Long>();

    static {
        sURIMatcher.addURI(EXCHANGE_GAL_AUTHORITY, "directories", GAL_DIRECTORIES);
        sURIMatcher.addURI(EXCHANGE_GAL_AUTHORITY, "contacts/filter/*", GAL_FILTER);
        sURIMatcher.addURI(EXCHANGE_GAL_AUTHORITY, "contacts/lookup/*/entities", GAL_CONTACT);
        sURIMatcher.addURI(EXCHANGE_GAL_AUTHORITY, "contacts/lookup/*/#/entities",
                GAL_CONTACT_WITH_ID);
        sURIMatcher.addURI(EXCHANGE_GAL_AUTHORITY, "data/emails/filter/*", GAL_EMAIL_FILTER);
        sURIMatcher.addURI(EXCHANGE_GAL_AUTHORITY, "data/phones/filter/*", GAL_PHONE_FILTER);

    }

    @Override
    public boolean onCreate() {
        EmailContent.init(getContext());
        return true;
    }

    static class GalProjection {
        final int size;
        final HashMap<String, Integer> columnMap = new HashMap<String, Integer>();

        GalProjection(String[] projection) {
            size = projection.length;
            for (int i = 0; i < projection.length; i++) {
                columnMap.put(projection[i], i);
            }
        }
    }

    static class GalContactRow {
        private final GalProjection mProjection;
        private Object[] row;
        static long dataId = 1;

        GalContactRow(GalProjection projection, long contactId, String accountName,
                String displayName) {
            this.mProjection = projection;
            row = new Object[projection.size];

            put(Contacts.Entity.CONTACT_ID, contactId);

            // We only have one raw contact per aggregate, so they can have the same ID
            put(Contacts.Entity.RAW_CONTACT_ID, contactId);
            put(Contacts.Entity.DATA_ID, dataId++);

            put(Contacts.DISPLAY_NAME, displayName);

            // TODO alternative display name
            put(Contacts.DISPLAY_NAME_ALTERNATIVE, displayName);

            put(RawContacts.ACCOUNT_TYPE, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE);
            put(RawContacts.ACCOUNT_NAME, accountName);
            put(RawContacts.RAW_CONTACT_IS_READ_ONLY, 1);
            put(Data.IS_READ_ONLY, 1);
        }

        Object[] getRow () {
            return row;
        }

        void put(String columnName, Object value) {
            final Integer integer = mProjection.columnMap.get(columnName);
            if (integer != null) {
                row[integer] = value;
            } else {
                LogUtils.e(TAG, "Unsupported column: " + columnName);
            }
        }

        static void addEmailAddress(MatrixCursor cursor, GalProjection galProjection,
                long contactId, String accountName, String displayName, String address) {
            if (!TextUtils.isEmpty(address)) {
                final GalContactRow r = new GalContactRow(
                        galProjection, contactId, accountName, displayName);
                r.put(Data.MIMETYPE, Email.CONTENT_ITEM_TYPE);
                r.put(Email.TYPE, Email.TYPE_WORK);
                r.put(Email.ADDRESS, address);
                cursor.addRow(r.getRow());
            }
        }

        static void addPhoneRow(MatrixCursor cursor, GalProjection projection, long contactId,
                String accountName, String displayName, int type, String number) {
            if (!TextUtils.isEmpty(number)) {
                final GalContactRow r = new GalContactRow(
                        projection, contactId, accountName, displayName);
                r.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);
                r.put(Phone.TYPE, type);
                r.put(Phone.NUMBER, number);
                cursor.addRow(r.getRow());
            }
        }

        public static void addNameRow(MatrixCursor cursor, GalProjection galProjection,
                long contactId, String accountName, String displayName,
                String firstName, String lastName) {
            final GalContactRow r = new GalContactRow(
                    galProjection, contactId, accountName, displayName);
            r.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);
            r.put(StructuredName.GIVEN_NAME, firstName);
            r.put(StructuredName.FAMILY_NAME, lastName);
            r.put(StructuredName.DISPLAY_NAME, displayName);
            cursor.addRow(r.getRow());
        }
    }

    /**
     * Find the record id of an Account, given its name (email address)
     * @param accountName the name of the account
     * @return the record id of the Account, or -1 if not found
     */
    /*package*/ long getAccountIdByName(Context context, String accountName) {
        Long accountId = mAccountIdMap.get(accountName);
        if (accountId == null) {
            accountId = Utility.getFirstRowLong(context, Account.CONTENT_URI,
                    EmailContent.ID_PROJECTION, AccountColumns.EMAIL_ADDRESS + "=?",
                    new String[] {accountName}, null, EmailContent.ID_PROJECTION_COLUMN , -1L);
            if (accountId != -1) {
                mAccountIdMap.put(accountName, accountId);
            }
        }
        return accountId;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
            String sortOrder) {
        LogUtils.d(TAG, "ExchangeDirectoryProvider: query: %s", uri.toString());
        final int match = sURIMatcher.match(uri);
        final MatrixCursor cursor;
        Object[] row;
        final PackedString ps;
        final String lookupKey;

        switch (match) {
            case GAL_DIRECTORIES: {
                // Assuming that GAL can be used with all exchange accounts
                final android.accounts.Account[] accounts = AccountManager.get(getContext())
                        .getAccountsByType(Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE);
                cursor = new MatrixCursor(projection);
                if (accounts != null) {
                    for (android.accounts.Account account : accounts) {
                        row = new Object[projection.length];

                        for (int i = 0; i < projection.length; i++) {
                            final String column = projection[i];
                            if (column.equals(Directory.ACCOUNT_NAME)) {
                                row[i] = account.name;
                            } else if (column.equals(Directory.ACCOUNT_TYPE)) {
                                row[i] = account.type;
                            } else if (column.equals(Directory.TYPE_RESOURCE_ID)) {
                                final String accountType = Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE;
                                final Bundle bundle = new AccountServiceProxy(getContext())
                                    .getConfigurationData(accountType);
                                // Default to the alternative name, erring on the conservative side
                                int exchangeName = R.string.exchange_name_alternate;
                                if (bundle != null && !bundle.getBoolean(
                                        Configuration.EXCHANGE_CONFIGURATION_USE_ALTERNATE_STRINGS,
                                        true)) {
                                    exchangeName = R.string.exchange_name;
                                }
                                row[i] = exchangeName;
                            } else if (column.equals(Directory.DISPLAY_NAME)) {
                                // If the account name is an email address, extract
                                // the domain name and use it as the directory display name
                                final String accountName = account.name;
                                final int atIndex = accountName.indexOf('@');
                                if (atIndex != -1 && atIndex < accountName.length() - 2) {
                                    final char firstLetter = Character.toUpperCase(
                                            accountName.charAt(atIndex + 1));
                                    row[i] = firstLetter + accountName.substring(atIndex + 2);
                                } else {
                                    row[i] = account.name;
                                }
                            } else if (column.equals(Directory.EXPORT_SUPPORT)) {
                                row[i] = Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY;
                            } else if (column.equals(Directory.SHORTCUT_SUPPORT)) {
                                row[i] = Directory.SHORTCUT_SUPPORT_NONE;
                            }
                        }
                        cursor.addRow(row);
                    }
                }
                return cursor;
            }

            case GAL_FILTER:
            case GAL_PHONE_FILTER:
            case GAL_EMAIL_FILTER: {
                final String filter = uri.getLastPathSegment();
                // We should have at least two characters before doing a GAL search
                if (filter == null || filter.length() < 2) {
                    return null;
                }

                final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME);
                if (accountName == null) {
                    return null;
                }

                // Enforce a limit on the number of lookup responses
                final String limitString = uri.getQueryParameter(ContactsContract.LIMIT_PARAM_KEY);
                int limit = DEFAULT_LOOKUP_LIMIT;
                if (limitString != null) {
                    try {
                        limit = Integer.parseInt(limitString);
                    } catch (NumberFormatException e) {
                        limit = 0;
                    }
                    if (limit <= 0) {
                        throw new IllegalArgumentException("Limit not valid: " + limitString);
                    }
                }

                final long callingId = Binder.clearCallingIdentity();
                try {
                    // Find the account id to pass along to EasSyncService
                    final long accountId = getAccountIdByName(getContext(), accountName);
                    if (accountId == -1) {
                        // The account was deleted?
                        return null;
                    }

                    final boolean isEmail = match == GAL_EMAIL_FILTER;
                    final boolean isPhone = match == GAL_PHONE_FILTER;
                    // For phone filter queries we request more results from the server
                    // than requested by the caller because we omit contacts without
                    // phone numbers, and the server lacks the ability to do this filtering
                    // for us. We then enforce the limit when constructing the cursor
                    // containing the results.
                    int queryLimit = limit;
                    if (isPhone) {
                        queryLimit = 3 * queryLimit;
                    }
                    if (queryLimit > MAX_LOOKUP_LIMIT) {
                        queryLimit = MAX_LOOKUP_LIMIT;
                    }

                    // Get results from the Exchange account
                    final GalResult galResult = EasService.searchGal(getContext(), accountId,
                            filter, queryLimit);
                    if (galResult != null) {
                         return buildGalResultCursor(
                                 projection, galResult, sortOrder, limit, isEmail, isPhone);
                    }
                } finally {
                    Binder.restoreCallingIdentity(callingId);
                }
                break;
            }

            case GAL_CONTACT:
            case GAL_CONTACT_WITH_ID: {
                final String accountName = uri.getQueryParameter(RawContacts.ACCOUNT_NAME);
                if (accountName == null) {
                    return null;
                }

                final GalProjection galProjection = new GalProjection(projection);
                cursor = new MatrixCursor(projection);
                // Handle the decomposition of the key into rows suitable for CP2
                final List<String> pathSegments = uri.getPathSegments();
                lookupKey = pathSegments.get(2);
                final long contactId = (match == GAL_CONTACT_WITH_ID)
                        ? Long.parseLong(pathSegments.get(3))
                        : DEFAULT_CONTACT_ID;
                ps = new PackedString(lookupKey);
                final String displayName = ps.get(GalData.DISPLAY_NAME);
                GalContactRow.addEmailAddress(cursor, galProjection, contactId,
                        accountName, displayName, ps.get(GalData.EMAIL_ADDRESS));
                GalContactRow.addPhoneRow(cursor, galProjection, contactId,
                        displayName, displayName, Phone.TYPE_HOME, ps.get(GalData.HOME_PHONE));
                GalContactRow.addPhoneRow(cursor, galProjection, contactId,
                        displayName, displayName, Phone.TYPE_WORK, ps.get(GalData.WORK_PHONE));
                GalContactRow.addPhoneRow(cursor, galProjection, contactId,
                        displayName, displayName, Phone.TYPE_MOBILE, ps.get(GalData.MOBILE_PHONE));
                GalContactRow.addNameRow(cursor, galProjection, contactId, displayName,
                        ps.get(GalData.FIRST_NAME), ps.get(GalData.LAST_NAME), displayName);
                return cursor;
            }
        }

        return null;
    }

    /*package*/ Cursor buildGalResultCursor(String[] projection, GalResult galResult,
            String sortOrder, int limit, boolean isEmailFilter, boolean isPhoneFilter) {
        int displayNameIndex = -1;
        int displayNameSourceIndex = -1;
        int alternateDisplayNameIndex = -1;
        int emailIndex = -1;
        int emailTypeIndex = -1;
        int phoneNumberIndex = -1;
        int phoneTypeIndex = -1;
        int hasPhoneNumberIndex = -1;
        int idIndex = -1;
        int contactIdIndex = -1;
        int lookupIndex = -1;

        for (int i = 0; i < projection.length; i++) {
            final String column = projection[i];
            if (Contacts.DISPLAY_NAME.equals(column) ||
                    Contacts.DISPLAY_NAME_PRIMARY.equals(column)) {
                displayNameIndex = i;
            } else if (Contacts.DISPLAY_NAME_ALTERNATIVE.equals(column)) {
                alternateDisplayNameIndex = i;
            } else if (Contacts.DISPLAY_NAME_SOURCE.equals(column)) {
                displayNameSourceIndex = i;
            } else if (Contacts.HAS_PHONE_NUMBER.equals(column)) {
                hasPhoneNumberIndex = i;
            } else if (Contacts._ID.equals(column)) {
                idIndex = i;
            } else if (Phone.CONTACT_ID.equals(column)) {
                contactIdIndex = i;
            } else if (Contacts.LOOKUP_KEY.equals(column)) {
                lookupIndex = i;
            } else if (isPhoneFilter) {
                if (Phone.NUMBER.equals(column)) {
                    phoneNumberIndex = i;
                } else if (Phone.TYPE.equals(column)) {
                    phoneTypeIndex = i;
                }
            } else {
                // Cannot support for Email and Phone in same query, so default
                // is to return email addresses.
                if (Email.ADDRESS.equals(column)) {
                    emailIndex = i;
                } else if (Email.TYPE.equals(column)) {
                    emailTypeIndex = i;
                }
            }
        }

        boolean usePrimarySortKey = false;
        boolean useAlternateSortKey = false;
        if (Contacts.SORT_KEY_PRIMARY.equals(sortOrder)) {
            usePrimarySortKey = true;
        } else if (Contacts.SORT_KEY_ALTERNATIVE.equals(sortOrder)) {
            useAlternateSortKey = true;
        } else if (sortOrder != null && sortOrder.length() > 0) {
            Log.w(TAG, "Ignoring unsupported sort order: " + sortOrder);
        }

        final TreeMap<GalSortKey, Object[]> sortedResultsMap =
                new TreeMap<GalSortKey, Object[]>(new NameComparator());

        // id populates the _ID column and is incremented for each row in the
        // result set, so each row has a unique id.
        int id = 1;
        // contactId populates the CONTACT_ID column and is incremented for
        // each contact. For the email and phone filters, there may be more
        // than one row with the same contactId if a given contact has multiple
        // email addresses or multiple phone numbers.
        int contactId = 1;

        final int count = galResult.galData.size();
        for (int i = 0; i < count; i++) {
            final GalData galDataRow = galResult.galData.get(i);

            final List<PhoneInfo> phones = new ArrayList<PhoneInfo>();
            addPhoneInfo(phones, galDataRow.get(GalData.WORK_PHONE), Phone.TYPE_WORK);
            addPhoneInfo(phones, galDataRow.get(GalData.OFFICE), Phone.TYPE_COMPANY_MAIN);
            addPhoneInfo(phones, galDataRow.get(GalData.HOME_PHONE), Phone.TYPE_HOME);
            addPhoneInfo(phones, galDataRow.get(GalData.MOBILE_PHONE), Phone.TYPE_MOBILE);

            // Track whether we added a result for this contact or not, in
            // order to stop once we have maxResult contacts.
            boolean addedContact = false;

            Pair<String, Integer> displayName = getDisplayName(galDataRow, phones);
            if (TextUtils.isEmpty(displayName.first)) {
                // can't use a contact if we can't find a decent name for it.
                continue;
            }
            galDataRow.put(GalData.DISPLAY_NAME, displayName.first);

            final String alternateDisplayName = getAlternateDisplayName(
                    galDataRow, displayName.first);
            final String sortName = usePrimarySortKey ? displayName.first
                : (useAlternateSortKey ? alternateDisplayName : "");
            final Object[] row = new Object[projection.length];
            if (displayNameIndex != -1) {
                row[displayNameIndex] = displayName.first;
            }
            if (displayNameSourceIndex != -1) {
                row[displayNameSourceIndex] = displayName.second;
            }

            if (alternateDisplayNameIndex != -1) {
                row[alternateDisplayNameIndex] = alternateDisplayName;
            }

            if (hasPhoneNumberIndex != -1) {
                if (phones.size() > 0) {
                    row[hasPhoneNumberIndex] = true;
                }
            }

            if (contactIdIndex != -1) {
                row[contactIdIndex] = contactId;
            }

            if (lookupIndex != -1) {
                // We use the packed string as our lookup key; it contains ALL of the gal data
                // We do this because we are not able to provide a stable id to ContactsProvider
                row[lookupIndex] = Uri.encode(galDataRow.toPackedString());
            }

            if (isPhoneFilter) {
                final Set<String> uniqueNumbers = new HashSet<String>();

                for (PhoneInfo phone : phones) {
                    if (!uniqueNumbers.add(phone.mNumber)) {
                        continue;
                    }
                    if (phoneNumberIndex != -1) {
                        row[phoneNumberIndex] = phone.mNumber;
                    }
                    if (phoneTypeIndex != -1) {
                        row[phoneTypeIndex] = phone.mType;
                    }
                    if (idIndex != -1) {
                        row[idIndex] = id;
                    }
                    sortedResultsMap.put(new GalSortKey(sortName, id), row.clone());
                    addedContact = true;
                    id++;
                }

            } else {
                boolean haveEmail = false;
                Object address = galDataRow.get(GalData.EMAIL_ADDRESS);
                if (address != null && !TextUtils.isEmpty(address.toString())) {
                    if (emailIndex != -1) {
                        row[emailIndex] = address;
                    }
                    if (emailTypeIndex != -1) {
                        row[emailTypeIndex] = Email.TYPE_WORK;
                    }
                    haveEmail = true;
                }

                if (!isEmailFilter || haveEmail) {
                    if (idIndex != -1) {
                        row[idIndex] = id;
                    }
                    sortedResultsMap.put(new GalSortKey(sortName, id), row.clone());
                    addedContact = true;
                    id++;
                }
            }
            if (addedContact) {
                contactId++;
                if (contactId > limit) {
                    break;
                }
            }
        }
        final MatrixCursor cursor = new MatrixCursor(projection, sortedResultsMap.size());
        for(Object[] result : sortedResultsMap.values()) {
            cursor.addRow(result);
        }

        return cursor;
    }

    /**
     * Try to create a display name from various fields.
     *
     * @return a display name for contact and its source
     */
    private static Pair<String, Integer> getDisplayName(GalData galDataRow, List<PhoneInfo> phones) {
        String displayName = galDataRow.get(GalData.DISPLAY_NAME);
        if (!TextUtils.isEmpty(displayName)) {
            return Pair.create(displayName, DisplayNameSources.STRUCTURED_NAME);
        }

        // try to get displayName from name fields
        final String firstName = galDataRow.get(GalData.FIRST_NAME);
        final String lastName = galDataRow.get(GalData.LAST_NAME);
        if (!TextUtils.isEmpty(firstName) || !TextUtils.isEmpty(lastName)) {
            if (!TextUtils.isEmpty(firstName) && !TextUtils.isEmpty(lastName)) {
                displayName = firstName + " " + lastName;
            } else if (!TextUtils.isEmpty(firstName)) {
                displayName = firstName;
            } else {
                displayName = lastName;
            }
            return Pair.create(displayName, DisplayNameSources.STRUCTURED_NAME);
        }

        // try to get displayName from email
        final String emailAddress = galDataRow.get(GalData.EMAIL_ADDRESS);
        if (!TextUtils.isEmpty(emailAddress)) {
            return Pair.create(emailAddress, DisplayNameSources.EMAIL);
        }

        // try to get displayName from phone numbers
        if (phones != null && phones.size() > 0) {
            final PhoneInfo phone = (PhoneInfo) phones.get(0);
            if (phone != null && !TextUtils.isEmpty(phone.mNumber)) {
                return Pair.create(phone.mNumber, DisplayNameSources.PHONE);
            }
        }
        return Pair.create(null, null);
    }

    /**
     * Try to create the alternate display name from various fields. The CP2
     * Alternate Display Name field is LastName FirstName to support user
     * choice of how to order names for display.
     *
     * @return alternate display name for contact and its source
     */
    private static String getAlternateDisplayName(GalData galDataRow, String displayName) {
        // try to get displayName from name fields
        final String firstName = galDataRow.get(GalData.FIRST_NAME);
        final String lastName = galDataRow.get(GalData.LAST_NAME);
        if (!TextUtils.isEmpty(firstName) && !TextUtils.isEmpty(lastName)) {
            return lastName + " " + firstName;
        } else if (!TextUtils.isEmpty(lastName)) {
            return lastName;
        }
        return displayName;
    }

    private void addPhoneInfo(List<PhoneInfo> phones, String number, int type) {
        if (!TextUtils.isEmpty(number)) {
            phones.add(new PhoneInfo(number, type));
        }
    }

    @Override
    public String getType(Uri uri) {
        final int match = sURIMatcher.match(uri);
        switch (match) {
            case GAL_FILTER:
                return Contacts.CONTENT_ITEM_TYPE;
        }
        return null;
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        throw new UnsupportedOperationException();
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        throw new UnsupportedOperationException();
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        throw new UnsupportedOperationException();
    }

    /**
     * Sort key for Gal filter results.
     *  - primary key is name
     *      for SORT_KEY_PRIMARY, this is displayName
     *      for SORT_KEY_ALTERNATIVE, this is alternativeDisplayName
     *      if no sort order is specified, this key is empty
     *  - secondary key is id, so ordering of the original results are
     *      preserved both between contacts with the same name and for
     *      multiple results within a given contact
     */
    protected static class GalSortKey {
        final String sortName;
        final int id;

        public GalSortKey(final String sortName, final int id) {
            this.sortName = sortName;
            this.id = id;
        }
    }

    /**
     * The Comparator that is used by ExchangeDirectoryProvider
     */
    protected static class NameComparator implements Comparator<GalSortKey> {
        private final Collator collator;

        public NameComparator() {
            collator = Collator.getInstance();
            // Case insensitive sorting
            collator.setStrength(Collator.SECONDARY);
        }

        @Override
        public int compare(final GalSortKey lhs, final GalSortKey rhs) {
            if (lhs.sortName != null && rhs.sortName != null) {
                final int res = collator.compare(lhs.sortName, rhs.sortName);
                if (res != 0) {
                    return res;
                }
            } else if (lhs.sortName != null) {
                return 1;
            } else if (rhs.sortName != null) {
                return -1;
            }

            // Either the names compared equally or both were null, use the id to compare.
            if (lhs.id != rhs.id) {
                return lhs.id > rhs.id ? 1 : -1;
            }
            return 0;
        }
    }

    private static class PhoneInfo {
        private String mNumber;
        private int mType;

        private PhoneInfo(String number, int type) {
            mNumber = number;
            mType = type;
        }
    }
}
