package com.android.exchange.eas;

import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Entity;
import android.content.EntityIterator;
import android.database.Cursor;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Email;
import android.provider.ContactsContract.CommonDataKinds.Event;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.CommonDataKinds.Im;
import android.provider.ContactsContract.CommonDataKinds.Nickname;
import android.provider.ContactsContract.CommonDataKinds.Note;
import android.provider.ContactsContract.CommonDataKinds.Organization;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.provider.ContactsContract.CommonDataKinds.Photo;
import android.provider.ContactsContract.CommonDataKinds.Relation;
import android.provider.ContactsContract.CommonDataKinds.StructuredName;
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.CommonDataKinds.Website;
import android.provider.ContactsContract.Groups;
import android.text.TextUtils;
import android.util.Base64;

import com.android.emailcommon.TrafficFlags;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.Mailbox;
import com.android.exchange.Eas;
import com.android.exchange.adapter.AbstractSyncParser;
import com.android.exchange.adapter.ContactsSyncParser;
import com.android.exchange.adapter.Serializer;
import com.android.exchange.adapter.Tags;
import com.android.mail.utils.LogUtils;

import java.io.IOException;
import java.io.InputStream;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;

/**
 * Performs an Exchange sync for contacts.
 * Contact state is in the contacts provider, not in our DB (and therefore not in e.g. mMailbox).
 * The Mailbox in the Email DB is only useful for serverId and syncInterval.
 */
public class EasSyncContacts extends EasSyncCollectionTypeBase {
    private static final String TAG = Eas.LOG_TAG;

    public static final int PIM_WINDOW_SIZE_CONTACTS = 10;

    private static final String MIMETYPE_GROUP_MEMBERSHIP_AND_ID_EQUALS =
            ContactsContract.Data.MIMETYPE + "='" + GroupMembership.CONTENT_ITEM_TYPE + "' AND " +
                    GroupMembership.GROUP_ROW_ID + "=?";

    private static final String[] GROUP_TITLE_PROJECTION =
            new String[] {Groups.TITLE};
    private static final String[] GROUPS_ID_PROJECTION = new String[] {Groups._ID};

    /** The maximum number of IMs we can send for one contact. */
    private static final int MAX_IM_ROWS = 3;
    /** The tags to use for IMs in an upsync. */
    private static final int[] IM_TAGS = new int[] {Tags.CONTACTS2_IM_ADDRESS,
            Tags.CONTACTS2_IM_ADDRESS_2, Tags.CONTACTS2_IM_ADDRESS_3};

    /** The maximum number of email addresses we can send for one contact. */
    private static final int MAX_EMAIL_ROWS = 3;
    /** The tags to use for the emails in an upsync. */
    private static final int[] EMAIL_TAGS = new int[] {Tags.CONTACTS_EMAIL1_ADDRESS,
            Tags.CONTACTS_EMAIL2_ADDRESS, Tags.CONTACTS_EMAIL3_ADDRESS};

    /** The maximum number of phone numbers of each type we can send for one contact. */
    private static final int MAX_PHONE_ROWS = 2;
    /** The tags to use for work phone numbers. */
    private static final int[] WORK_PHONE_TAGS = new int[] {Tags.CONTACTS_BUSINESS_TELEPHONE_NUMBER,
            Tags.CONTACTS_BUSINESS2_TELEPHONE_NUMBER};
    /** The tags to use for home phone numbers. */
    private static final int[] HOME_PHONE_TAGS = new int[] {Tags.CONTACTS_HOME_TELEPHONE_NUMBER,
            Tags.CONTACTS_HOME2_TELEPHONE_NUMBER};

    /** The tags to use for different parts of a home address. */
    private static final int[] HOME_ADDRESS_TAGS = new int[] {Tags.CONTACTS_HOME_ADDRESS_CITY,
            Tags.CONTACTS_HOME_ADDRESS_COUNTRY,
            Tags.CONTACTS_HOME_ADDRESS_POSTAL_CODE,
            Tags.CONTACTS_HOME_ADDRESS_STATE,
            Tags.CONTACTS_HOME_ADDRESS_STREET};

    /** The tags to use for different parts of a work address. */
    private static final int[] WORK_ADDRESS_TAGS = new int[] {Tags.CONTACTS_BUSINESS_ADDRESS_CITY,
            Tags.CONTACTS_BUSINESS_ADDRESS_COUNTRY,
            Tags.CONTACTS_BUSINESS_ADDRESS_POSTAL_CODE,
            Tags.CONTACTS_BUSINESS_ADDRESS_STATE,
            Tags.CONTACTS_BUSINESS_ADDRESS_STREET};

    /** The tags to use for different parts of an "other" address. */
    private static final int[] OTHER_ADDRESS_TAGS = new int[] {Tags.CONTACTS_HOME_ADDRESS_CITY,
            Tags.CONTACTS_OTHER_ADDRESS_COUNTRY,
            Tags.CONTACTS_OTHER_ADDRESS_POSTAL_CODE,
            Tags.CONTACTS_OTHER_ADDRESS_STATE,
            Tags.CONTACTS_OTHER_ADDRESS_STREET};

    private final android.accounts.Account mAccountManagerAccount;

    private final ArrayList<Long> mDeletedContacts = new ArrayList<Long>();
    private final ArrayList<Long> mUpdatedContacts = new ArrayList<Long>();

    // We store the parser so that we can ask it later isGroupsUsed.
    // TODO: Can we do this more cleanly?
    private ContactsSyncParser mParser = null;

    private static final class EasChildren {
        private EasChildren() {}

        /** MIME type used when storing this in data table. */
        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/eas_children";
        public static final int MAX_CHILDREN = 8;
        public static final String[] ROWS =
            new String[] {"data2", "data3", "data4", "data5", "data6", "data7", "data8", "data9"};
    }

    // Classes for each type of contact.
    // These are copied from ContactSyncAdapter, with unused fields and methods removed, but the
    // parser hasn't been moved over yet. When that happens, the variables and functions may also
    // need to be copied over.

    /**
     * Data and constants for a Personal contact.
     */
    private static final class EasPersonal {
            /** MIME type used when storing this in data table. */
        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/eas_personal";
        public static final String ANNIVERSARY = "data2";
        public static final String FILE_AS = "data4";
    }

    /**
     * Data and constants for a Business contact.
     */
    private static final class EasBusiness {
        /** MIME type used when storing this in data table. */
        public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/eas_business";
        public static final String CUSTOMER_ID = "data6";
        public static final String GOVERNMENT_ID = "data7";
        public static final String ACCOUNT_NAME = "data8";
    }

    public EasSyncContacts(final String emailAddress) {
        mAccountManagerAccount = new android.accounts.Account(emailAddress,
                Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE);
    }

    @Override
    public int getTrafficFlag() {
        return TrafficFlags.DATA_CONTACTS;
    }

    @Override
    public void setSyncOptions(final Context context, final Serializer s,
            final double protocolVersion, final Account account, final Mailbox mailbox,
            final boolean isInitialSync, final int numWindows) throws IOException {
        if (isInitialSync) {
            setInitialSyncOptions(s);
            return;
        }

        final int windowSize = numWindows * PIM_WINDOW_SIZE_CONTACTS;
        if (windowSize > MAX_WINDOW_SIZE  + PIM_WINDOW_SIZE_CONTACTS) {
            throw new IOException("Max window size reached and still no data");
        }
        setPimSyncOptions(s, null, protocolVersion,
                windowSize < MAX_WINDOW_SIZE ? windowSize : MAX_WINDOW_SIZE);

        setUpsyncCommands(s, context.getContentResolver(), account, mailbox, protocolVersion);
    }

    @Override
    public AbstractSyncParser getParser(final Context context, final Account account,
            final Mailbox mailbox, final InputStream is) throws IOException {
        mParser = new ContactsSyncParser(context, context.getContentResolver(), is, mailbox,
                account, mAccountManagerAccount);
        return mParser;
    }

    private void setInitialSyncOptions(final Serializer s) throws IOException {
        // These are the tags we support for upload; whenever we add/remove support
        // (in addData), we need to update this list
        s.start(Tags.SYNC_SUPPORTED);
        s.tag(Tags.CONTACTS_FIRST_NAME);
        s.tag(Tags.CONTACTS_LAST_NAME);
        s.tag(Tags.CONTACTS_MIDDLE_NAME);
        s.tag(Tags.CONTACTS_SUFFIX);
        s.tag(Tags.CONTACTS_COMPANY_NAME);
        s.tag(Tags.CONTACTS_JOB_TITLE);
        s.tag(Tags.CONTACTS_EMAIL1_ADDRESS);
        s.tag(Tags.CONTACTS_EMAIL2_ADDRESS);
        s.tag(Tags.CONTACTS_EMAIL3_ADDRESS);
        s.tag(Tags.CONTACTS_BUSINESS2_TELEPHONE_NUMBER);
        s.tag(Tags.CONTACTS_BUSINESS_TELEPHONE_NUMBER);
        s.tag(Tags.CONTACTS2_MMS);
        s.tag(Tags.CONTACTS_BUSINESS_FAX_NUMBER);
        s.tag(Tags.CONTACTS2_COMPANY_MAIN_PHONE);
        s.tag(Tags.CONTACTS_HOME_FAX_NUMBER);
        s.tag(Tags.CONTACTS_HOME_TELEPHONE_NUMBER);
        s.tag(Tags.CONTACTS_HOME2_TELEPHONE_NUMBER);
        s.tag(Tags.CONTACTS_MOBILE_TELEPHONE_NUMBER);
        s.tag(Tags.CONTACTS_CAR_TELEPHONE_NUMBER);
        s.tag(Tags.CONTACTS_RADIO_TELEPHONE_NUMBER);
        s.tag(Tags.CONTACTS_PAGER_NUMBER);
        s.tag(Tags.CONTACTS_ASSISTANT_TELEPHONE_NUMBER);
        s.tag(Tags.CONTACTS2_IM_ADDRESS);
        s.tag(Tags.CONTACTS2_IM_ADDRESS_2);
        s.tag(Tags.CONTACTS2_IM_ADDRESS_3);
        s.tag(Tags.CONTACTS_BUSINESS_ADDRESS_CITY);
        s.tag(Tags.CONTACTS_BUSINESS_ADDRESS_COUNTRY);
        s.tag(Tags.CONTACTS_BUSINESS_ADDRESS_POSTAL_CODE);
        s.tag(Tags.CONTACTS_BUSINESS_ADDRESS_STATE);
        s.tag(Tags.CONTACTS_BUSINESS_ADDRESS_STREET);
        s.tag(Tags.CONTACTS_HOME_ADDRESS_CITY);
        s.tag(Tags.CONTACTS_HOME_ADDRESS_COUNTRY);
        s.tag(Tags.CONTACTS_HOME_ADDRESS_POSTAL_CODE);
        s.tag(Tags.CONTACTS_HOME_ADDRESS_STATE);
        s.tag(Tags.CONTACTS_HOME_ADDRESS_STREET);
        s.tag(Tags.CONTACTS_OTHER_ADDRESS_CITY);
        s.tag(Tags.CONTACTS_OTHER_ADDRESS_COUNTRY);
        s.tag(Tags.CONTACTS_OTHER_ADDRESS_POSTAL_CODE);
        s.tag(Tags.CONTACTS_OTHER_ADDRESS_STATE);
        s.tag(Tags.CONTACTS_OTHER_ADDRESS_STREET);
        s.tag(Tags.CONTACTS_YOMI_COMPANY_NAME);
        s.tag(Tags.CONTACTS_YOMI_FIRST_NAME);
        s.tag(Tags.CONTACTS_YOMI_LAST_NAME);
        s.tag(Tags.CONTACTS2_NICKNAME);
        s.tag(Tags.CONTACTS_ASSISTANT_NAME);
        s.tag(Tags.CONTACTS2_MANAGER_NAME);
        s.tag(Tags.CONTACTS_SPOUSE);
        s.tag(Tags.CONTACTS_DEPARTMENT);
        s.tag(Tags.CONTACTS_TITLE);
        s.tag(Tags.CONTACTS_OFFICE_LOCATION);
        s.tag(Tags.CONTACTS2_CUSTOMER_ID);
        s.tag(Tags.CONTACTS2_GOVERNMENT_ID);
        s.tag(Tags.CONTACTS2_ACCOUNT_NAME);
        s.tag(Tags.CONTACTS_ANNIVERSARY);
        s.tag(Tags.CONTACTS_BIRTHDAY);
        s.tag(Tags.CONTACTS_WEBPAGE);
        s.tag(Tags.CONTACTS_PICTURE);
        s.end(); // SYNC_SUPPORTED
    }

    /**
     * Add account info and the "caller is syncadapter" param to a URI.
     * @param uri The {@link Uri} to add to.
     * @param emailAddress The email address to add to uri.
     * @return
     */
    private static Uri uriWithAccountAndIsSyncAdapter(final Uri uri, final String emailAddress) {
        return uri.buildUpon()
            .appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, emailAddress)
            .appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE,
                    Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE)
            .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
            .build();
    }

    /**
     * Add the "caller is syncadapter" param to a URI.
     * @param uri The {@link Uri} to add to.
     * @return
     */
    private static Uri addCallerIsSyncAdapterParameter(final Uri uri) {
        return uri.buildUpon()
                .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
                .build();
    }

    /**
     * Mark contacts in dirty groups as dirty.
     */
    private void dirtyContactsWithinDirtyGroups(final ContentResolver cr, final Account account) {
        final String emailAddress = account.mEmailAddress;
        final Cursor c = cr.query( uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI, emailAddress),
                GROUPS_ID_PROJECTION, Groups.DIRTY + "=1", null, null);
        if (c == null) {
            return;
        }
        try {
            if (c.getCount() > 0) {
                final String[] updateArgs = new String[1];
                final ContentValues updateValues = new ContentValues();
                while (c.moveToNext()) {
                    // For each, "touch" all data rows with this group id; this will mark contacts
                    // in this group as dirty (per ContactsContract).  We will then know to upload
                    // them to the server with the modified group information
                    final long id = c.getLong(0);
                    updateValues.put(GroupMembership.GROUP_ROW_ID, id);
                    updateArgs[0] = Long.toString(id);
                    cr.update(ContactsContract.Data.CONTENT_URI, updateValues,
                            MIMETYPE_GROUP_MEMBERSHIP_AND_ID_EQUALS, updateArgs);
                }
                // Really delete groups that are marked deleted
                cr.delete(uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI, emailAddress),
                        Groups.DELETED + "=1", null);
                // Clear the dirty flag for all of our groups
                updateValues.clear();
                updateValues.put(Groups.DIRTY, 0);
                cr.update(uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI, emailAddress),
                        updateValues, null, null);
            }
        } finally {
            c.close();
        }
    }

    /**
     * Helper to add a string to the upsync.
     * @param s The {@link Serializer} for this sync request
     * @param cv The {@link ContentValues} with the data for this string.
     * @param column The column name in cv to find the string.
     * @param tag The tag to use when adding to s.
     * @throws IOException
     */
    private static void sendStringData(final Serializer s, final ContentValues cv,
            final String column, final int tag) throws IOException {
        if (cv.containsKey(column)) {
            final String value = cv.getAsString(column);
            if (!TextUtils.isEmpty(value)) {
                s.data(tag, value);
            }
        }
    }


    // This is to catch when the contacts provider has a date in this particular wrong format.
    private static final SimpleDateFormat SHORT_DATE_FORMAT;
    // Array of formats we check when parsing dates from the contacts provider.
    private static final DateFormat[] DATE_FORMATS;
    static {
        SHORT_DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
        SHORT_DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
        //TODO: We only handle two formatting types. The default contacts app will work with this
        // but any other contacts apps might not. We can try harder to handle those guys too.
        DATE_FORMATS = new DateFormat[] { Eas.DATE_FORMAT, SHORT_DATE_FORMAT };
    }

    /**
     * Helper to add a date to the upsync. It reads the date as a string from the
     * {@link ContentValues} that we got from the provider, tries to parse it using various formats,
     * and formats it correctly to send to the server. If it can't parse it, it will omit the date
     * in the upsync; since Birthdays (the only date currently supported by this class) can be
     * ghosted, this means that any date changes on the client will NOT be reflected on the server.
     * @param s The {@link Serializer} for this sync request
     * @param cv The {@link ContentValues} with the data for this string.
     * @param column The column name in cv to find the string.
     * @param tag The tag to use when adding to s.
     * @throws IOException
     */
    private static void sendDateData(final Serializer s, final ContentValues cv,
            final String column, final int tag) throws IOException {
        if (cv.containsKey(column)) {
            final String value = cv.getAsString(column);
            if (!TextUtils.isEmpty(value)) {
                Date date;
                // Check all the formats we know about to see if one of them works.
                for (final DateFormat format : DATE_FORMATS) {
                    try {
                        date = format.parse(value);
                        if (date != null) {
                            // We got a legit date for this format, so send it up.
                            s.data(tag, Eas.DATE_FORMAT.format(date));
                            return;
                        }
                    } catch (final ParseException e) {
                        // The date didn't match this particular format; keep looping.
                    }
                }
            }
        }
    }


    /**
     * Add a nickname to the upsync.
     * @param s The {@link Serializer} for this sync request.
     * @param cv The {@link ContentValues} with the data for this nickname.
     * @throws IOException
     */
    private static void sendNickname(final Serializer s, final ContentValues cv)
            throws IOException {
        sendStringData(s, cv, Nickname.NAME, Tags.CONTACTS2_NICKNAME);
    }

    /**
     * Add children data to the upsync.
     * @param s The {@link Serializer} for this sync request.
     * @param cv The {@link ContentValues} with the data for a set of children.
     * @throws IOException
     */
    private static void sendChildren(final Serializer s, final ContentValues cv)
            throws IOException {
        boolean first = true;
        for (int i = 0; i < EasChildren.MAX_CHILDREN; i++) {
            final String row = EasChildren.ROWS[i];
            if (cv.containsKey(row)) {
                if (first) {
                    s.start(Tags.CONTACTS_CHILDREN);
                    first = false;
                }
                s.data(Tags.CONTACTS_CHILD, cv.getAsString(row));
            }
        }
        if (!first) {
            s.end();
        }
    }

    /**
     * Add business contact info to the upsync.
     * @param s The {@link Serializer} for this sync request.
     * @param cv The {@link ContentValues} with the data for this business contact.
     * @throws IOException
     */
    private static void sendBusiness(final Serializer s, final ContentValues cv)
            throws IOException {
        sendStringData(s, cv, EasBusiness.ACCOUNT_NAME, Tags.CONTACTS2_ACCOUNT_NAME);
        sendStringData(s, cv, EasBusiness.CUSTOMER_ID, Tags.CONTACTS2_CUSTOMER_ID);
        sendStringData(s, cv, EasBusiness.GOVERNMENT_ID, Tags.CONTACTS2_GOVERNMENT_ID);
    }

    /**
     * Add a webpage info to the upsync.
     * @param s The {@link Serializer} for this sync request.
     * @param cv The {@link ContentValues} with the data for this webpage.
     * @throws IOException
     */
    private static void sendWebpage(final Serializer s, final ContentValues cv) throws IOException {
        sendStringData(s, cv, Website.URL, Tags.CONTACTS_WEBPAGE);
    }

    /**
     * Add personal contact info to the upsync.
     * @param s The {@link Serializer} for this sync request.
     * @param cv The {@link ContentValues} with the data for this personal contact.
     * @throws IOException
     */
    private static void sendPersonal(final Serializer s, final ContentValues cv)
            throws IOException {
        sendStringData(s, cv, EasPersonal.ANNIVERSARY, Tags.CONTACTS_ANNIVERSARY);
        sendStringData(s, cv, EasPersonal.FILE_AS, Tags.CONTACTS_FILE_AS);
    }

    /**
     * Add a phone number to the upsync.
     * @param s The {@link Serializer} for this sync request.
     * @param cv The {@link ContentValues} with the data for this phone number.
     * @param workCount The number of work phone numbers already added.
     * @param homeCount The number of home phone numbers already added.
     * @throws IOException
     */
    private static void sendPhone(final Serializer s, final ContentValues cv, final int workCount,
            final int homeCount) throws IOException {
        final String value = cv.getAsString(Phone.NUMBER);
        if (value == null) return;
        switch (cv.getAsInteger(Phone.TYPE)) {
            case Phone.TYPE_WORK:
                if (workCount < MAX_PHONE_ROWS) {
                    s.data(WORK_PHONE_TAGS[workCount], value);
                }
                break;
            case Phone.TYPE_MMS:
                s.data(Tags.CONTACTS2_MMS, value);
                break;
            case Phone.TYPE_ASSISTANT:
                s.data(Tags.CONTACTS_ASSISTANT_TELEPHONE_NUMBER, value);
                break;
            case Phone.TYPE_FAX_WORK:
                s.data(Tags.CONTACTS_BUSINESS_FAX_NUMBER, value);
                break;
            case Phone.TYPE_COMPANY_MAIN:
                s.data(Tags.CONTACTS2_COMPANY_MAIN_PHONE, value);
                break;
            case Phone.TYPE_HOME:
                if (homeCount < MAX_PHONE_ROWS) {
                    s.data(HOME_PHONE_TAGS[homeCount], value);
                }
                break;
            case Phone.TYPE_MOBILE:
                s.data(Tags.CONTACTS_MOBILE_TELEPHONE_NUMBER, value);
                break;
            case Phone.TYPE_CAR:
                s.data(Tags.CONTACTS_CAR_TELEPHONE_NUMBER, value);
                break;
            case Phone.TYPE_PAGER:
                s.data(Tags.CONTACTS_PAGER_NUMBER, value);
                break;
            case Phone.TYPE_RADIO:
                s.data(Tags.CONTACTS_RADIO_TELEPHONE_NUMBER, value);
                break;
            case Phone.TYPE_FAX_HOME:
                s.data(Tags.CONTACTS_HOME_FAX_NUMBER, value);
                break;
            default:
                break;
        }
    }

    /**
     * Add a relation to the upsync.
     * @param s The {@link Serializer} for this sync request.
     * @param cv The {@link ContentValues} with the data for this relation.
     * @throws IOException
     */
    private static void sendRelation(final Serializer s, final ContentValues cv)
            throws IOException {
        final String value = cv.getAsString(Relation.DATA);
        if (value == null) return;
        switch (cv.getAsInteger(Relation.TYPE)) {
            case Relation.TYPE_ASSISTANT:
                s.data(Tags.CONTACTS_ASSISTANT_NAME, value);
                break;
            case Relation.TYPE_MANAGER:
                s.data(Tags.CONTACTS2_MANAGER_NAME, value);
                break;
            case Relation.TYPE_SPOUSE:
                s.data(Tags.CONTACTS_SPOUSE, value);
                break;
            default:
                break;
        }
    }

    /**
     * Add a name to the upsync.
     * @param s The {@link Serializer} for this sync request.
     * @param cv The {@link ContentValues} with the data for this name.
     * @throws IOException
     */
    // TODO: This used to return a displayName, but it was always null. Figure out what it really
    // wanted to return.
    private static void sendStructuredName(final Serializer s, final ContentValues cv)
            throws IOException {
        sendStringData(s, cv, StructuredName.FAMILY_NAME, Tags.CONTACTS_LAST_NAME);
        sendStringData(s, cv, StructuredName.GIVEN_NAME, Tags.CONTACTS_FIRST_NAME);
        sendStringData(s, cv, StructuredName.MIDDLE_NAME, Tags.CONTACTS_MIDDLE_NAME);
        sendStringData(s, cv, StructuredName.SUFFIX, Tags.CONTACTS_SUFFIX);
        sendStringData(s, cv, StructuredName.PHONETIC_GIVEN_NAME, Tags.CONTACTS_YOMI_FIRST_NAME);
        sendStringData(s, cv, StructuredName.PHONETIC_FAMILY_NAME, Tags.CONTACTS_YOMI_LAST_NAME);
        sendStringData(s, cv, StructuredName.PREFIX, Tags.CONTACTS_TITLE);
    }

    /**
     * Add an address of a particular type to the upsync.
     * @param s The {@link Serializer} for this sync request.
     * @param cv The {@link ContentValues} with the data for this address.
     * @param fieldNames The field names for this address type.
     * @throws IOException
     */
    private static void sendOnePostal(final Serializer s, final ContentValues cv,
            final int[] fieldNames) throws IOException{
        sendStringData(s, cv, StructuredPostal.CITY, fieldNames[0]);
        sendStringData(s, cv, StructuredPostal.COUNTRY, fieldNames[1]);
        sendStringData(s, cv, StructuredPostal.POSTCODE, fieldNames[2]);
        sendStringData(s, cv, StructuredPostal.REGION, fieldNames[3]);
        sendStringData(s, cv, StructuredPostal.STREET, fieldNames[4]);
    }

    /**
     * Add an address to the upsync.
     * @param s The {@link Serializer} for this sync request.
     * @param cv The {@link ContentValues} with the data for this address.
     * @throws IOException
     */
    private static void sendStructuredPostal(final Serializer s, final ContentValues cv)
            throws IOException {
        switch (cv.getAsInteger(StructuredPostal.TYPE)) {
            case StructuredPostal.TYPE_HOME:
                sendOnePostal(s, cv, HOME_ADDRESS_TAGS);
                break;
            case StructuredPostal.TYPE_WORK:
                sendOnePostal(s, cv, WORK_ADDRESS_TAGS);
                break;
            case StructuredPostal.TYPE_OTHER:
                sendOnePostal(s, cv, OTHER_ADDRESS_TAGS);
                break;
            default:
                break;
        }
    }

    /**
     * Add an organization to the upsync.
     * @param s The {@link Serializer} for this sync request.
     * @param cv The {@link ContentValues} with the data for this organization.
     * @throws IOException
     */
    private static void sendOrganization(final Serializer s, final ContentValues cv)
            throws IOException {
        sendStringData(s, cv, Organization.TITLE, Tags.CONTACTS_JOB_TITLE);
        sendStringData(s, cv, Organization.COMPANY, Tags.CONTACTS_COMPANY_NAME);
        sendStringData(s, cv, Organization.DEPARTMENT, Tags.CONTACTS_DEPARTMENT);
        sendStringData(s, cv, Organization.OFFICE_LOCATION, Tags.CONTACTS_OFFICE_LOCATION);
    }

    /**
     * Add an IM to the upsync.
     * @param s The {@link Serializer} for this sync request.
     * @param cv The {@link ContentValues} with the data for this IM.
     * @throws IOException
     */
     private static void sendIm(final Serializer s, final ContentValues cv, final int count)
             throws IOException {
        final String value = cv.getAsString(Im.DATA);
        if (value == null) return;
        if (count < MAX_IM_ROWS) {
            s.data(IM_TAGS[count], value);
        }
    }

    /**
     * Add a birthday to the upsync.
     * @param s The {@link Serializer} for this sync request.
     * @param cv The {@link ContentValues} with the data for this birthday.
     * @throws IOException
     */
    private static void sendBirthday(final Serializer s, final ContentValues cv)
            throws IOException {
        sendDateData(s, cv, Event.START_DATE, Tags.CONTACTS_BIRTHDAY);
    }

    /**
     * Add a note to the upsync.
     * @param s The {@link Serializer} for this sync request.
     * @param cv The {@link ContentValues} with the data for this note.
     * @param protocolVersion
     * @throws IOException
     */
    private void sendNote(final Serializer s, final ContentValues cv, final double protocolVersion)
            throws IOException {
        // Even when there is no local note, we must explicitly upsync an empty note,
        // which is the only way to force the server to delete any pre-existing note.
        String note = "";
        if (cv.containsKey(Note.NOTE)) {
            // EAS won't accept note data with raw newline characters
            note = cv.getAsString(Note.NOTE).replaceAll("\n", "\r\n");
        }
        // Format of upsync data depends on protocol version
        if (protocolVersion >= Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
            s.start(Tags.BASE_BODY);
            s.data(Tags.BASE_TYPE, Eas.BODY_PREFERENCE_TEXT).data(Tags.BASE_DATA, note);
            s.end();
        } else {
            s.data(Tags.CONTACTS_BODY, note);
        }
    }

    /**
     * Add a photo to the upsync.
     * @param s The {@link Serializer} for this sync request.
     * @param cv The {@link ContentValues} with the data for this photo.
     * @throws IOException
     */
    private static void sendPhoto(final Serializer s, final ContentValues cv) throws IOException {
        if (cv.containsKey(Photo.PHOTO)) {
            final byte[] bytes = cv.getAsByteArray(Photo.PHOTO);
            final String pic = Base64.encodeToString(bytes, Base64.NO_WRAP);
            s.data(Tags.CONTACTS_PICTURE, pic);
        } else {
            // Send an empty tag, which signals the server to delete any pre-existing photo
            s.tag(Tags.CONTACTS_PICTURE);
        }
    }

    /**
     * Add an email address to the upsync.
     * @param s The {@link Serializer} for this sync request.
     * @param cv The {@link ContentValues} with the data for this email address.
     * @param count The number of email addresses that have already been added.
     * @param displayName The display name for this contact.
     * @param protocolVersion
     * @throws IOException
     */
    private void sendEmail(final Serializer s, final ContentValues cv, final int count,
            final String displayName, final double protocolVersion) throws IOException {
        // Get both parts of the email address (a newly created one in the UI won't have a name)
        final String addr = cv.getAsString(Email.DATA);
        String name = cv.getAsString(Email.DISPLAY_NAME);
        if (name == null) {
            if (displayName != null) {
                name = displayName;
            } else {
                name = addr;
            }
        }
        // Compose address from name and addr
        if (addr != null) {
            final String value;
            // Only send the raw email address for EAS 2.5 (Hotmail, in particular, chokes on
            // an RFC822 address)
            if (protocolVersion < Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
                value = addr;
            } else {
                value = '\"' + name + "\" <" + addr + '>';
            }
            if (count < MAX_EMAIL_ROWS) {
                s.data(EMAIL_TAGS[count], value);
            }
        }
    }

    private void setUpsyncCommands(final Serializer s, final ContentResolver cr,
            final Account account, final Mailbox mailbox, final double protocolVersion)
            throws IOException {
        // Find any groups of ours that are dirty and dirty those groups' members
        dirtyContactsWithinDirtyGroups(cr, account);

        // First, let's find Contacts that have changed.
        final Uri uri = uriWithAccountAndIsSyncAdapter(
                ContactsContract.RawContactsEntity.CONTENT_URI, account.mEmailAddress);

        // Get them all atomically
        final EntityIterator ei = ContactsContract.RawContacts.newEntityIterator(
                cr.query(uri, null, ContactsContract.RawContacts.DIRTY + "=1", null, null));
        final ContentValues cidValues = new ContentValues();
        try {
            boolean first = true;
            final Uri rawContactUri = addCallerIsSyncAdapterParameter(
                    ContactsContract.RawContacts.CONTENT_URI);
            while (ei.hasNext()) {
                final Entity entity = ei.next();
                // For each of these entities, create the change commands
                final ContentValues entityValues = entity.getEntityValues();
                final String serverId =
                        entityValues.getAsString(ContactsContract.RawContacts.SOURCE_ID);
                final ArrayList<Integer> groupIds = new ArrayList<Integer>();
                if (first) {
                    s.start(Tags.SYNC_COMMANDS);
                    LogUtils.d(TAG, "Sending Contacts changes to the server");
                    first = false;
                }
                if (serverId == null) {
                    // This is a new contact; create a clientId
                    final String clientId =
                            "new_" + mailbox.mId + '_' + System.currentTimeMillis();
                    LogUtils.d(TAG, "Creating new contact with clientId: %s", clientId);
                    s.start(Tags.SYNC_ADD).data(Tags.SYNC_CLIENT_ID, clientId);
                    // And save it in the raw contact
                    cidValues.put(ContactsContract.RawContacts.SYNC1, clientId);
                    cr.update(ContentUris.withAppendedId(rawContactUri,
                            entityValues.getAsLong(ContactsContract.RawContacts._ID)),
                            cidValues, null, null);
                } else {
                    if (entityValues.getAsInteger(ContactsContract.RawContacts.DELETED) == 1) {
                        LogUtils.d(TAG, "Deleting contact with serverId: %s", serverId);
                        s.start(Tags.SYNC_DELETE).data(Tags.SYNC_SERVER_ID, serverId).end();
                        mDeletedContacts.add(
                                entityValues.getAsLong(ContactsContract.RawContacts._ID));
                        continue;
                    }
                    LogUtils.d(TAG, "Upsync change to contact with serverId: %s", serverId);
                    s.start(Tags.SYNC_CHANGE).data(Tags.SYNC_SERVER_ID, serverId);
                }
                s.start(Tags.SYNC_APPLICATION_DATA);
                // Write out the data here
                int imCount = 0;
                int emailCount = 0;
                int homePhoneCount = 0;
                int workPhoneCount = 0;
                // TODO: How is this name supposed to be formed?
                String displayName = null;
                final ArrayList<ContentValues> emailValues = new ArrayList<ContentValues>();
                for (final Entity.NamedContentValues ncv: entity.getSubValues()) {
                    final ContentValues cv = ncv.values;
                    final String mimeType = cv.getAsString(ContactsContract.Data.MIMETYPE);
                    if (mimeType.equals(Email.CONTENT_ITEM_TYPE)) {
                        emailValues.add(cv);
                    } else if (mimeType.equals(Nickname.CONTENT_ITEM_TYPE)) {
                        sendNickname(s, cv);
                    } else if (mimeType.equals(EasChildren.CONTENT_ITEM_TYPE)) {
                        sendChildren(s, cv);
                    } else if (mimeType.equals(EasBusiness.CONTENT_ITEM_TYPE)) {
                        sendBusiness(s, cv);
                    } else if (mimeType.equals(Website.CONTENT_ITEM_TYPE)) {
                        sendWebpage(s, cv);
                    } else if (mimeType.equals(EasPersonal.CONTENT_ITEM_TYPE)) {
                        sendPersonal(s, cv);
                    } else if (mimeType.equals(Phone.CONTENT_ITEM_TYPE)) {
                        sendPhone(s, cv, workPhoneCount, homePhoneCount);
                        int type = cv.getAsInteger(Phone.TYPE);
                        if (type == Phone.TYPE_HOME) homePhoneCount++;
                        if (type == Phone.TYPE_WORK) workPhoneCount++;
                    } else if (mimeType.equals(Relation.CONTENT_ITEM_TYPE)) {
                        sendRelation(s, cv);
                    } else if (mimeType.equals(StructuredName.CONTENT_ITEM_TYPE)) {
                        sendStructuredName(s, cv);
                    } else if (mimeType.equals(StructuredPostal.CONTENT_ITEM_TYPE)) {
                        sendStructuredPostal(s, cv);
                    } else if (mimeType.equals(Organization.CONTENT_ITEM_TYPE)) {
                        sendOrganization(s, cv);
                    } else if (mimeType.equals(Im.CONTENT_ITEM_TYPE)) {
                        sendIm(s, cv, imCount++);
                    } else if (mimeType.equals(Event.CONTENT_ITEM_TYPE)) {
                        Integer eventType = cv.getAsInteger(Event.TYPE);
                        if (eventType != null && eventType.equals(Event.TYPE_BIRTHDAY)) {
                            sendBirthday(s, cv);
                        }
                    } else if (mimeType.equals(GroupMembership.CONTENT_ITEM_TYPE)) {
                        // We must gather these, and send them together (below)
                        groupIds.add(cv.getAsInteger(GroupMembership.GROUP_ROW_ID));
                    } else if (mimeType.equals(Note.CONTENT_ITEM_TYPE)) {
                        sendNote(s, cv, protocolVersion);
                    } else if (mimeType.equals(Photo.CONTENT_ITEM_TYPE)) {
                        sendPhoto(s, cv);
                    } else {
                        LogUtils.i(TAG, "Contacts upsync, unknown data: %s", mimeType);
                    }
                }

                // We do the email rows last, because we need to make sure we've found the
                // displayName (if one exists); this would be in a StructuredName rnow
                for (final ContentValues cv: emailValues) {
                    sendEmail(s, cv, emailCount++, displayName, protocolVersion);
                }

                // Now, we'll send up groups, if any
                if (!groupIds.isEmpty()) {
                    boolean groupFirst = true;
                    for (final int id: groupIds) {
                        // Since we get id's from the provider, we need to find their names
                        final Cursor c = cr.query(ContentUris.withAppendedId(Groups.CONTENT_URI,
                                id), GROUP_TITLE_PROJECTION, null, null, null);
                        try {
                            // Presumably, this should always succeed, but ...
                            if (c.moveToFirst()) {
                                if (groupFirst) {
                                    s.start(Tags.CONTACTS_CATEGORIES);
                                    groupFirst = false;
                                }
                                s.data(Tags.CONTACTS_CATEGORY, c.getString(0));
                            }
                        } finally {
                            c.close();
                        }
                    }
                    if (!groupFirst) {
                        s.end();
                    }
                }
                s.end().end(); // ApplicationData & Change
                mUpdatedContacts.add(entityValues.getAsLong(ContactsContract.RawContacts._ID));
            }
            if (!first) {
                s.end(); // Commands
            }
        } finally {
            ei.close();
        }

    }

    @Override
    public void cleanup(final Context context, final Account account) {
        final ContentResolver cr = context.getContentResolver();

        // Mark the changed contacts dirty = 0
        // Permanently delete the user deletions
        ContactsSyncParser.ContactOperations ops = new ContactsSyncParser.ContactOperations();
        for (final Long id: mUpdatedContacts) {
            ops.add(ContentProviderOperation
                    .newUpdate(ContentUris.withAppendedId(ContactsContract.RawContacts.CONTENT_URI,
                            id).buildUpon()
                            .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
                            .build())
                    .withValue(ContactsContract.RawContacts.DIRTY, 0).build());
        }
        for (final Long id: mDeletedContacts) {
            ops.add(ContentProviderOperation.newDelete(ContentUris.withAppendedId(
                    ContactsContract.RawContacts.CONTENT_URI, id).buildUpon()
                    .appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true").build())
                    .build());
        }
        ops.execute(context);
        if (mParser != null && mParser.isGroupsUsed()) {
            // Make sure the title column is set for all of our groups
            // And that all of our groups are visible
            // TODO Perhaps the visible part should only happen when the group is created, but
            // this is fine for now.
            final Uri groupsUri = uriWithAccountAndIsSyncAdapter(Groups.CONTENT_URI,
                    account.mEmailAddress);
            final Cursor c = cr.query(groupsUri, new String[] {Groups.SOURCE_ID, Groups.TITLE},
                    Groups.TITLE + " IS NULL", null, null);
            final ContentValues values = new ContentValues();
            values.put(Groups.GROUP_VISIBLE, 1);
            try {
                while (c.moveToNext()) {
                    final String sourceId = c.getString(0);
                    values.put(Groups.TITLE, sourceId);
                    cr.update(uriWithAccountAndIsSyncAdapter(groupsUri,
                            account.mEmailAddress), values, Groups.SOURCE_ID + "=?",
                            new String[] {sourceId});
                }
            } finally {
                c.close();
            }
        }
    }

    /**
     * Delete an account from the Contacts provider.
     * @param context Our {@link Context}
     * @param emailAddress The email address of the account we wish to delete
     */
    public static void wipeAccountFromContentProvider(final Context context,
            final String emailAddress) {
        context.getContentResolver().delete(uriWithAccountAndIsSyncAdapter(
                ContactsContract.RawContacts.CONTENT_URI, emailAddress), null, null);
    }
}
