package com.github.yeriomin.dumbphoneassistant;

import android.annotation.TargetApi;
import android.app.Activity;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.PhoneLookup;
import android.text.TextUtils;
import android.util.Log;

import java.util.ArrayList;
import java.util.Arrays;

@TargetApi(5)
public class PhoneUtilEclair extends PhoneUtil {

    private static final String[] simTypes = new String[] {
            "com.android.contacts.sim",
            "com.anddroid.contacts.sim", // HTC
            "com.sonyericsson.adncontacts", // Sony
            "vnd.sec.contact.sim",
            "USIM Account",
    };

    public PhoneUtilEclair(Activity activity) {
        super(activity);
    }

    public ArrayList<Contact> get() {
        Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
        String[] projection = new String[] {
                PhoneLookup._ID,
                PhoneLookup.DISPLAY_NAME,
                ContactsContract.CommonDataKinds.Phone.TYPE,
                ContactsContract.CommonDataKinds.Phone.LABEL,
                ContactsContract.CommonDataKinds.Phone.NUMBER
        };
        String[] simTypesQueryParts = new String[simTypes.length];
        Arrays.fill(simTypesQueryParts, ContactsContract.RawContacts.ACCOUNT_TYPE + " <> ?");
        String simTypesQuery = TextUtils.join(" AND ", simTypesQueryParts);
        String selection = ContactsContract.RawContacts.ACCOUNT_TYPE + " IS NULL OR (" + simTypesQuery + ")";
        String[] selectionArgs = simTypes;

        Cursor results = resolver.query(
                uri,
                projection,
                selection,
                selectionArgs,
                null
        );

        // create array of Phone contacts and fill it
        final ArrayList<Contact> phoneContacts = new ArrayList<>();
        int indexId = results.getColumnIndex(PhoneLookup._ID);
        int indexName = results.getColumnIndex(PhoneLookup.DISPLAY_NAME);
        int indexType = results.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE);
        int indexLabel = results.getColumnIndex(ContactsContract.CommonDataKinds.Phone.LABEL);
        int indexNumber = results.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
        while (results.moveToNext()) {
            int type = results.getInt(indexType);
            String custom = results.getString(indexLabel);
            final Contact phoneContact = new Contact(
                    results.getString(indexId),
                    results.getString(indexName),
                    results.getString(indexNumber),
                    (String) Phone.getTypeLabel(this.activity.getResources(), type, custom)
            );
            phoneContacts.add(phoneContact);
        }
        results.close();
        return phoneContacts;
    }

    public void create(Contact contact) throws Exception {
        String name = contact.getName();
        // Prevents previously placed phone type suffixes from being interpreted as part of the name
        if (name.charAt(name.length() - 2) == ',') {
            name = name.substring(0, name.length() - 2);
            contact.setName(name);
        }

        ArrayList<ContentProviderOperation> ops = new ArrayList<>();
        ops.add(ContentProviderOperation
                .newInsert(ContactsContract.RawContacts.CONTENT_URI)
                .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
                .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
                .build()
        );
        ops.add(ContentProviderOperation
                .newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Contacts.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, contact.getName())
                .build()
        );
        ops.add(ContentProviderOperation
                .newInsert(ContactsContract.Data.CONTENT_URI)
                .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
                .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
                .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, contact.getNumber())
                .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE)
                .build()
        );

        ContentProviderResult[] results;
        try {
            results = resolver.applyBatch(ContactsContract.AUTHORITY, ops);
        } catch (Exception e) {
            throw new Exception(String.valueOf(R.string.error_phone_number_error));
        }

        if (results.length > 2) {
            Uri uri = results[2].uri;
            // if contacts uri returned, there was an error with adding the number
            if (uri.getPath().contains("people")) {
                throw new Exception(String.valueOf(R.string.error_phone_number_not_stored));
            }
            contact.setId(uri.getLastPathSegment());
        }
    }

    public Uri retrieveContactUri(Contact contact) {
        String lookupKey;
        Long contactId;
        Cursor result = null;
        Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI;
        String[] projection = new String[] { ContactsContract.Contacts.LOOKUP_KEY, ContactsContract.RawContacts.CONTACT_ID };
        String selection;
        String[] selectionArgs;

        // at first try to resolve with contacts id
        if (contact.getId() != null) {
            selection = PhoneLookup._ID + "=?";
            selectionArgs = new String[] { contact.getId() };
            result = resolver.query(uri, projection, selection, selectionArgs, null);
            // check if unique result
            if (result.getCount() != 1) {
                result.close();
                result = null;
            }
        }
        
        // if no contact id or no result, try alternate method
        if (result == null) {
            selection = ContactsContract.Contacts.DISPLAY_NAME + " = '?' AND "
                    + ContactsContract.CommonDataKinds.Phone.NUMBER + " = '?'"
            ;
            selectionArgs = new String[] { contact.getName(), contact.getNumber() };
            result = resolver.query(uri, projection, selection, selectionArgs, null);
            // check if unique result
            if (result.getCount() != 1) {
                result.close();
                result = null;
            }
        }
                
        // check for result
        if (result == null) {
            return null;
        }
        
        // get results
        result.moveToNext();
        lookupKey = result.getString(0);
        contactId = result.getLong(1);
        result.close();

        // create contact URI
        return ContactsContract.Contacts.getLookupUri(contactId, lookupKey);
    }
}