package com.alexstyl.specialdates.contact;

import android.content.ContentResolver;
import android.database.Cursor;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;

import com.alexstyl.specialdates.DisplayName;

import static com.alexstyl.specialdates.contact.ContactsQuery.SORT_ORDER;

class DeviceContactFactory {

    private static final String SELECTION_CONTACT_WITH_ID = ContactsContract.Data.CONTACT_ID + " = ? AND " + ContactsContract.Data.MIMETYPE + " = ?";
    private final ContentResolver resolver;

    DeviceContactFactory(ContentResolver contentResolver) {
        resolver = contentResolver;
    }

    Contact createContactWithId(long contactID) throws ContactNotFoundException {
        Cursor cursor = queryContactsWithContactId(contactID);
        if (isInvalid(cursor)) {
            throw new RuntimeException("Cursor was invalid");
        }
        try {
            if (cursor.moveToFirst()) {
                return createContactFrom(cursor);
            }
        } finally {
            cursor.close();
        }
        throw new ContactNotFoundException(contactID);
    }

    public Contact createContactFrom(Cursor cursor) {
        long contactID = getContactIdFrom(cursor);
        DisplayName displayName = getDisplayNameFrom(cursor);
        String lookupKey = getLookupKeyFrom(cursor);
        return new DeviceContact(contactID, displayName, lookupKey);
    }

    private Cursor queryContactsWithContactId(long contactID) {
        return resolver.query(
                ContactsQuery.CONTENT_URI,
                ContactsQuery.PROJECTION,
                SELECTION_CONTACT_WITH_ID,
                new String[]{
                        String.valueOf(contactID),
                        StructuredName.CONTENT_ITEM_TYPE
                },
                SORT_ORDER + " LIMIT 1"
        );
    }

    private static boolean isInvalid(Cursor cursor) {
        return cursor == null || cursor.isClosed();
    }

    private static long getContactIdFrom(Cursor cursor) {
        return cursor.getLong(ContactsQuery.CONTACT_ID);
    }

    private static DisplayName getDisplayNameFrom(Cursor cursor) {
        return DisplayName.from(cursor.getString(ContactsQuery.DISPLAY_NAME));
    }

    private static String getLookupKeyFrom(Cursor cursor) {
        return cursor.getString(ContactsQuery.LOOKUP_KEY);
    }

}

@@ -149,16 +149,25 @@
 Contract
+.Contacts
 ;%0Aimport
@@ -179,64 +179,34 @@
 oid.
-provider.ContactsContract.CommonDataKinds.StructuredName
+support.annotation.NonNull
 ;%0A%0Ai
@@ -428,79 +428,12 @@
 acts
-Contract.Data.CONTACT_ID + %22 = ? AND %22 + ContactsContract.Data.MIMETYPE
+._ID
  + %22
@@ -1614,85 +1614,94 @@
     
-new String%5B%5D%7B%0A                        String.valueOf(contactID),%0A    
+makeSelectionArgumentsFor(contactID),%0A                SORT_ORDER + %22 LIMIT 1%22%0A
         
     
@@ -1700,111 +1700,166 @@
     
+);%0A
     
+%7D%0A%0A
     
-    StructuredName.CONTENT_ITEM_TYPE%0A                %7D,%0A                SORT_ORDER + %22 LIMIT 1%22
+@NonNull%0A    private String%5B%5D makeSelectionArgumentsFor(long contactID) %7B%0A        return new String%5B%5D%7B%0A                String.valueOf(contactID)
 %0A   
@@ -1855,33 +1855,33 @@
 tactID)%0A        
-)
+%7D
 ;%0A    %7D%0A%0A    pri

Query the correct Contact ID