/*
 * 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 (directoryId == null || 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);
    }
}
