Change editor raw contact selector to open the compact editor

* Whe editing more than one raw contact, just show the
  raw contact selector with no input fields.
  Eventually we'll be displaying the raw contacts in
  a list instead of a drop down.
* When a raw contact selector item is clicked, open
  the compact editor instead of the full one.
* We do the same trickery that the full editor does
  to render a single raw contact -- even though
  ContactLoader loads the aggregate, we pass along
  the raw contact ID in the Intent to start the compact
  editor and ignore all the other raw contacts in the
   RawContactDeltaList.
* The compact editor is updated to be able to render
  read-only raw contacts.

Test: Tested the following editor scenarios:
  1) new contact
  2) edit writable raw contact
  3) edit read-only raw contact (joins a new writable raw contact to it)
  4) edit aggregate w/ 1 writable and 1 read-only raw contact
  5) edit aggregate w/ 2 writable raw contacts
  6) edit local me raw contact
  7) edit local me raw contact joined with a read-only raw contact

Bug: 31088704

Change-Id: I86a7fde976af8b318c7fb3da4f74f29f08a69eef
diff --git a/src/com/android/contacts/editor/CompactRawContactsEditorView.java b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
index ece3829..d023d35 100644
--- a/src/com/android/contacts/editor/CompactRawContactsEditorView.java
+++ b/src/com/android/contacts/editor/CompactRawContactsEditorView.java
@@ -327,6 +327,10 @@
     private boolean mHasNewContact;
     private boolean mIsUserProfile;
     private AccountWithDataSet mPrimaryAccount;
+    private RawContactDeltaList mRawContactDeltas;
+    private long mRawContactIdToDisplayAlone = -1;
+    private boolean mRawContactDisplayAloneIsReadOnly;
+    private boolean mIsEditingReadOnlyRawContactWithNewContact;
     private Map<String,KindSectionDataList> mKindSectionDataMap = new HashMap<>();
 
     // Account header
@@ -621,7 +625,14 @@
     public void setState(RawContactDeltaList rawContactDeltas,
             MaterialColorMapUtils.MaterialPalette materialPalette, ViewIdGenerator viewIdGenerator,
             long photoId, boolean hasNewContact, boolean isUserProfile,
-            AccountWithDataSet primaryAccount) {
+            AccountWithDataSet primaryAccount, long rawContactIdToDisplayAlone,
+            boolean rawContactDisplayAloneIsReadOnly,
+            boolean isEditingReadOnlyRawContactWithNewContact) {
+        mRawContactDeltas = rawContactDeltas;
+        mRawContactIdToDisplayAlone = rawContactIdToDisplayAlone;
+        mRawContactDisplayAloneIsReadOnly = rawContactDisplayAloneIsReadOnly;
+        mIsEditingReadOnlyRawContactWithNewContact = isEditingReadOnlyRawContactWithNewContact;
+
         mKindSectionDataMap.clear();
         mKindSectionViews.removeAllViews();
         mMoreFields.setVisibility(View.VISIBLE);
@@ -669,15 +680,48 @@
         }
 
         // Setup the view
-        addAccountInfo(rawContactDeltas);
         addPhotoView();
-        addKindSectionViews();
+        if (isSingleReadOnlyRawContact()) {
+            // We're want to display the inputs fields for a single read only raw contact
+            addReadOnlyRawContactEditorViews();
+            // Hide the "More fields" link
+            mMoreFields.setVisibility(View.GONE);
+        } else if (mIsEditingReadOnlyRawContactWithNewContact) {
+            // A new writable raw contact was created and joined with the read only contact
+            // that the user is trying to edit.
+            setupCompactEditorNormally();
 
-        if (mIsExpanded) showAllFields();
+            // TODO: Hide the raw contact selector since it will just contain the read-only raw
+            // contact and clicking that will just open the exact same editor.  When we clean up
+            // the whole account header, selector, and raw contact selector mess, we can prevent
+            // the selector from being displayed in a less hacky way.
+            mRawContactContainer.setVisibility(View.GONE);
+        } else if (mRawContactDeltas.size() > 1) {
+            // We're editing an aggregate composed of more than one writable raw contacts
 
+            // TODO: Don't render any input fields. Eventually we will show a list of account
+            // types and names but for now just show the account selector and hide the "More fields"
+            // link.
+            addAccountInfo(rawContactDeltas);
+            mMoreFields.setVisibility(View.GONE);
+        } else {
+            setupCompactEditorNormally();
+        }
         if (mListener != null) mListener.onEditorsBound();
     }
 
+    private void setupCompactEditorNormally() {
+        addAccountInfo(mRawContactDeltas);
+        addKindSectionViews();
+        if (mIsExpanded) showAllFields();
+    }
+
+    private boolean isSingleReadOnlyRawContact() {
+        return mRawContactDeltas.size() == 1
+                && mRawContactDeltas.get(0).getRawContactId() == mRawContactIdToDisplayAlone
+                && mRawContactDisplayAloneIsReadOnly;
+    }
+
     private void parseRawContactDeltas(RawContactDeltaList rawContactDeltas) {
         // Build the kind section data list map
         vlog("parse: " + rawContactDeltas.size() + " rawContactDelta(s)");
@@ -692,8 +736,8 @@
             vlog("parse: " + dataKindSize + " dataKinds(s)");
             for (int i = 0; i < dataKindSize; i++) {
                 final DataKind dataKind = dataKinds.get(i);
-                if (dataKind == null || !dataKind.editable) {
-                    vlog("parse: " + i + " " + dataKind.mimeType + " dropped read-only");
+                if (dataKind == null) {
+                    vlog("parse: " + i + " " + dataKind.mimeType + " dropped null data kind");
                     continue;
                 }
                 final String mimeType = dataKind.mimeType;
@@ -729,6 +773,27 @@
         return kindSectionDataList;
     }
 
+    private void addReadOnlyRawContactEditorViews() {
+        final LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(
+                Context.LAYOUT_INFLATER_SERVICE);
+        final AccountTypeManager accountTypes = AccountTypeManager.getInstance(
+                getContext());
+
+        for (int i = 0; i < mRawContactDeltas.size(); i++) {
+            final RawContactDelta rawContactDelta = mRawContactDeltas.get(i);
+            if (!rawContactDelta.isVisible()) continue;
+            final AccountType type = rawContactDelta.getAccountType(accountTypes);
+            if (type.areContactsWritable()) continue;
+
+            final BaseRawContactEditorView editor = (BaseRawContactEditorView) inflater.inflate(
+                        R.layout.raw_contact_readonly_editor_view, mKindSectionViews, false);
+            editor.setCollapsed(false);
+            mKindSectionViews.addView(editor);
+            editor.setState(rawContactDelta, type, mViewIdGenerator, mIsUserProfile);
+        }
+    }
+
+    // TODO: we have mRawContactDeltas, we don't need to pass the RawContactDeltaList to this method
     private void addAccountInfo(RawContactDeltaList rawContactDeltas) {
         mAccountHeaderContainer.setVisibility(View.GONE);
         mAccountSelectorContainer.setVisibility(View.GONE);