/*
 * Copyright (C) 2011 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.ex.chips;

import android.accounts.Account;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.graphics.drawable.StateListDrawable;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.text.TextUtils;
import android.text.util.Rfc822Token;
import android.text.util.Rfc822Tokenizer;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;

import com.android.ex.chips.BaseRecipientAdapter.DirectoryListQuery;
import com.android.ex.chips.BaseRecipientAdapter.DirectorySearchParams;
import com.android.ex.chips.DropdownChipLayouter.AdapterType;
import com.android.ex.chips.Queries.Query;

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

/**
 * RecipientAlternatesAdapter backs the RecipientEditTextView for managing contacts
 * queried by email or by phone number.
 */
public class RecipientAlternatesAdapter extends CursorAdapter {
    public static final int MAX_LOOKUPS = 50;

    private final long mCurrentId;

    private int mCheckedItemPosition = -1;

    private OnCheckedItemChangedListener mCheckedItemChangedListener;

    private static final String TAG = "RecipAlternates";

    public static final int QUERY_TYPE_EMAIL = 0;
    public static final int QUERY_TYPE_PHONE = 1;
    private final Long mDirectoryId;
    private DropdownChipLayouter mDropdownChipLayouter;
    private final StateListDrawable mDeleteDrawable;

    private static final Map<String, String> sCorrectedPhotoUris = new HashMap<String, String>();

    public interface RecipientMatchCallback {
        public void matchesFound(Map<String, RecipientEntry> results);
        /**
         * Called with all addresses that could not be resolved to valid recipients.
         */
        public void matchesNotFound(Set<String> unfoundAddresses);
    }

    public static void getMatchingRecipients(Context context, BaseRecipientAdapter adapter,
            ArrayList<String> inAddresses, Account account, RecipientMatchCallback callback) {
        getMatchingRecipients(context, adapter, inAddresses, QUERY_TYPE_EMAIL, account, callback);
    }

    /**
     * Get a HashMap of address to RecipientEntry that contains all contact
     * information for a contact with the provided address, if one exists. This
     * may block the UI, so run it in an async task.
     *
     * @param context Context.
     * @param inAddresses Array of addresses on which to perform the lookup.
     * @param callback RecipientMatchCallback called when a match or matches are found.
     */
    public static void getMatchingRecipients(Context context, BaseRecipientAdapter adapter,
            ArrayList<String> inAddresses, int addressType, Account account,
            RecipientMatchCallback callback) {
        Queries.Query query;
        if (addressType == QUERY_TYPE_EMAIL) {
            query = Queries.EMAIL;
        } else {
            query = Queries.PHONE;
        }
        int addressesSize = Math.min(MAX_LOOKUPS, inAddresses.size());
        HashSet<String> addresses = new HashSet<String>();
        StringBuilder bindString = new StringBuilder();
        // Create the "?" string and set up arguments.
        for (int i = 0; i < addressesSize; i++) {
            Rfc822Token[] tokens = Rfc822Tokenizer.tokenize(inAddresses.get(i).toLowerCase());
            addresses.add(tokens.length > 0 ? tokens[0].getAddress() : inAddresses.get(i));
            bindString.append("?");
            if (i < addressesSize - 1) {
                bindString.append(",");
            }
        }

        if (Log.isLoggable(TAG, Log.DEBUG)) {
            Log.d(TAG, "Doing reverse lookup for " + addresses.toString());
        }

        String[] addressArray = new String[addresses.size()];
        addresses.toArray(addressArray);
        HashMap<String, RecipientEntry> recipientEntries = null;
        Cursor c = null;

        try {
            c = context.getContentResolver().query(
                    query.getContentUri(),
                    query.getProjection(),
                    query.getProjection()[Queries.Query.DESTINATION] + " IN ("
                            + bindString.toString() + ")", addressArray, null);
            recipientEntries = processContactEntries(c, null /* directoryId */);
            callback.matchesFound(recipientEntries);
        } finally {
            if (c != null) {
                c.close();
            }
        }

        final Set<String> matchesNotFound = new HashSet<String>();

        getMatchingRecipientsFromDirectoryQueries(context, recipientEntries,
                addresses, account, matchesNotFound, query, callback);

        getMatchingRecipientsFromExtensionMatcher(adapter, matchesNotFound, callback);
    }

    public static void getMatchingRecipientsFromDirectoryQueries(Context context,
            Map<String, RecipientEntry> recipientEntries, Set<String> addresses,
            Account account, Set<String> matchesNotFound,
            RecipientMatchCallback callback) {
        getMatchingRecipientsFromDirectoryQueries(
                context, recipientEntries, addresses, account,
                matchesNotFound, Queries.EMAIL, callback);
    }

    private static void getMatchingRecipientsFromDirectoryQueries(Context context,
            Map<String, RecipientEntry> recipientEntries, Set<String> addresses,
            Account account, Set<String> matchesNotFound, Queries.Query query,
            RecipientMatchCallback callback) {
        // See if any entries did not resolve; if so, we need to check other
        // directories

        if (recipientEntries.size() < addresses.size()) {
            final List<DirectorySearchParams> paramsList;
            Cursor directoryCursor = null;
            try {
                directoryCursor = context.getContentResolver().query(DirectoryListQuery.URI,
                        DirectoryListQuery.PROJECTION, null, null, null);
                if (directoryCursor == null) {
                    paramsList = null;
                } else {
                    paramsList = BaseRecipientAdapter.setupOtherDirectories(context,
                            directoryCursor, account);
                }
            } finally {
                if (directoryCursor != null) {
                    directoryCursor.close();
                }
            }
            // Run a directory query for each unmatched recipient.
            HashSet<String> unresolvedAddresses = new HashSet<String>();
            for (String address : addresses) {
                if (!recipientEntries.containsKey(address)) {
                    unresolvedAddresses.add(address);
                }
            }

            matchesNotFound.addAll(unresolvedAddresses);

            if (paramsList != null) {
                Cursor directoryContactsCursor = null;
                for (String unresolvedAddress : unresolvedAddresses) {
                    Long directoryId = null;
                    for (int i = 0; i < paramsList.size(); i++) {
                        try {
                            directoryContactsCursor = doQuery(unresolvedAddress, 1,
                                    paramsList.get(i).directoryId, account,
                                    context.getContentResolver(), query);
                        } finally {
                            if (directoryContactsCursor != null
                                    && directoryContactsCursor.getCount() == 0) {
                                directoryContactsCursor.close();
                                directoryContactsCursor = null;
                            } else {
                                directoryId = paramsList.get(i).directoryId;
                                break;
                            }
                        }
                    }
                    if (directoryContactsCursor != null) {
                        try {
                            final Map<String, RecipientEntry> entries =
                                    processContactEntries(directoryContactsCursor, directoryId);

                            for (final String address : entries.keySet()) {
                                matchesNotFound.remove(address);
                            }

                            callback.matchesFound(entries);
                        } finally {
                            directoryContactsCursor.close();
                        }
                    }
                }
            }
        }
    }

    public static void getMatchingRecipientsFromExtensionMatcher(BaseRecipientAdapter adapter,
            Set<String> matchesNotFound, RecipientMatchCallback callback) {
        // If no matches found in contact provider or the directories, try the extension
        // matcher.
        // todo (aalbert): This whole method needs to be in the adapter?
        if (adapter != null) {
            final Map<String, RecipientEntry> entries =
                    adapter.getMatchingRecipients(matchesNotFound);
            if (entries != null && entries.size() > 0) {
                callback.matchesFound(entries);
                for (final String address : entries.keySet()) {
                    matchesNotFound.remove(address);
                }
            }
        }
        callback.matchesNotFound(matchesNotFound);
    }

    private static HashMap<String, RecipientEntry> processContactEntries(Cursor c,
            Long directoryId) {
        HashMap<String, RecipientEntry> recipientEntries = new HashMap<String, RecipientEntry>();
        if (c != null && c.moveToFirst()) {
            do {
                String address = c.getString(Queries.Query.DESTINATION);

                final RecipientEntry newRecipientEntry = RecipientEntry.constructTopLevelEntry(
                        c.getString(Queries.Query.NAME),
                        c.getInt(Queries.Query.DISPLAY_NAME_SOURCE),
                        c.getString(Queries.Query.DESTINATION),
                        c.getInt(Queries.Query.DESTINATION_TYPE),
                        c.getString(Queries.Query.DESTINATION_LABEL),
                        c.getLong(Queries.Query.CONTACT_ID),
                        directoryId,
                        c.getLong(Queries.Query.DATA_ID),
                        c.getString(Queries.Query.PHOTO_THUMBNAIL_URI),
                        true,
                        c.getString(Queries.Query.LOOKUP_KEY));

                /*
                 * In certain situations, we may have two results for one address, where one of the
                 * results is just the email address, and the other has a name and photo, so we want
                 * to use the better one.
                 */
                final RecipientEntry recipientEntry =
                        getBetterRecipient(recipientEntries.get(address), newRecipientEntry);

                recipientEntries.put(address, recipientEntry);
                if (Log.isLoggable(TAG, Log.DEBUG)) {
                    Log.d(TAG, "Received reverse look up information for " + address
                            + " RESULTS: "
                            + " NAME : " + c.getString(Queries.Query.NAME)
                            + " CONTACT ID : " + c.getLong(Queries.Query.CONTACT_ID)
                            + " ADDRESS :" + c.getString(Queries.Query.DESTINATION));
                }
            } while (c.moveToNext());
        }
        return recipientEntries;
    }

    /**
     * Given two {@link RecipientEntry}s for the same email address, this will return the one that
     * contains more complete information for display purposes. Defaults to <code>entry2</code> if
     * no significant differences are found.
     */
    static RecipientEntry getBetterRecipient(final RecipientEntry entry1,
            final RecipientEntry entry2) {
        // If only one has passed in, use it
        if (entry2 == null) {
            return entry1;
        }

        if (entry1 == null) {
            return entry2;
        }

        // If only one has a display name, use it
        if (!TextUtils.isEmpty(entry1.getDisplayName())
                && TextUtils.isEmpty(entry2.getDisplayName())) {
            return entry1;
        }

        if (!TextUtils.isEmpty(entry2.getDisplayName())
                && TextUtils.isEmpty(entry1.getDisplayName())) {
            return entry2;
        }

        // If only one has a display name that is not the same as the destination, use it
        if (!TextUtils.equals(entry1.getDisplayName(), entry1.getDestination())
                && TextUtils.equals(entry2.getDisplayName(), entry2.getDestination())) {
            return entry1;
        }

        if (!TextUtils.equals(entry2.getDisplayName(), entry2.getDestination())
                && TextUtils.equals(entry1.getDisplayName(), entry1.getDestination())) {
            return entry2;
        }

        // If only one has a photo, use it
        if ((entry1.getPhotoThumbnailUri() != null || entry1.getPhotoBytes() != null)
                && (entry2.getPhotoThumbnailUri() == null && entry2.getPhotoBytes() == null)) {
            return entry1;
        }

        if ((entry2.getPhotoThumbnailUri() != null || entry2.getPhotoBytes() != null)
                && (entry1.getPhotoThumbnailUri() == null && entry1.getPhotoBytes() == null)) {
            return entry2;
        }

        // Go with the second option as a default
        return entry2;
    }

    private static Cursor doQuery(CharSequence constraint, int limit, Long directoryId,
            Account account, ContentResolver resolver, Query query) {
        final Uri.Builder builder = query
                .getContentFilterUri()
                .buildUpon()
                .appendPath(constraint.toString())
                .appendQueryParameter(ContactsContract.LIMIT_PARAM_KEY,
                        String.valueOf(limit + BaseRecipientAdapter.ALLOWANCE_FOR_DUPLICATES));
        if (directoryId != null) {
            builder.appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
                    String.valueOf(directoryId));
        }
        if (account != null) {
            builder.appendQueryParameter(BaseRecipientAdapter.PRIMARY_ACCOUNT_NAME, account.name);
            builder.appendQueryParameter(BaseRecipientAdapter.PRIMARY_ACCOUNT_TYPE, account.type);
        }
        final Cursor cursor = resolver.query(builder.build(), query.getProjection(), null, null,
                null);
        return cursor;
    }

    public RecipientAlternatesAdapter(Context context, long contactId, Long directoryId,
            String lookupKey, long currentId, int queryMode, OnCheckedItemChangedListener listener,
            DropdownChipLayouter dropdownChipLayouter) {
        this(context, contactId, directoryId, lookupKey, currentId, queryMode, listener,
                dropdownChipLayouter, null);
    }

    public RecipientAlternatesAdapter(Context context, long contactId, Long directoryId,
            String lookupKey, long currentId, int queryMode, OnCheckedItemChangedListener listener,
            DropdownChipLayouter dropdownChipLayouter, StateListDrawable deleteDrawable) {
        super(context,
                getCursorForConstruction(context, contactId, directoryId, lookupKey, queryMode), 0);
        mCurrentId = currentId;
        mDirectoryId = directoryId;
        mCheckedItemChangedListener = listener;

        mDropdownChipLayouter = dropdownChipLayouter;
        mDeleteDrawable = deleteDrawable;
    }

    private static Cursor getCursorForConstruction(Context context, long contactId,
            Long directoryId, String lookupKey, int queryType) {
        final Cursor cursor;
        final String desiredMimeType;
        if (queryType == QUERY_TYPE_EMAIL) {
            final Uri uri;
            final StringBuilder selection = new StringBuilder();
            selection.append(Queries.EMAIL.getProjection()[Queries.Query.CONTACT_ID]);
            selection.append(" = ?");

            if (directoryId == null || lookupKey == null) {
                uri = Queries.EMAIL.getContentUri();
                desiredMimeType = null;
            } else {
                final Uri.Builder builder = Contacts.getLookupUri(contactId, lookupKey).buildUpon();
                builder.appendPath(Contacts.Entity.CONTENT_DIRECTORY)
                        .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
                                String.valueOf(directoryId));
                uri = builder.build();
                desiredMimeType = ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE;
            }
            cursor = context.getContentResolver().query(
                    uri,
                    Queries.EMAIL.getProjection(),
                    selection.toString(), new String[] {
                        String.valueOf(contactId)
                    }, null);
        } else {
            final Uri uri;
            final StringBuilder selection = new StringBuilder();
            selection.append(Queries.PHONE.getProjection()[Queries.Query.CONTACT_ID]);
            selection.append(" = ?");

            if (lookupKey == null) {
                uri = Queries.PHONE.getContentUri();
                desiredMimeType = null;
            } else {
                final Uri.Builder builder = Contacts.getLookupUri(contactId, lookupKey).buildUpon();
                builder.appendPath(Contacts.Entity.CONTENT_DIRECTORY)
                        .appendQueryParameter(ContactsContract.DIRECTORY_PARAM_KEY,
                                String.valueOf(directoryId));
                uri = builder.build();
                desiredMimeType = ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE;
            }
            cursor = context.getContentResolver().query(
                    uri,
                    Queries.PHONE.getProjection(),
                    selection.toString(), new String[] {
                        String.valueOf(contactId)
                    }, null);
        }

        final Cursor resultCursor = removeUndesiredDestinations(cursor, desiredMimeType, lookupKey);
        cursor.close();

        return resultCursor;
    }

    /**
     * @return a new cursor based on the given cursor with all duplicate destinations removed.
     *
     * It's only intended to use for the alternate list, so...
     * - This method ignores all other fields and dedupe solely on the destination.  Normally,
     * if a cursor contains multiple contacts and they have the same destination, we'd still want
     * to show both.
     * - This method creates a MatrixCursor, so all data will be kept in memory.  We wouldn't want
     * to do this if the original cursor is large, but it's okay here because the alternate list
     * won't be that big.
     *
     * @param desiredMimeType If this is non-<code>null</code>, only entries with this mime type
     *            will be added to the cursor
     * @param lookupKey The lookup key used for this contact if there isn't one in the cursor. This
     *            should be the same one used in the query that returned the cursor
     */
    // Visible for testing
    static Cursor removeUndesiredDestinations(final Cursor original, final String desiredMimeType,
            final String lookupKey) {
        final MatrixCursor result = new MatrixCursor(
                original.getColumnNames(), original.getCount());
        final HashSet<String> destinationsSeen = new HashSet<String>();

        String defaultDisplayName = null;
        String defaultPhotoThumbnailUri = null;
        int defaultDisplayNameSource = 0;

        // Find some nice defaults in case we need them
        original.moveToPosition(-1);
        while (original.moveToNext()) {
            final String mimeType = original.getString(Query.MIME_TYPE);

            if (ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE.equals(
                    mimeType)) {
                // Store this data
                defaultDisplayName = original.getString(Query.NAME);
                defaultPhotoThumbnailUri = original.getString(Query.PHOTO_THUMBNAIL_URI);
                defaultDisplayNameSource = original.getInt(Query.DISPLAY_NAME_SOURCE);
                break;
            }
        }

        original.moveToPosition(-1);
        while (original.moveToNext()) {
            if (desiredMimeType != null) {
                final String mimeType = original.getString(Query.MIME_TYPE);
                if (!desiredMimeType.equals(mimeType)) {
                    continue;
                }
            }
            final String destination = original.getString(Query.DESTINATION);
            if (destinationsSeen.contains(destination)) {
                continue;
            }
            destinationsSeen.add(destination);

            final Object[] row = new Object[] {
                    original.getString(Query.NAME),
                    original.getString(Query.DESTINATION),
                    original.getInt(Query.DESTINATION_TYPE),
                    original.getString(Query.DESTINATION_LABEL),
                    original.getLong(Query.CONTACT_ID),
                    original.getLong(Query.DATA_ID),
                    original.getString(Query.PHOTO_THUMBNAIL_URI),
                    original.getInt(Query.DISPLAY_NAME_SOURCE),
                    original.getString(Query.LOOKUP_KEY),
                    original.getString(Query.MIME_TYPE)
            };

            if (row[Query.NAME] == null) {
                row[Query.NAME] = defaultDisplayName;
            }
            if (row[Query.PHOTO_THUMBNAIL_URI] == null) {
                row[Query.PHOTO_THUMBNAIL_URI] = defaultPhotoThumbnailUri;
            }
            if ((Integer) row[Query.DISPLAY_NAME_SOURCE] == 0) {
                row[Query.DISPLAY_NAME_SOURCE] = defaultDisplayNameSource;
            }
            if (row[Query.LOOKUP_KEY] == null) {
                row[Query.LOOKUP_KEY] = lookupKey;
            }

            // Ensure we don't have two '?' like content://.../...?account_name=...?sz=...
            final String photoThumbnailUri = (String) row[Query.PHOTO_THUMBNAIL_URI];
            if (photoThumbnailUri != null) {
                if (sCorrectedPhotoUris.containsKey(photoThumbnailUri)) {
                    row[Query.PHOTO_THUMBNAIL_URI] = sCorrectedPhotoUris.get(photoThumbnailUri);
                } else if (photoThumbnailUri.indexOf('?') != photoThumbnailUri.lastIndexOf('?')) {
                    final String[] parts = photoThumbnailUri.split("\\?");
                    final StringBuilder correctedUriBuilder = new StringBuilder();
                    for (int i = 0; i < parts.length; i++) {
                        if (i == 1) {
                            correctedUriBuilder.append("?"); // We only want one of these
                        } else if (i > 1) {
                            correctedUriBuilder.append("&"); // And we want these elsewhere
                        }
                        correctedUriBuilder.append(parts[i]);
                    }

                    final String correctedUri = correctedUriBuilder.toString();
                    sCorrectedPhotoUris.put(photoThumbnailUri, correctedUri);
                    row[Query.PHOTO_THUMBNAIL_URI] = correctedUri;
                }
            }

            result.addRow(row);
        }

        return result;
    }

    @Override
    public long getItemId(int position) {
        Cursor c = getCursor();
        if (c.moveToPosition(position)) {
            c.getLong(Queries.Query.DATA_ID);
        }
        return -1;
    }

    public RecipientEntry getRecipientEntry(int position) {
        Cursor c = getCursor();
        c.moveToPosition(position);
        return RecipientEntry.constructTopLevelEntry(
                c.getString(Queries.Query.NAME),
                c.getInt(Queries.Query.DISPLAY_NAME_SOURCE),
                c.getString(Queries.Query.DESTINATION),
                c.getInt(Queries.Query.DESTINATION_TYPE),
                c.getString(Queries.Query.DESTINATION_LABEL),
                c.getLong(Queries.Query.CONTACT_ID),
                mDirectoryId,
                c.getLong(Queries.Query.DATA_ID),
                c.getString(Queries.Query.PHOTO_THUMBNAIL_URI),
                true,
                c.getString(Queries.Query.LOOKUP_KEY));
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Cursor cursor = getCursor();
        cursor.moveToPosition(position);
        if (convertView == null) {
            convertView = mDropdownChipLayouter.newView(AdapterType.RECIPIENT_ALTERNATES);
        }
        if (cursor.getLong(Queries.Query.DATA_ID) == mCurrentId) {
            mCheckedItemPosition = position;
            if (mCheckedItemChangedListener != null) {
                mCheckedItemChangedListener.onCheckedItemChanged(mCheckedItemPosition);
            }
        }
        bindView(convertView, convertView.getContext(), cursor);
        return convertView;
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        int position = cursor.getPosition();
        RecipientEntry entry = getRecipientEntry(position);

        mDropdownChipLayouter.bindView(view, null, entry, position,
                AdapterType.RECIPIENT_ALTERNATES, null, mDeleteDrawable);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        return mDropdownChipLayouter.newView(AdapterType.RECIPIENT_ALTERNATES);
    }

    /*package*/ static interface OnCheckedItemChangedListener {
        public void onCheckedItemChanged(int position);
    }
}
