/*
 * 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.providers.contacts.aggregation;

import static com.android.providers.contacts.aggregation.util.RawContactMatcher.SCORE_THRESHOLD_PRIMARY;
import static com.android.providers.contacts.aggregation.util.RawContactMatcher.SCORE_THRESHOLD_SECONDARY;
import static com.android.providers.contacts.aggregation.util.RawContactMatcher.SCORE_THRESHOLD_SUGGEST;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.provider.ContactsContract.AggregationExceptions;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Identity;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.Contacts.AggregationSuggestions;
import android.provider.ContactsContract.Data;
import android.provider.ContactsContract.FullNameStyle;
import android.provider.ContactsContract.PhotoFiles;
import android.provider.ContactsContract.RawContacts;
import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import com.android.providers.contacts.ContactsDatabaseHelper;
import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupColumns;
import com.android.providers.contacts.ContactsDatabaseHelper.NameLookupType;
import com.android.providers.contacts.ContactsDatabaseHelper.PhoneLookupColumns;
import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
import com.android.providers.contacts.ContactsProvider2;
import com.android.providers.contacts.NameSplitter;
import com.android.providers.contacts.PhotoPriorityResolver;
import com.android.providers.contacts.TransactionContext;
import com.android.providers.contacts.aggregation.util.CommonNicknameCache;
import com.android.providers.contacts.aggregation.util.ContactAggregatorHelper;
import com.android.providers.contacts.aggregation.util.MatchScore;
import com.android.providers.contacts.aggregation.util.RawContactMatcher;
import com.android.providers.contacts.aggregation.util.RawContactMatchingCandidates;
import com.android.providers.contacts.database.ContactsTableUtil;
import com.google.android.collect.Sets;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * ContactAggregator2 deals with aggregating contact information with sufficient matching data
 * points. E.g., two John Doe contacts with same phone numbers are presumed to be the same
 * person unless the user declares otherwise.
 */
public class ContactAggregator2 extends AbstractContactAggregator {

    // Possible operation types for contacts aggregation.
    private static final int CREATE_NEW_CONTACT = 1;
    private static final int KEEP_INTACT = 0;
    private static final int RE_AGGREGATE = -1;

    private final RawContactMatcher mMatcher = new RawContactMatcher();

    /**
     * Constructor.
     */
    public ContactAggregator2(ContactsProvider2 contactsProvider,
            ContactsDatabaseHelper contactsDatabaseHelper,
            PhotoPriorityResolver photoPriorityResolver, NameSplitter nameSplitter,
            CommonNicknameCache commonNicknameCache) {
        super(contactsProvider, contactsDatabaseHelper, photoPriorityResolver, nameSplitter,
                commonNicknameCache);
    }

    /**
     * Given a specific raw contact, finds all matching raw contacts and re-aggregate them
     * based on the matching connectivity.
     */
     synchronized void aggregateContact(TransactionContext txContext, SQLiteDatabase db,
             long rawContactId, long accountId, long currentContactId,
             MatchCandidateList candidates) {

         if (!needAggregate(db, rawContactId)) {
             if (VERBOSE_LOGGING) {
                 Log.v(TAG, "Skip rid=" + rawContactId + " which has already been aggregated.");
             }
             return;
         }

         if (VERBOSE_LOGGING) {
            Log.v(TAG, "aggregateContact: rid=" + rawContactId + " cid=" + currentContactId);
        }

        int aggregationMode = RawContacts.AGGREGATION_MODE_DEFAULT;

        Integer aggModeObject = mRawContactsMarkedForAggregation.remove(rawContactId);
        if (aggModeObject != null) {
            aggregationMode = aggModeObject;
        }

        RawContactMatcher matcher = new RawContactMatcher();
        RawContactMatchingCandidates matchingCandidates = new RawContactMatchingCandidates();
        if (aggregationMode == RawContacts.AGGREGATION_MODE_DEFAULT) {
            // If this is a newly inserted contact or a visible contact, look for
            // data matches.
            if (currentContactId == 0
                    || mDbHelper.isContactInDefaultDirectory(db, currentContactId)) {
                // Find the set of matching candidates
                matchingCandidates = findRawContactMatchingCandidates(db, rawContactId, candidates,
                        matcher);
            }
        } else if (aggregationMode == RawContacts.AGGREGATION_MODE_DISABLED) {
            return;
        }

        // # of raw_contacts in the [currentContactId] contact excluding the [rawContactId]
        // raw_contact.
        long currentContactContentsCount = 0;

        if (currentContactId != 0) {
            mRawContactCountQuery.bindLong(1, currentContactId);
            mRawContactCountQuery.bindLong(2, rawContactId);
            currentContactContentsCount = mRawContactCountQuery.simpleQueryForLong();
        }

        // Set aggregation operation, i.e., re-aggregate, keep intact, or create new contact based
        // on the number of matching candidates and the number of raw_contacts in the
        // [currentContactId] excluding the [rawContactId].
        final int operation;
        final int candidatesCount = matchingCandidates.getCount();
        if (candidatesCount >= AGGREGATION_CONTACT_SIZE_LIMIT) {
            operation = KEEP_INTACT;
            if (VERBOSE_LOGGING) {
                Log.v(TAG, "Too many matching raw contacts (" + candidatesCount
                        + ") are found, so skip aggregation");
            }
        } else if (candidatesCount > 0) {
            operation = RE_AGGREGATE;
        } else {
            // When there is no matching raw contact found, if there are no other raw contacts in
            // the current aggregate, we might as well reuse it. Also, if the aggregation mode is
            // SUSPENDED, we must reuse the same aggregate.
            if (currentContactId != 0
                    && (currentContactContentsCount == 0
                    || aggregationMode == RawContacts.AGGREGATION_MODE_SUSPENDED)) {
                operation = KEEP_INTACT;
            } else {
                operation = CREATE_NEW_CONTACT;
            }
        }

        if (operation == KEEP_INTACT) {
            // Aggregation unchanged
            if (VERBOSE_LOGGING) {
                Log.v(TAG, "Aggregation unchanged");
            }
            markAggregated(db, String.valueOf(rawContactId));
        } else if (operation == CREATE_NEW_CONTACT) {
            // create new contact for [rawContactId]
            if (VERBOSE_LOGGING) {
                Log.v(TAG, "create new contact for rid=" + rawContactId);
            }
            createContactForRawContacts(db, txContext, Sets.newHashSet(rawContactId), null);
            if (currentContactContentsCount > 0) {
                updateAggregateData(txContext, currentContactId);
            }
            markAggregated(db, String.valueOf(rawContactId));
        } else {
            // re-aggregate
            if (VERBOSE_LOGGING) {
                Log.v(TAG, "Re-aggregating rids=" + rawContactId + ","
                        + TextUtils.join(",", matchingCandidates.getRawContactIdSet()));
            }
            reAggregateRawContacts(txContext, db, currentContactId, rawContactId, accountId,
                    currentContactContentsCount, matchingCandidates);
        }
    }

    private boolean needAggregate(SQLiteDatabase db, long rawContactId) {
        final String sql = "SELECT " + RawContacts._ID + " FROM " + Tables.RAW_CONTACTS +
                " WHERE " + RawContactsColumns.AGGREGATION_NEEDED + "=1" +
                " AND " + RawContacts._ID + "=?";

        mSelectionArgs1[0] = String.valueOf(rawContactId);
        final Cursor cursor = db.rawQuery(sql, mSelectionArgs1);

        try {
            return cursor.getCount() != 0;
        } finally {
            cursor.close();
        }
    }
    /**
     * Find the set of matching raw contacts for given rawContactId. Add all the raw contact
     * candidates with matching scores > threshold to RawContactMatchingCandidates. Keep doing
     * this for every raw contact in RawContactMatchingCandidates until is it not changing.
     */
    private RawContactMatchingCandidates findRawContactMatchingCandidates(SQLiteDatabase db, long
            rawContactId, MatchCandidateList candidates, RawContactMatcher matcher) {
        updateMatchScores(db, rawContactId, candidates, matcher);
        final RawContactMatchingCandidates matchingCandidates = new RawContactMatchingCandidates(
                matcher.pickBestMatches());
        Set<Long> newIds = new ArraySet<>();
        newIds.addAll(matchingCandidates.getRawContactIdSet());
        // Keep doing the following until no new raw contact candidate is found.
        while (!newIds.isEmpty()) {
            if (matchingCandidates.getCount() >= AGGREGATION_CONTACT_SIZE_LIMIT) {
                return matchingCandidates;
            }
            final Set<Long> tmpIdSet = new ArraySet<>();
            for (long rId : newIds) {
                final RawContactMatcher rMatcher = new RawContactMatcher();
                updateMatchScores(db, rId, new MatchCandidateList(),
                        rMatcher);
                List<MatchScore> newMatches = rMatcher.pickBestMatches();
                for (MatchScore newMatch : newMatches) {
                    final long newRawContactId = newMatch.getRawContactId();
                    if (!matchingCandidates.getRawContactIdSet().contains(newRawContactId)) {
                        tmpIdSet.add(newRawContactId);
                        matchingCandidates.add(newMatch);
                    }
                }
            }
            newIds.clear();
            newIds.addAll(tmpIdSet);
        }
        return matchingCandidates;
    }

    /**
     * Find out which mime-types are shared by more than one contacts for {@code rawContactIds}.
     * Clear the is_super_primary settings for these mime-types.
     * {@code rawContactIds} should be a comma separated ID list.
     */
     private void clearSuperPrimarySetting(SQLiteDatabase db, String rawContactIds) {
        final String sql =
                "SELECT " + DataColumns.MIMETYPE_ID + ", count(1) c  FROM " +
                        Tables.DATA +" WHERE " + Data.IS_SUPER_PRIMARY + " = 1 AND " +
                        Data.RAW_CONTACT_ID + " IN (" + rawContactIds + ") group by " +
                        DataColumns.MIMETYPE_ID + " HAVING c > 1";

        // Find out which mime-types exist with is_super_primary=true on more then one contacts.
        int index = 0;
        final StringBuilder mimeTypeCondition = new StringBuilder();
        mimeTypeCondition.append(" AND " + DataColumns.MIMETYPE_ID + " IN (");

        final Cursor c = db.rawQuery(sql, null);
        try {
            c.moveToPosition(-1);
            while (c.moveToNext()) {
                if (index > 0) {
                    mimeTypeCondition.append(',');
                }
                mimeTypeCondition.append(c.getLong((0)));
                index++;
            }
        } finally {
            c.close();
        }

        if (index == 0) {
            return;
        }

        // Clear is_super_primary setting for all the mime-types with is_super_primary=true
        // in both raw contact of rawContactId and raw contacts of contactId
        String superPrimaryUpdateSql = "UPDATE " + Tables.DATA +
                " SET " + Data.IS_SUPER_PRIMARY + "=0" +
                " WHERE " +  Data.RAW_CONTACT_ID +
                " IN (" + rawContactIds + ")";

        mimeTypeCondition.append(')');
        superPrimaryUpdateSql += mimeTypeCondition.toString();
        db.execSQL(superPrimaryUpdateSql);
    }

    private String buildExceptionMatchingSql(String rawContactIdSet1, String rawContactIdSet2,
            int aggregationType, boolean countOnly) {
        final String idPairSelection =  "SELECT " + AggregationExceptions.RAW_CONTACT_ID1 + ", " +
                AggregationExceptions.RAW_CONTACT_ID2;
        final String sql =
                " FROM " + Tables.AGGREGATION_EXCEPTIONS +
                " WHERE " + AggregationExceptions.RAW_CONTACT_ID1 + " IN (" +
                        rawContactIdSet1 + ")" +
                " AND " + AggregationExceptions.RAW_CONTACT_ID2 + " IN (" + rawContactIdSet2 + ")" +
                " AND " + AggregationExceptions.TYPE + "=" + aggregationType;
        return (countOnly) ? RawContactMatchingSelectionStatement.SELECT_COUNT + sql :
                idPairSelection + sql;
    }

    /**
     * Re-aggregate rawContact of {@code rawContactId} and all the raw contacts of
     * {@code matchingCandidates} into connected components. This only happens when a given
     * raw contacts cannot be joined with its best matching contacts directly.
     *
     *  Two raw contacts are considered connected if they share at least one email address, phone
     *  number or identity. Create new contact for each connected component except the very first
     *  one that doesn't contain rawContactId of {@code rawContactId}.
     */
    private void reAggregateRawContacts(TransactionContext txContext, SQLiteDatabase db,
            long currentCidForRawContact, long rawContactId, long accountId,
            long currentContactContentsCount, RawContactMatchingCandidates matchingCandidates) {
        // Find the connected component based on the aggregation exceptions or
        // identity/email/phone matching for all the raw contacts of [contactId] and the give
        // raw contact.
        final Set<Long> allIds = new ArraySet<>();
        allIds.add(rawContactId);
        allIds.addAll(matchingCandidates.getRawContactIdSet());
        final Set<Set<Long>> connectedRawContactSets = findConnectedRawContacts(db, allIds);

        final Map<Long, Long> rawContactsToAccounts = matchingCandidates.getRawContactToAccount();
        rawContactsToAccounts.put(rawContactId, accountId);
        ContactAggregatorHelper.mergeComponentsWithDisjointAccounts(connectedRawContactSets,
                rawContactsToAccounts);
        breakComponentsByExceptions(db, connectedRawContactSets);

        // Create new contact for each connected component. Use the first reusable contactId if
        // possible. If no reusable contactId found, create new contact for the connected component.
        // Update aggregate data for all the contactIds touched by this connected component,
        for (Set<Long> connectedRawContactIds : connectedRawContactSets) {
            Long contactId = null;
            Set<Long> cidsNeedToBeUpdated = new ArraySet<>();
            if (connectedRawContactIds.contains(rawContactId)) {
                // If there is no other raw contacts aggregated with the given raw contact currently
                // or all the raw contacts in [currentCidForRawContact] are still in the same
                // connected component, we might as well reuse it.
                if (currentCidForRawContact != 0 &&
                        (currentContactContentsCount == 0) ||
                        canBeReused(db, currentCidForRawContact, connectedRawContactIds)) {
                    contactId = currentCidForRawContact;
                    for (Long connectedRawContactId : connectedRawContactIds) {
                        Long cid = matchingCandidates.getContactId(connectedRawContactId);
                        if (cid != null && !cid.equals(contactId)) {
                            cidsNeedToBeUpdated.add(cid);
                        }
                    }
                } else if (currentCidForRawContact != 0){
                    cidsNeedToBeUpdated.add(currentCidForRawContact);
                }
            } else {
                boolean foundContactId = false;
                for (Long connectedRawContactId : connectedRawContactIds) {
                    Long currentContactId = matchingCandidates.getContactId(connectedRawContactId);
                    if (!foundContactId && currentContactId != null &&
                            canBeReused(db, currentContactId, connectedRawContactIds)) {
                        contactId = currentContactId;
                        foundContactId = true;
                    } else {
                        cidsNeedToBeUpdated.add(currentContactId);
                    }
                }
            }
            final String connectedRids = TextUtils.join(",", connectedRawContactIds);
            clearSuperPrimarySetting(db, connectedRids);
            createContactForRawContacts(db, txContext, connectedRawContactIds, contactId);
            // re-aggregate
            if (VERBOSE_LOGGING) {
                Log.v(TAG, "Aggregating rids=" + connectedRawContactIds);
            }
            markAggregated(db, connectedRids);

            for (Long cid : cidsNeedToBeUpdated) {
                long currentRcCount = 0;
                if (cid != 0) {
                    mRawContactCountQuery.bindLong(1, cid);
                    mRawContactCountQuery.bindLong(2, 0);
                    currentRcCount = mRawContactCountQuery.simpleQueryForLong();
                }

                if (currentRcCount == 0) {
                    // Delete a contact if it doesn't contain anything
                    ContactsTableUtil.deleteContact(db, cid);
                    mAggregatedPresenceDelete.bindLong(1, cid);
                    mAggregatedPresenceDelete.execute();
                } else {
                    updateAggregateData(txContext, cid);
                }
            }
        }
    }

    /**
     * Check if contactId can be reused as the contact Id for new aggregation of all the
     * connectedRawContactIds. If connectedRawContactIds set contains all the raw contacts
     * currently aggregated under contactId, return true; Otherwise, return false.
     */
    private boolean canBeReused(SQLiteDatabase db, Long contactId,
            Set<Long> connectedRawContactIds) {
        final String sql = "SELECT " + RawContactsColumns.CONCRETE_ID + " FROM " +
                Tables.RAW_CONTACTS + " WHERE " + RawContacts.CONTACT_ID + "=? AND " +
                RawContacts.DELETED + "=0";
        mSelectionArgs1[0] = String.valueOf(contactId);
        final Cursor cursor = db.rawQuery(sql, mSelectionArgs1);
        try {
            cursor.moveToPosition(-1);
            while (cursor.moveToNext()) {
                if (!connectedRawContactIds.contains(cursor.getLong(0))) {
                    return false;
                }
            }
        } finally {
            cursor.close();
        }
        return true;
    }

    /**
     * Separate all the raw_contacts which has "SEPARATE" aggregation exception to another
     * raw_contacts in the same component.
     */
    private void breakComponentsByExceptions(SQLiteDatabase db,
            Set<Set<Long>> connectedRawContacts) {
        final Set<Set<Long>> tmpSets = new ArraySet<>(connectedRawContacts);
        for (Set<Long> component : tmpSets) {
            final String rawContacts = TextUtils.join(",", component);
            // If "SEPARATE" exception is found inside an connected component [component],
            // remove the [component] from [connectedRawContacts], and create new connected
            // components for all raw contacts of [component] solely based on "JOIN" exceptions
            // and add them to [connectedRawContacts].
            if (isFirstColumnGreaterThanZero(db, buildExceptionMatchingSql(rawContacts, rawContacts,
                    AggregationExceptions.TYPE_KEEP_SEPARATE, /* countOnly =*/true))) {
                Multimap<Long, Long> joinPairs = HashMultimap.create();
                findIdPairs(db, buildExceptionMatchingSql(rawContacts, rawContacts), joinPairs);
                connectedRawContacts.remove(component);
                connectedRawContacts.addAll(
                    ContactAggregatorHelper.findConnectedComponents(component, joinPairs));
            }
        }
    }

    /**
     * Ensures that automatic aggregation rules are followed after a contact
     * becomes visible or invisible. Specifically, consider this case: there are
     * three contacts named Foo. Two of them come from account A1 and one comes
     * from account A2. The aggregation rules say that in this case none of the
     * three Foo's should be aggregated: two of them are in the same account, so
     * they don't get aggregated; the third has two affinities, so it does not
     * join either of them.
     * <p>
     * Consider what happens if one of the "Foo"s from account A1 becomes
     * invisible. Nothing stands in the way of aggregating the other two
     * anymore, so they should get joined.
     * <p>
     * What if the invisible "Foo" becomes visible after that? We should split the
     * aggregate between the other two.
     */
    public void updateAggregationAfterVisibilityChange(long contactId) {
        SQLiteDatabase db = mDbHelper.getWritableDatabase();
        boolean visible = mDbHelper.isContactInDefaultDirectory(db, contactId);
        if (visible) {
            markContactForAggregation(db, contactId);
        } else {
            // Find all contacts that _could be_ aggregated with this one and
            // rerun aggregation for all of them
            mSelectionArgs1[0] = String.valueOf(contactId);
            Cursor cursor = db.query(RawContactIdQuery.TABLE, RawContactIdQuery.COLUMNS,
                    RawContactIdQuery.SELECTION, mSelectionArgs1, null, null, null);
            try {
                while (cursor.moveToNext()) {
                    long rawContactId = cursor.getLong(RawContactIdQuery.RAW_CONTACT_ID);
                    mMatcher.clear();

                    updateMatchScoresBasedOnIdentityMatch(db, rawContactId, mMatcher);
                    updateMatchScoresBasedOnNameMatches(db, rawContactId, mMatcher);
                    List<MatchScore> bestMatches =
                            mMatcher.pickBestMatches(SCORE_THRESHOLD_PRIMARY);
                    for (MatchScore matchScore : bestMatches) {
                        markContactForAggregation(db, matchScore.getContactId());
                    }

                    mMatcher.clear();
                    updateMatchScoresBasedOnEmailMatches(db, rawContactId, mMatcher);
                    updateMatchScoresBasedOnPhoneMatches(db, rawContactId, mMatcher);
                    bestMatches =
                            mMatcher.pickBestMatches(SCORE_THRESHOLD_SECONDARY);
                    for (MatchScore matchScore : bestMatches) {
                        markContactForAggregation(db, matchScore.getContactId());
                    }
                }
            } finally {
                cursor.close();
            }
        }
    }

    /**
     * Computes match scores based on exceptions entered by the user: always match and never match.
     */
    private void updateMatchScoresBasedOnExceptions(SQLiteDatabase db, long rawContactId,
            RawContactMatcher matcher) {
        if (!mAggregationExceptionIdsValid) {
            prefetchAggregationExceptionIds(db);
        }

        // If there are no aggregation exceptions involving this raw contact, there is no need to
        // run a query and we can just return -1, which stands for "nothing found"
        if (!mAggregationExceptionIds.contains(rawContactId)) {
            return;
        }

        final Cursor c = db.query(AggregateExceptionQuery.TABLE,
                AggregateExceptionQuery.COLUMNS,
                AggregationExceptions.RAW_CONTACT_ID1 + "=" + rawContactId
                        + " OR " + AggregationExceptions.RAW_CONTACT_ID2 + "=" + rawContactId,
                null, null, null, null);

        try {
            while (c.moveToNext()) {
                int type = c.getInt(AggregateExceptionQuery.TYPE);
                long rawContactId1 = c.getLong(AggregateExceptionQuery.RAW_CONTACT_ID1);
                long contactId = -1;
                long rId = -1;
                long accountId = -1;
                if (rawContactId == rawContactId1) {
                    if (!c.isNull(AggregateExceptionQuery.RAW_CONTACT_ID2)) {
                        rId = c.getLong(AggregateExceptionQuery.RAW_CONTACT_ID2);
                        contactId = c.getLong(AggregateExceptionQuery.CONTACT_ID2);
                        accountId = c.getLong(AggregateExceptionQuery.ACCOUNT_ID2);
                    }
                } else {
                    if (!c.isNull(AggregateExceptionQuery.RAW_CONTACT_ID1)) {
                        rId = c.getLong(AggregateExceptionQuery.RAW_CONTACT_ID1);
                        contactId = c.getLong(AggregateExceptionQuery.CONTACT_ID1);
                        accountId = c.getLong(AggregateExceptionQuery.ACCOUNT_ID1);
                    }
                }
                if (rId != -1) {
                    if (type == AggregationExceptions.TYPE_KEEP_TOGETHER) {
                        matcher.keepIn(rId, contactId, accountId);
                    } else {
                        matcher.keepOut(rId, contactId, accountId);
                    }
                }
            }
        } finally {
            c.close();
        }
    }

    /**
     * Finds contacts with exact identity matches to the the specified raw contact.
     */
    private void updateMatchScoresBasedOnIdentityMatch(SQLiteDatabase db, long rawContactId,
            RawContactMatcher matcher) {
        mSelectionArgs2[0] = String.valueOf(rawContactId);
        mSelectionArgs2[1] = String.valueOf(mMimeTypeIdIdentity);
        Cursor c = db.query(IdentityLookupMatchQuery.TABLE, IdentityLookupMatchQuery.COLUMNS,
                IdentityLookupMatchQuery.SELECTION,
                mSelectionArgs2, RawContacts.CONTACT_ID, null, null);
        try {
            while (c.moveToNext()) {
                final long rId = c.getLong(IdentityLookupMatchQuery.RAW_CONTACT_ID);
                if (rId == rawContactId) {
                    continue;
                }
                final long contactId = c.getLong(IdentityLookupMatchQuery.CONTACT_ID);
                final long accountId = c.getLong(IdentityLookupMatchQuery.ACCOUNT_ID);
                matcher.matchIdentity(rId, contactId, accountId);
            }
        } finally {
            c.close();
        }
    }

    /**
     * Finds contacts with names matching the name of the specified raw contact.
     */
    private void updateMatchScoresBasedOnNameMatches(SQLiteDatabase db, long rawContactId,
            RawContactMatcher matcher) {
        mSelectionArgs1[0] = String.valueOf(rawContactId);
        Cursor c = db.query(NameLookupMatchQuery.TABLE, NameLookupMatchQuery.COLUMNS,
                NameLookupMatchQuery.SELECTION,
                mSelectionArgs1, null, null, null, PRIMARY_HIT_LIMIT_STRING);
        try {
            while (c.moveToNext()) {
                long rId =  c.getLong(NameLookupMatchQuery.RAW_CONTACT_ID);
                if (rId == rawContactId) {
                    continue;
                }
                long contactId = c.getLong(NameLookupMatchQuery.CONTACT_ID);
                long accountId = c.getLong(NameLookupMatchQuery.ACCOUNT_ID);
                String name = c.getString(NameLookupMatchQuery.NAME);
                int nameTypeA = c.getInt(NameLookupMatchQuery.NAME_TYPE_A);
                int nameTypeB = c.getInt(NameLookupMatchQuery.NAME_TYPE_B);
                matcher.matchName(rId, contactId, accountId, nameTypeA, name,
                        nameTypeB, name, RawContactMatcher.MATCHING_ALGORITHM_EXACT);
                if (nameTypeA == NameLookupType.NICKNAME &&
                        nameTypeB == NameLookupType.NICKNAME) {
                    matcher.updateScoreWithNicknameMatch(rId, contactId, accountId);
                }
            }
        } finally {
            c.close();
        }
    }

    private void updateMatchScoresBasedOnEmailMatches(SQLiteDatabase db, long rawContactId,
            RawContactMatcher matcher) {
        mSelectionArgs2[0] = String.valueOf(rawContactId);
        mSelectionArgs2[1] = String.valueOf(mMimeTypeIdEmail);
        Cursor c = db.query(EmailLookupQuery.TABLE, EmailLookupQuery.COLUMNS,
                EmailLookupQuery.SELECTION,
                mSelectionArgs2, null, null, null, SECONDARY_HIT_LIMIT_STRING);
        try {
            while (c.moveToNext()) {
                long rId = c.getLong(EmailLookupQuery.RAW_CONTACT_ID);
                if (rId == rawContactId) {
                    continue;
                }
                long contactId = c.getLong(EmailLookupQuery.CONTACT_ID);
                long accountId = c.getLong(EmailLookupQuery.ACCOUNT_ID);
                matcher.updateScoreWithEmailMatch(rId, contactId, accountId);
            }
        } finally {
            c.close();
        }
    }

    /**
     * Finds contacts with names matching the specified name.
     */
    private void updateMatchScoresBasedOnNameMatches(SQLiteDatabase db, String query,
            MatchCandidateList candidates, RawContactMatcher matcher) {
        candidates.clear();
        NameLookupSelectionBuilder builder = new NameLookupSelectionBuilder(
                mNameSplitter, candidates);
        builder.insertNameLookup(0, 0, query, FullNameStyle.UNDEFINED);
        if (builder.isEmpty()) {
            return;
        }

        Cursor c = db.query(NameLookupMatchQueryWithParameter.TABLE,
                NameLookupMatchQueryWithParameter.COLUMNS, builder.getSelection(), null, null, null,
                null, PRIMARY_HIT_LIMIT_STRING);
        try {
            while (c.moveToNext()) {
                long rId = c.getLong(NameLookupMatchQueryWithParameter.RAW_CONTACT_ID);
                long contactId = c.getLong(NameLookupMatchQueryWithParameter.CONTACT_ID);
                long accountId = c.getLong(NameLookupMatchQueryWithParameter.ACCOUNT_ID);
                String name = c.getString(NameLookupMatchQueryWithParameter.NAME);
                int nameTypeA = builder.getLookupType(name);
                int nameTypeB = c.getInt(NameLookupMatchQueryWithParameter.NAME_TYPE);
                matcher.matchName(rId, contactId, accountId, nameTypeA, name, nameTypeB, name,
                        RawContactMatcher.MATCHING_ALGORITHM_EXACT);
                if (nameTypeA == NameLookupType.NICKNAME && nameTypeB == NameLookupType.NICKNAME) {
                    matcher.updateScoreWithNicknameMatch(rId, contactId, accountId);
                }
            }
        } finally {
            c.close();
        }
    }

    private void updateMatchScoresBasedOnPhoneMatches(SQLiteDatabase db, long rawContactId,
            RawContactMatcher matcher) {
        mSelectionArgs2[0] = String.valueOf(rawContactId);
        mSelectionArgs2[1] = mDbHelper.getUseStrictPhoneNumberComparisonParameter();
        Cursor c = db.query(PhoneLookupQuery.TABLE, PhoneLookupQuery.COLUMNS,
                PhoneLookupQuery.SELECTION,
                mSelectionArgs2, null, null, null, SECONDARY_HIT_LIMIT_STRING);
        try {
            while (c.moveToNext()) {
                long rId = c.getLong(PhoneLookupQuery.RAW_CONTACT_ID);
                if (rId == rawContactId) {
                    continue;
                }
                long contactId = c.getLong(PhoneLookupQuery.CONTACT_ID);
                long accountId = c.getLong(PhoneLookupQuery.ACCOUNT_ID);
                matcher.updateScoreWithPhoneNumberMatch(rId, contactId, accountId);
            }
        } finally {
            c.close();
        }
    }

    /**
     * Loads name lookup rows for approximate name matching and updates match scores based on that
     * data.
     */
    private void lookupApproximateNameMatches(SQLiteDatabase db, MatchCandidateList candidates,
            RawContactMatcher matcher) {
        ArraySet<String> firstLetters = new ArraySet<>();
        for (int i = 0; i < candidates.mCount; i++) {
            final NameMatchCandidate candidate = candidates.mList.get(i);
            if (candidate.mName.length() >= 2) {
                String firstLetter = candidate.mName.substring(0, 2);
                if (!firstLetters.contains(firstLetter)) {
                    firstLetters.add(firstLetter);
                    final String selection = "(" + NameLookupColumns.NORMALIZED_NAME + " GLOB '"
                            + firstLetter + "*') AND "
                            + "(" + NameLookupColumns.NAME_TYPE + " IN("
                                    + NameLookupType.NAME_COLLATION_KEY + ","
                                    + NameLookupType.EMAIL_BASED_NICKNAME + ","
                                    + NameLookupType.NICKNAME + ")) AND "
                            + RawContacts.CONTACT_ID + " IN " + Tables.DEFAULT_DIRECTORY;
                    matchAllCandidates(db, selection, candidates, matcher,
                            RawContactMatcher.MATCHING_ALGORITHM_APPROXIMATE,
                            String.valueOf(FIRST_LETTER_SUGGESTION_HIT_LIMIT));
                }
            }
        }
    }

    private interface ContactNameLookupQuery {
        String TABLE = Tables.NAME_LOOKUP_JOIN_RAW_CONTACTS;

        String[] COLUMNS = new String[] {
                RawContacts._ID,
                RawContacts.CONTACT_ID,
                RawContactsColumns.ACCOUNT_ID,
                NameLookupColumns.NORMALIZED_NAME,
                NameLookupColumns.NAME_TYPE
        };

        int RAW_CONTACT_ID = 0;
        int CONTACT_ID = 1;
        int ACCOUNT_ID = 2;
        int NORMALIZED_NAME = 3;
        int NAME_TYPE = 4;
    }

    /**
     * Loads all candidate rows from the name lookup table and updates match scores based
     * on that data.
     */
    private void matchAllCandidates(SQLiteDatabase db, String selection,
            MatchCandidateList candidates, RawContactMatcher matcher, int algorithm, String limit) {
        final Cursor c = db.query(ContactNameLookupQuery.TABLE, ContactNameLookupQuery.COLUMNS,
                selection, null, null, null, null, limit);

        try {
            while (c.moveToNext()) {
                Long rawContactId = c.getLong(ContactNameLookupQuery.RAW_CONTACT_ID);
                Long contactId = c.getLong(ContactNameLookupQuery.CONTACT_ID);
                Long accountId = c.getLong(ContactNameLookupQuery.ACCOUNT_ID);
                String name = c.getString(ContactNameLookupQuery.NORMALIZED_NAME);
                int nameType = c.getInt(ContactNameLookupQuery.NAME_TYPE);

                // Note the N^2 complexity of the following fragment. This is not a huge concern
                // since the number of candidates is very small and in general secondary hits
                // in the absence of primary hits are rare.
                for (int i = 0; i < candidates.mCount; i++) {
                    NameMatchCandidate candidate = candidates.mList.get(i);
                    matcher.matchName(rawContactId, contactId, accountId, candidate.mLookupType,
                            candidate.mName, nameType, name, algorithm);
                }
            }
        } finally {
            c.close();
        }
    }

    private interface PhotoFileQuery {
        final String[] COLUMNS = new String[] {
                PhotoFiles.HEIGHT,
                PhotoFiles.WIDTH,
                PhotoFiles.FILESIZE
        };

        int HEIGHT = 0;
        int WIDTH = 1;
        int FILESIZE = 2;
    }

    private class PhotoEntry implements Comparable<PhotoEntry> {
        // Pixel count (width * height) for the image.
        final int pixelCount;

        // File size (in bytes) of the image.  Not populated if the image is a thumbnail.
        final int fileSize;

        private PhotoEntry(int pixelCount, int fileSize) {
            this.pixelCount = pixelCount;
            this.fileSize = fileSize;
        }

        @Override
        public int compareTo(PhotoEntry pe) {
            if (pe == null) {
                return -1;
            }
            if (pixelCount == pe.pixelCount) {
                return pe.fileSize - fileSize;
            } else {
                return pe.pixelCount - pixelCount;
            }
        }
    }

    /**
     * Finds contacts with data matches and returns a list of {@link MatchScore}'s in the
     * descending order of match score.
     * @param parameters
     */
    protected List<MatchScore> findMatchingContacts(final SQLiteDatabase db, long contactId,
            ArrayList<AggregationSuggestionParameter> parameters) {

        MatchCandidateList candidates = new MatchCandidateList();
        RawContactMatcher matcher = new RawContactMatcher();

        if (parameters == null || parameters.size() == 0) {
            final Cursor c = db.query(RawContactIdQuery.TABLE, RawContactIdQuery.COLUMNS,
                    RawContacts.CONTACT_ID + "=" + contactId, null, null, null, null);
            try {
                while (c.moveToNext()) {
                    long rawContactId = c.getLong(RawContactIdQuery.RAW_CONTACT_ID);
                    long accountId = c.getLong(RawContactIdQuery.ACCOUNT_ID);
                    // Don't aggregate a contact with its own raw contacts.
                    matcher.keepOut(rawContactId, contactId, accountId);
                    updateMatchScoresForSuggestionsBasedOnDataMatches(db, rawContactId, candidates,
                            matcher);
                }
            } finally {
                c.close();
            }
        } else {
            updateMatchScoresForSuggestionsBasedOnDataMatches(db, candidates,
                    matcher, parameters);
        }

        return matcher.pickBestMatches(SCORE_THRESHOLD_SUGGEST);
    }

    /**
     * Computes suggestion scores for contacts that have matching data rows.
     * Aggregation suggestion doesn't consider aggregation exceptions, but is purely based on the
     * raw contacts information.
     */
    private void updateMatchScoresForSuggestionsBasedOnDataMatches(SQLiteDatabase db,
            long rawContactId, MatchCandidateList candidates, RawContactMatcher matcher) {

        updateMatchScoresBasedOnIdentityMatch(db, rawContactId, matcher);
        updateMatchScoresBasedOnNameMatches(db, rawContactId, matcher);
        updateMatchScoresBasedOnEmailMatches(db, rawContactId, matcher);
        updateMatchScoresBasedOnPhoneMatches(db, rawContactId, matcher);
        loadNameMatchCandidates(db, rawContactId, candidates, false);
        lookupApproximateNameMatches(db, candidates, matcher);
    }

    /**
     * Computes scores for contacts that have matching data rows.
     */
    private void updateMatchScores(SQLiteDatabase db, long rawContactId,
            MatchCandidateList candidates, RawContactMatcher matcher) {
        //update primary score
        updateMatchScoresBasedOnExceptions(db, rawContactId, matcher);
        updateMatchScoresBasedOnNameMatches(db, rawContactId, matcher);
        // update scores only if the raw contact doesn't have structured name
        if (rawContactWithoutName(db, rawContactId)) {
            updateMatchScoresBasedOnIdentityMatch(db, rawContactId, matcher);
            updateMatchScoresBasedOnEmailMatches(db, rawContactId, matcher);
            updateMatchScoresBasedOnPhoneMatches(db, rawContactId, matcher);
            final List<Long> secondaryRawContactIds = matcher.prepareSecondaryMatchCandidates();
            if (secondaryRawContactIds != null
                    && secondaryRawContactIds.size() <= SECONDARY_HIT_LIMIT) {
                updateScoreForCandidatesWithoutName(db, secondaryRawContactIds, matcher);
            }
        }
    }

    private void updateMatchScoresForSuggestionsBasedOnDataMatches(SQLiteDatabase db,
            MatchCandidateList candidates, RawContactMatcher matcher,
            ArrayList<AggregationSuggestionParameter> parameters) {
        for (AggregationSuggestionParameter parameter : parameters) {
            if (AggregationSuggestions.PARAMETER_MATCH_NAME.equals(parameter.kind)) {
                updateMatchScoresBasedOnNameMatches(db, parameter.value, candidates, matcher);
            }

            // TODO: add support for other parameter kinds
        }
    }

    private boolean rawContactWithoutName(SQLiteDatabase db, long rawContactId) {
        String selection = RawContacts._ID + " =" + rawContactId;
        final Cursor c = db.query(NullNameRawContactsIdsQuery.TABLE,
                NullNameRawContactsIdsQuery.COLUMNS, selection, null, null, null, null);

        try {
            if (c.moveToFirst()) {
                return TextUtils.isEmpty(c.getString(NullNameRawContactsIdsQuery.NAME));
            }
        } finally {
            c.close();
        }
        return false;
    }

    /**
     * Update scores for matches with secondary data matching but no structured name.
     */
    private void updateScoreForCandidatesWithoutName(SQLiteDatabase db,
            List<Long> secondaryRawContactIds, RawContactMatcher matcher) {

        mSb.setLength(0);

        mSb.append(RawContacts._ID).append(" IN (");
        for (int i = 0; i < secondaryRawContactIds.size(); i++) {
            if (i != 0) {
                mSb.append(",");
            }
            mSb.append(secondaryRawContactIds.get(i));
        }
        mSb.append( ")");
        final Cursor c = db.query(NullNameRawContactsIdsQuery.TABLE,
                NullNameRawContactsIdsQuery.COLUMNS, mSb.toString(), null, null, null, null);

        try {
            while (c.moveToNext()) {
                Long rId = c.getLong(NullNameRawContactsIdsQuery.RAW_CONTACT_ID);
                Long contactId = c.getLong(NullNameRawContactsIdsQuery.CONTACT_ID);
                Long accountId = c.getLong(NullNameRawContactsIdsQuery.ACCOUNT_ID);
                String name = c.getString(NullNameRawContactsIdsQuery.NAME);
                if (TextUtils.isEmpty(name)) {
                    matcher.matchNoName(rId, contactId, accountId);
                }
            }
        } finally {
            c.close();
        }
    }

    protected interface IdentityLookupMatchQuery {
        final String TABLE = Tables.DATA + " dataA"
                + " JOIN " + Tables.DATA + " dataB" +
                " ON (dataA." + Identity.NAMESPACE + "=dataB." + Identity.NAMESPACE +
                " AND dataA." + Identity.IDENTITY + "=dataB." + Identity.IDENTITY + ")"
                + " JOIN " + Tables.RAW_CONTACTS +
                " ON (dataB." + Data.RAW_CONTACT_ID + " = "
                + Tables.RAW_CONTACTS + "." + RawContacts._ID + ")";

        final String SELECTION = "dataA." + Data.RAW_CONTACT_ID + "=?1"
                + " AND dataA." + DataColumns.MIMETYPE_ID + "=?2"
                + " AND dataA." + Identity.NAMESPACE + " NOT NULL"
                + " AND dataA." + Identity.IDENTITY + " NOT NULL"
                + " AND dataB." + DataColumns.MIMETYPE_ID + "=?2"
                + " AND " + RawContacts.CONTACT_ID + " IN " + Tables.DEFAULT_DIRECTORY;

        final String[] COLUMNS = new String[] {
                RawContactsColumns.CONCRETE_ID, RawContacts.CONTACT_ID,
                RawContactsColumns.ACCOUNT_ID
        };

        int RAW_CONTACT_ID = 0;
        int CONTACT_ID = 1;
        int ACCOUNT_ID = 2;
    }

    protected interface NameLookupMatchQuery {
        String TABLE = Tables.NAME_LOOKUP + " nameA"
                + " JOIN " + Tables.NAME_LOOKUP + " nameB" +
                " ON (" + "nameA." + NameLookupColumns.NORMALIZED_NAME + "="
                + "nameB." + NameLookupColumns.NORMALIZED_NAME + ")"
                + " JOIN " + Tables.RAW_CONTACTS +
                " ON (nameB." + NameLookupColumns.RAW_CONTACT_ID + " = "
                + Tables.RAW_CONTACTS + "." + RawContacts._ID + ")";

        String SELECTION = "nameA." + NameLookupColumns.RAW_CONTACT_ID + "=?"
                + " AND " + RawContacts.CONTACT_ID + " IN " + Tables.DEFAULT_DIRECTORY;

        String[] COLUMNS = new String[] {
                RawContacts._ID,
                RawContacts.CONTACT_ID,
                RawContactsColumns.ACCOUNT_ID,
                "nameA." + NameLookupColumns.NORMALIZED_NAME,
                "nameA." + NameLookupColumns.NAME_TYPE,
                "nameB." + NameLookupColumns.NAME_TYPE,
        };

        int RAW_CONTACT_ID = 0;
        int CONTACT_ID = 1;
        int ACCOUNT_ID = 2;
        int NAME = 3;
        int NAME_TYPE_A = 4;
        int NAME_TYPE_B = 5;
    }

    protected interface EmailLookupQuery {
        String TABLE = Tables.DATA + " dataA"
                + " JOIN " + Tables.DATA + " dataB" +
                " ON dataA." + Email.DATA + "= dataB." + Email.DATA
                + " JOIN " + Tables.RAW_CONTACTS +
                " ON (dataB." + Data.RAW_CONTACT_ID + " = "
                + Tables.RAW_CONTACTS + "." + RawContacts._ID + ")";

        String SELECTION = "dataA." + Data.RAW_CONTACT_ID + "=?1"
                + " AND dataA." + DataColumns.MIMETYPE_ID + "=?2"
                + " AND dataA." + Email.DATA + " NOT NULL"
                + " AND dataB." + DataColumns.MIMETYPE_ID + "=?2"
                + " AND " + RawContacts.CONTACT_ID + " IN " + Tables.DEFAULT_DIRECTORY;

        String[] COLUMNS = new String[] {
                Tables.RAW_CONTACTS + "." + RawContacts._ID,
                RawContacts.CONTACT_ID,
                RawContactsColumns.ACCOUNT_ID
        };

        int RAW_CONTACT_ID = 0;
        int CONTACT_ID = 1;
        int ACCOUNT_ID = 2;
    }

    protected interface PhoneLookupQuery {
        String TABLE = Tables.PHONE_LOOKUP + " phoneA"
                + " JOIN " + Tables.DATA + " dataA"
                + " ON (dataA." + Data._ID + "=phoneA." + PhoneLookupColumns.DATA_ID + ")"
                + " JOIN " + Tables.PHONE_LOOKUP + " phoneB"
                + " ON (phoneA." + PhoneLookupColumns.MIN_MATCH + "="
                + "phoneB." + PhoneLookupColumns.MIN_MATCH + ")"
                + " JOIN " + Tables.DATA + " dataB"
                + " ON (dataB." + Data._ID + "=phoneB." + PhoneLookupColumns.DATA_ID + ")"
                + " JOIN " + Tables.RAW_CONTACTS
                + " ON (dataB." + Data.RAW_CONTACT_ID + " = "
                + Tables.RAW_CONTACTS + "." + RawContacts._ID + ")";

        String SELECTION = "dataA." + Data.RAW_CONTACT_ID + "=?"
                + " AND PHONE_NUMBERS_EQUAL(dataA." + Phone.NUMBER + ", "
                + "dataB." + Phone.NUMBER + ",?)"
                + " AND " + RawContacts.CONTACT_ID + " IN " + Tables.DEFAULT_DIRECTORY;

        String[] COLUMNS = new String[] {
                Tables.RAW_CONTACTS + "." + RawContacts._ID,
                RawContacts.CONTACT_ID,
                RawContactsColumns.ACCOUNT_ID
        };

        int RAW_CONTACT_ID = 0;
        int CONTACT_ID = 1;
        int ACCOUNT_ID = 2;
    }

    protected interface NullNameRawContactsIdsQuery {
        final String TABLE =  Tables.RAW_CONTACTS + " LEFT OUTER JOIN " +  Tables.NAME_LOOKUP
                + " ON "+ RawContacts._ID + " = " + NameLookupColumns.RAW_CONTACT_ID
                + " AND " + NameLookupColumns.NAME_TYPE + " = " + NameLookupType.NAME_EXACT;

        final String[] COLUMNS = new String[] {
                RawContacts._ID, RawContacts.CONTACT_ID, RawContactsColumns.ACCOUNT_ID,
                NameLookupColumns.NORMALIZED_NAME};

        int RAW_CONTACT_ID = 0;
        int CONTACT_ID = 1;
        int ACCOUNT_ID = 2;
        int NAME = 3;
    }
}
