Show all merged accounts in Contact editor.

Show all merged rawContacts' accounts in Contact editor, not
just primary account.
Expand all accounts to a list.
Clicking each account (rawContact) will go to the full editor
to editor the rawContact.

BUG 24547289

Change-Id: I671a946f87b25d9393daccb600287e35826fa6eb
diff --git a/src/com/android/contacts/editor/CompactRawContactsEditorView.java b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
index 090ea31..f808d4d 100644
--- a/src/com/android/contacts/editor/CompactRawContactsEditorView.java
+++ b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
@@ -31,12 +31,16 @@
 import com.android.contacts.util.ContactPhotoUtils;
 import com.android.contacts.util.UiClosables;
 
+import android.content.ContentUris;
+import android.content.ContentValues;
 import android.content.Context;
+import android.content.Intent;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.net.Uri;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.provider.ContactsContract;
 import android.provider.ContactsContract.CommonDataKinds.Email;
 import android.provider.ContactsContract.CommonDataKinds.Event;
 import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
@@ -59,6 +63,8 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.ImageView;
 import android.widget.LinearLayout;
 import android.widget.ListPopupWindow;
 import android.widget.TextView;
@@ -70,9 +76,11 @@
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 import java.util.TreeSet;
 
 /**
@@ -117,6 +125,70 @@
          * Invoked after editors have been bound for the contact.
          */
         public void onEditorsBound();
+
+        /**
+         * Invoked when a rawcontact from merged contacts is selected in editor.
+         */
+        public void onRawContactSelected(Uri uri, long rawContactId);
+    }
+
+    /**
+     * Used to list the account info for the given raw contacts list.
+     */
+    private static final class RawContactAccountListAdapter extends BaseAdapter {
+        private final LayoutInflater mInflater;
+        private final Context mContext;
+        private final RawContactDeltaList mRawContactDeltas;
+
+        public RawContactAccountListAdapter(Context context, RawContactDeltaList rawContactDeltas) {
+            mContext = context;
+            mRawContactDeltas = new RawContactDeltaList();
+            for (RawContactDelta rawContactDelta : rawContactDeltas) {
+                if (rawContactDelta.isVisible()) {
+                    mRawContactDeltas.add(rawContactDelta);
+                }
+            }
+            mInflater = LayoutInflater.from(context);
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            final View resultView = convertView != null ? convertView
+                    : mInflater.inflate(R.layout.account_selector_list_item, parent, false);
+
+            final RawContactDelta rawContactDelta = mRawContactDeltas.get(position);
+            final String accountName = rawContactDelta.getAccountName();
+            final AccountType accountType = rawContactDelta.getRawContactAccountType(mContext);
+
+            final TextView text1 = (TextView) resultView.findViewById(android.R.id.text1);
+            text1.setText(accountType.getDisplayLabel(mContext));
+
+            // For email addresses, we don't want to truncate at end, which might cut off the domain
+            // name.
+            final TextView text2 = (TextView) resultView.findViewById(android.R.id.text2);
+            text2.setText(accountName);
+            text2.setEllipsize(TextUtils.TruncateAt.MIDDLE);
+
+            final ImageView icon = (ImageView) resultView.findViewById(android.R.id.icon);
+            icon.setImageDrawable(accountType.getDisplayIcon(mContext));
+
+            return resultView;
+        }
+
+        @Override
+        public int getCount() {
+            return mRawContactDeltas.size();
+        }
+
+        @Override
+        public RawContactDelta getItem(int position) {
+            return mRawContactDeltas.get(position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return getItem(position).getRawContactId();
+        }
     }
 
     /** Used to sort entire kind sections. */
@@ -317,6 +389,11 @@
     private TextView mAccountSelectorType;
     private TextView mAccountSelectorName;
 
+    // Raw contacts selector
+    private View mRawContactContainer;
+    private TextView mRawContactSummary;
+    private ImageView mPrimaryAccountIcon;
+
     private CompactPhotoEditorView mPhotoView;
     private ViewGroup mKindSectionViews;
     private Map<String,List<CompactKindSectionView>> mKindSectionViewsMap = new HashMap<>();
@@ -360,6 +437,11 @@
         mAccountSelectorType = (TextView) findViewById(R.id.account_type_selector);
         mAccountSelectorName = (TextView) findViewById(R.id.account_name_selector);
 
+        // Raw contacts selector
+        mRawContactContainer = findViewById(R.id.all_rawcontacts_accounts_container);
+        mRawContactSummary = (TextView) findViewById(R.id.rawcontacts_accounts_summary);
+        mPrimaryAccountIcon = (ImageView) findViewById(R.id.primary_account_icon);
+
         mPhotoView = (CompactPhotoEditorView) findViewById(R.id.photo_editor);
         mKindSectionViews = (LinearLayout) findViewById(R.id.kind_section_views);
         mMoreFields = findViewById(R.id.more_fields);
@@ -586,7 +668,7 @@
         }
 
         // Setup the view
-        addAccountInfo();
+        addAccountInfo(rawContactDeltas);
         addPhotoView();
         addKindSectionViews();
 
@@ -699,7 +781,7 @@
                 && Objects.equals(accountWithDataSet.dataSet, rawContactDelta.getDataSet());
     }
 
-    private void addAccountInfo() {
+    private void addAccountInfo(RawContactDeltaList rawContactDeltas) {
         if (mPrimaryRawContactDelta == null) {
             mAccountHeaderContainer.setVisibility(View.GONE);
             mAccountSelectorContainer.setVisibility(View.GONE);
@@ -715,9 +797,17 @@
         // at the same time
         final List<AccountWithDataSet> accounts =
                 AccountTypeManager.getInstance(getContext()).getAccounts(true);
+        mRawContactContainer.setVisibility(View.GONE);
         if (mHasNewContact && !mIsUserProfile && accounts.size() > 1) {
             mAccountHeaderContainer.setVisibility(View.GONE);
             addAccountSelector(accountInfo);
+        } else if (mHasNewContact && !mIsUserProfile) {
+            addAccountHeader(accountInfo);
+            mAccountSelectorContainer.setVisibility(View.GONE);
+        } else if (rawContactDeltas.size() > 1) {
+            mAccountHeaderContainer.setVisibility(View.GONE);
+            mAccountSelectorContainer.setVisibility(View.GONE);
+            addRawContactAccountSelector(rawContactDeltas);
         } else {
             addAccountHeader(accountInfo);
             mAccountSelectorContainer.setVisibility(View.GONE);
@@ -787,6 +877,88 @@
         });
     }
 
+    private void addRawContactAccountSelector(final RawContactDeltaList rawContactDeltas) {
+        mRawContactContainer.setVisibility(View.VISIBLE);
+
+        final String accountsSummary = getRawContactsAccountsSummary(
+                getContext(), rawContactDeltas);
+        mRawContactSummary.setText(accountsSummary);
+        mRawContactContainer.setContentDescription(accountsSummary);
+        if (mPrimaryRawContactDelta != null) {
+            final AccountType primaryAccountType = mPrimaryRawContactDelta.getRawContactAccountType(
+                    getContext());
+            mPrimaryAccountIcon.setImageDrawable(primaryAccountType.getDisplayIcon(getContext()));
+        }
+
+        mRawContactContainer.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                final ListPopupWindow popup = new ListPopupWindow(getContext(), null);
+                final RawContactAccountListAdapter adapter =
+                        new RawContactAccountListAdapter(getContext(), rawContactDeltas);
+                popup.setWidth(mRawContactContainer.getWidth());
+                popup.setAnchorView(mRawContactContainer);
+                popup.setAdapter(adapter);
+                popup.setModal(true);
+                popup.setInputMethodMode(ListPopupWindow.INPUT_METHOD_NOT_NEEDED);
+                popup.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+                    @Override
+                    public void onItemClick(AdapterView<?> parent, View view, int position,
+                                            long id) {
+                        UiClosables.closeQuietly(popup);
+                        final RawContactDelta rawContactDelta = adapter.getItem(position);
+                        final long rawContactId = adapter.getItemId(position);
+                        final Uri rawContactUri = ContentUris.withAppendedId(
+                                ContactsContract.RawContacts.CONTENT_URI, rawContactId);
+                        // Start new activity for the raw contact in selected account.
+                        final Intent intent = new Intent(Intent.ACTION_INSERT_OR_EDIT);
+                        intent.setType(ContactsContract.Contacts.CONTENT_ITEM_TYPE);
+
+                        ArrayList<ContentValues> values = rawContactDelta.getContentValues();
+                        intent.putExtra(ContactsContract.Intents.Insert.DATA, values);
+
+                        if (mListener != null) {
+                            mListener.onRawContactSelected(rawContactUri, rawContactId);
+                        }
+                    }
+                });
+                popup.show();
+            }
+        });
+    }
+
+    private static String getRawContactsAccountsSummary(
+            Context context, RawContactDeltaList rawContactDeltas) {
+        final Map<String, Integer> accountTypeNumber = new HashMap<>();
+        for (RawContactDelta rawContactDelta : rawContactDeltas) {
+            if (rawContactDelta.isVisible()) {
+                final AccountType accountType = rawContactDelta.getRawContactAccountType(context);
+                final String accountTypeLabel = accountType.getDisplayLabel(context).toString();
+                if (accountTypeNumber.containsKey(accountTypeLabel)) {
+                    int number = accountTypeNumber.get(accountTypeLabel);
+                    number++;
+                    accountTypeNumber.put(accountTypeLabel, number);
+                } else {
+                    accountTypeNumber.put(accountTypeLabel, 1);
+                }
+            }
+        }
+
+        final Set<String> linkedAccounts = new HashSet<>();
+        for (String accountTypeLabel : accountTypeNumber.keySet()) {
+            final String number = context.getResources().getQuantityString(
+                    R.plurals.quickcontact_suggestion_account_type_number,
+                    accountTypeNumber.get(accountTypeLabel),
+                    accountTypeNumber.get(accountTypeLabel));
+            final String accountWithNumber = context.getResources().getString(
+                    R.string.quickcontact_suggestion_account_type,
+                    accountTypeLabel,
+                    number);
+            linkedAccounts.add(accountWithNumber);
+        }
+        return TextUtils.join(",", linkedAccounts);
+    }
+
     private void addPhotoView() {
         // Get the kind section data and values delta that we will display in the photo view
         Pair<KindSectionData,ValuesDelta> pair = getPrimaryPhotoKindSectionData(mPhotoId);