/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License
 */
package com.android.providers.contacts;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.provider.ContactsContract.CommonDataKinds.GroupMembership;
import android.provider.ContactsContract.Groups;
import android.provider.ContactsContract.RawContacts;

import com.android.providers.contacts.ContactsDatabaseHelper.Clauses;
import com.android.providers.contacts.ContactsDatabaseHelper.DataColumns;
import com.android.providers.contacts.ContactsDatabaseHelper.GroupsColumns;
import com.android.providers.contacts.ContactsDatabaseHelper.Projections;
import com.android.providers.contacts.ContactsDatabaseHelper.RawContactsColumns;
import com.android.providers.contacts.ContactsDatabaseHelper.Tables;
import com.android.providers.contacts.ContactsProvider2.GroupIdCacheEntry;
import com.android.providers.contacts.aggregation.AbstractContactAggregator;

import java.util.ArrayList;
import java.util.Map;

/**
 * Handler for group membership data rows.
 */
public class DataRowHandlerForGroupMembership extends DataRowHandler {

    interface RawContactsQuery {
        String TABLE = Tables.RAW_CONTACTS;

        String[] COLUMNS = new String[] {
                RawContacts.DELETED,
                RawContactsColumns.ACCOUNT_ID,
        };

        int DELETED = 0;
        int ACCOUNT_ID = 1;
    }

    private static final String SELECTION_RAW_CONTACT_ID = RawContacts._ID + "=?";

    private static final String QUERY_COUNT_FAVORITES_GROUP_MEMBERSHIPS_BY_RAW_CONTACT_ID =
            "SELECT COUNT(*) FROM " + Tables.DATA + " LEFT OUTER JOIN " + Tables .GROUPS
                    + " ON " + Tables.DATA + "." + GroupMembership.GROUP_ROW_ID
                    + "=" + GroupsColumns.CONCRETE_ID
                    + " WHERE " + DataColumns.MIMETYPE_ID + "=?"
                    + " AND " + Tables.DATA + "." + GroupMembership.RAW_CONTACT_ID + "=?"
                    + " AND " + Groups.FAVORITES + "!=0";

    private final Map<String, ArrayList<GroupIdCacheEntry>> mGroupIdCache;

    public DataRowHandlerForGroupMembership(Context context, ContactsDatabaseHelper dbHelper,
            AbstractContactAggregator aggregator,
            Map<String, ArrayList<GroupIdCacheEntry>> groupIdCache) {
        super(context, dbHelper, aggregator, GroupMembership.CONTENT_ITEM_TYPE);
        mGroupIdCache = groupIdCache;
    }

    @Override
    public long insert(SQLiteDatabase db, TransactionContext txContext, long rawContactId,
            ContentValues values) {
        resolveGroupSourceIdInValues(txContext, rawContactId, db, values, true);
        long dataId = super.insert(db, txContext, rawContactId, values);
        if (hasFavoritesGroupMembership(db, rawContactId)) {
            updateRawContactsStar(db, rawContactId, true /* starred */);
        }
        updateVisibility(txContext, rawContactId);
        return dataId;
    }

    @Override
    public boolean update(SQLiteDatabase db, TransactionContext txContext, ContentValues values,
            Cursor c, boolean callerIsSyncAdapter, boolean callerIsMetadataSyncAdapter) {
        long rawContactId = c.getLong(DataUpdateQuery.RAW_CONTACT_ID);
        boolean wasStarred = hasFavoritesGroupMembership(db, rawContactId);
        resolveGroupSourceIdInValues(txContext, rawContactId, db, values, false);
        if (!super.update(db, txContext, values, c, callerIsSyncAdapter, callerIsMetadataSyncAdapter)) {
            return false;
        }
        boolean isStarred = hasFavoritesGroupMembership(db, rawContactId);
        if (wasStarred != isStarred) {
            updateRawContactsStar(db, rawContactId, isStarred);
        }
        updateVisibility(txContext, rawContactId);
        return true;
    }

    private void updateRawContactsStar(SQLiteDatabase db, long rawContactId, boolean starred) {
        ContentValues rawContactValues = new ContentValues();
        rawContactValues.put(RawContacts.STARRED, starred ? 1 : 0);
        if (db.update(Tables.RAW_CONTACTS, rawContactValues, SELECTION_RAW_CONTACT_ID,
                new String[]{Long.toString(rawContactId)}) > 0) {
            mContactAggregator.updateStarred(rawContactId);
        }
    }

    private boolean hasFavoritesGroupMembership(SQLiteDatabase db, long rawContactId) {
        // TODO compiled SQL statement
        final long groupMembershipMimetypeId = mDbHelper
                .getMimeTypeId(GroupMembership.CONTENT_ITEM_TYPE);
        boolean isStarred = 0 < DatabaseUtils
                .longForQuery(db, QUERY_COUNT_FAVORITES_GROUP_MEMBERSHIPS_BY_RAW_CONTACT_ID,
                new String[]{Long.toString(groupMembershipMimetypeId), Long.toString(rawContactId)});
        return isStarred;
    }

    @Override
    public int delete(SQLiteDatabase db, TransactionContext txContext, Cursor c) {
        long rawContactId = c.getLong(DataDeleteQuery.RAW_CONTACT_ID);
        boolean wasStarred = hasFavoritesGroupMembership(db, rawContactId);
        int count = super.delete(db, txContext, c);
        boolean isStarred = hasFavoritesGroupMembership(db, rawContactId);
        if (wasStarred && !isStarred) {
            updateRawContactsStar(db, rawContactId, false /* starred */);
        }
        updateVisibility(txContext, rawContactId);
        return count;
    }

    private void updateVisibility(TransactionContext txContext, long rawContactId) {
        long contactId = mDbHelper.getContactId(rawContactId);
        if (contactId == 0) {
            return;
        }

        if (mDbHelper.updateContactVisibleOnlyIfChanged(txContext, contactId)) {
            mContactAggregator.updateAggregationAfterVisibilityChange(contactId);
        }
    }

    private void resolveGroupSourceIdInValues(TransactionContext txContext,
            long rawContactId, SQLiteDatabase db, ContentValues values, boolean isInsert) {
        boolean containsGroupSourceId = values.containsKey(GroupMembership.GROUP_SOURCE_ID);
        boolean containsGroupId = values.containsKey(GroupMembership.GROUP_ROW_ID);
        if (containsGroupSourceId && containsGroupId) {
            throw new IllegalArgumentException(
                    "you are not allowed to set both the GroupMembership.GROUP_SOURCE_ID "
                            + "and GroupMembership.GROUP_ROW_ID");
        }

        if (!containsGroupSourceId && !containsGroupId) {
            if (isInsert) {
                throw new IllegalArgumentException(
                        "you must set exactly one of GroupMembership.GROUP_SOURCE_ID "
                                + "and GroupMembership.GROUP_ROW_ID");
            } else {
                return;
            }
        }

        if (containsGroupSourceId) {
            final String sourceId = values.getAsString(GroupMembership.GROUP_SOURCE_ID);
            final long groupId = getOrMakeGroup(db, rawContactId, sourceId,
                    txContext.getAccountIdOrNullForRawContact(rawContactId));
            values.remove(GroupMembership.GROUP_SOURCE_ID);
            values.put(GroupMembership.GROUP_ROW_ID, groupId);
        }
    }

    /**
     * Returns the group id of the group with sourceId and the same account as rawContactId.
     * If the group doesn't already exist then it is first created.
     *
     * @param db SQLiteDatabase to use for this operation
     * @param rawContactId the raw contact this group is associated with
     * @param sourceId the source ID of the group to query or create
     * @param accountIdOrNull the account ID for the raw contact.  If null it'll be queried from
     *    the raw_contacts table.
     * @return the group id of the existing or created group
     * @throws IllegalArgumentException if the contact is not associated with an account
     * @throws IllegalStateException if a group needs to be created but the creation failed
     */
    private long getOrMakeGroup(SQLiteDatabase db, long rawContactId, String sourceId,
            Long accountIdOrNull) {

        if (accountIdOrNull == null) {
            mSelectionArgs1[0] = String.valueOf(rawContactId);
            Cursor c = db.query(RawContactsQuery.TABLE, RawContactsQuery.COLUMNS,
                    RawContactsColumns.CONCRETE_ID + "=?", mSelectionArgs1, null, null, null);
            try {
                if (c.moveToFirst()) {
                    accountIdOrNull = c.getLong(RawContactsQuery.ACCOUNT_ID);
                }
            } finally {
                c.close();
            }
        }

        if (accountIdOrNull == null) {
            throw new IllegalArgumentException("Raw contact not found for _ID=" + rawContactId);
        }
        final long accountId = accountIdOrNull;

        ArrayList<GroupIdCacheEntry> entries = mGroupIdCache.get(sourceId);
        if (entries == null) {
            entries = new ArrayList<GroupIdCacheEntry>(1);
            mGroupIdCache.put(sourceId, entries);
        }

        int count = entries.size();
        for (int i = 0; i < count; i++) {
            GroupIdCacheEntry entry = entries.get(i);
            if (entry.accountId == accountId) {
                return entry.groupId;
            }
        }

        GroupIdCacheEntry entry = new GroupIdCacheEntry();
        entry.accountId = accountId;
        entry.sourceId = sourceId;
        entries.add(0, entry);

        // look up the group that contains this sourceId and has the same account as the contact
        // referred to by rawContactId
        Cursor c = db.query(Tables.GROUPS, Projections.ID,
                Clauses.GROUP_HAS_ACCOUNT_AND_SOURCE_ID,
                new String[]{sourceId, Long.toString(accountId)}, null, null, null);

        try {
            if (c.moveToFirst()) {
                entry.groupId = c.getLong(0);
            } else {
                ContentValues groupValues = new ContentValues();
                groupValues.put(GroupsColumns.ACCOUNT_ID, accountId);
                groupValues.put(Groups.SOURCE_ID, sourceId);
                long groupId = db.insert(Tables.GROUPS, null, groupValues);
                if (groupId < 0) {
                    throw new IllegalStateException("unable to create a new group with "
                            + "this sourceid: " + groupValues);
                }
                entry.groupId = groupId;
            }
        } finally {
            c.close();
        }

        return entry.groupId;
    }
}
