/*
 * Copyright (C) 2011 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.exchange.provider;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.util.Log;

import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent.MailboxColumns;
import com.android.emailcommon.provider.Mailbox;

public class MailboxUtilities {
    public static final String WHERE_PARENT_KEY_UNINITIALIZED =
        "(" + MailboxColumns.PARENT_KEY + " isnull OR " + MailboxColumns.PARENT_KEY + "=" +
        Mailbox.PARENT_KEY_UNINITIALIZED + ")";
    // The flag we use in Account to indicate a mailbox change in progress
    private static final int ACCOUNT_MAILBOX_CHANGE_FLAG = Account.FLAGS_SYNC_ADAPTER;

    /**
     * Recalculate a mailbox's flags and the parent key of any children
     * @param context the caller's context
     * @param parentCursor a cursor to a mailbox that requires fixup
     */
    public static void setFlagsAndChildrensParentKey(Context context, Cursor parentCursor,
            String accountSelector) {
        ContentResolver resolver = context.getContentResolver();
        String[] selectionArgs = new String[1];
        ContentValues parentValues = new ContentValues();
        // Get the data we need first
        long parentId = parentCursor.getLong(Mailbox.CONTENT_ID_COLUMN);
        int parentFlags = 0;
        int parentType = parentCursor.getInt(Mailbox.CONTENT_TYPE_COLUMN);
        String parentServerId = parentCursor.getString(Mailbox.CONTENT_SERVER_ID_COLUMN);
        // All email-type boxes hold mail
        if (parentType <= Mailbox.TYPE_NOT_EMAIL) {
            parentFlags |= Mailbox.FLAG_HOLDS_MAIL + Mailbox.FLAG_SUPPORTS_SETTINGS;
        }
        // Outbox, Drafts, and Sent don't allow mail to be moved to them
        if (parentType == Mailbox.TYPE_MAIL || parentType == Mailbox.TYPE_TRASH ||
                parentType == Mailbox.TYPE_JUNK || parentType == Mailbox.TYPE_INBOX) {
            parentFlags |= Mailbox.FLAG_ACCEPTS_MOVED_MAIL;
        }
        // There's no concept of "append" in EAS so FLAG_ACCEPTS_APPENDED_MAIL is never used
        // Mark parent mailboxes as parents & add parent key to children
        // An example of a mailbox with a null serverId would be an Outbox that we create locally
        // for hotmail accounts (which don't have a server-based Outbox)
        if (parentServerId != null) {
            selectionArgs[0] = parentServerId;
            Cursor childCursor = resolver.query(Mailbox.CONTENT_URI,
                    Mailbox.ID_PROJECTION, MailboxColumns.PARENT_SERVER_ID + "=? AND " +
                    accountSelector, selectionArgs, null);
            if (childCursor == null) return;
            try {
                while (childCursor.moveToNext()) {
                    parentFlags |= Mailbox.FLAG_HAS_CHILDREN | Mailbox.FLAG_CHILDREN_VISIBLE;
                    ContentValues childValues = new ContentValues();
                    childValues.put(Mailbox.PARENT_KEY, parentId);
                    long childId = childCursor.getLong(Mailbox.ID_PROJECTION_COLUMN);
                    resolver.update(ContentUris.withAppendedId(Mailbox.CONTENT_URI, childId),
                            childValues, null, null);
                }
            } finally {
                childCursor.close();
            }
        } else {
            // Mark this is having no parent, so that we don't examine this mailbox again
            parentValues.put(Mailbox.PARENT_KEY, Mailbox.NO_MAILBOX);
            Log.w(Logging.LOG_TAG, "Mailbox with null serverId: " +
                    parentCursor.getString(Mailbox.CONTENT_DISPLAY_NAME_COLUMN) + ", type: " +
                    parentType);
        }
        // Save away updated flags and parent key (if any)
        parentValues.put(Mailbox.FLAGS, parentFlags);
        resolver.update(ContentUris.withAppendedId(Mailbox.CONTENT_URI, parentId),
                parentValues, null, null);
    }

    /**
     * Recalculate a mailbox's flags and the parent key of any children
     * @param context the caller's context
     * @param accountSelector (see description below in fixupUninitializedParentKeys)
     * @param serverId the server id of an individual mailbox
     */
    public static void setFlagsAndChildrensParentKey(Context context, String accountSelector,
            String serverId) {
        Cursor cursor = context.getContentResolver().query(Mailbox.CONTENT_URI,
                Mailbox.CONTENT_PROJECTION, MailboxColumns.SERVER_ID + "=? AND " + accountSelector,
                new String[] {serverId}, null);
        if (cursor == null) return;
        try {
            if (cursor.moveToFirst()) {
                setFlagsAndChildrensParentKey(context, cursor, accountSelector);
            }
        } finally {
            cursor.close();
        }
    }

    /**
     * Given an account selector, specifying the account(s) on which to work, create the parentKey
     * and flags for each mailbox in the account(s) that is uninitialized (parentKey = 0 or null)
     *
     * @param accountSelector a sqlite WHERE clause expression to be used in determining the
     * mailboxes to be acted upon, e.g. accountKey IN (1, 2), accountKey = 12, etc.
     */
    public static void fixupUninitializedParentKeys(Context context, String accountSelector) {
        // Sanity check first on our arguments
        if (accountSelector == null) throw new IllegalArgumentException();
        // The selection we'll use to find uninitialized parent key mailboxes
        String noParentKeySelection = WHERE_PARENT_KEY_UNINITIALIZED + " AND " + accountSelector;

        // We'll loop through mailboxes with an uninitialized parent key
        ContentResolver resolver = context.getContentResolver();
        Cursor noParentKeyMailboxCursor =
                resolver.query(Mailbox.CONTENT_URI, Mailbox.CONTENT_PROJECTION,
                        noParentKeySelection, null, null);
        if (noParentKeyMailboxCursor == null) return;
        try {
            while (noParentKeyMailboxCursor.moveToNext()) {
                setFlagsAndChildrensParentKey(context, noParentKeyMailboxCursor, accountSelector);
                String parentServerId =
                        noParentKeyMailboxCursor.getString(Mailbox.CONTENT_PARENT_SERVER_ID_COLUMN);
                // Fixup the parent so that the children's parentKey is updated
                if (parentServerId != null) {
                    setFlagsAndChildrensParentKey(context, accountSelector, parentServerId);
                }
            }
        } finally {
            noParentKeyMailboxCursor.close();
        }

        // Any mailboxes without a parent key should have parentKey set to -1 (no parent)
        ContentValues values = new ContentValues();
        values.clear();
        values.put(Mailbox.PARENT_KEY, Mailbox.NO_MAILBOX);
        resolver.update(Mailbox.CONTENT_URI, values, noParentKeySelection, null);
     }

    private static void setAccountSyncAdapterFlag(Context context, long accountId, boolean start) {
        Account account = Account.restoreAccountWithId(context, accountId);
        if (account == null) return;
        // Set temporary flag indicating state of update of mailbox list
        ContentValues cv = new ContentValues();
        cv.put(Account.FLAGS, start ? (account.mFlags | ACCOUNT_MAILBOX_CHANGE_FLAG) :
            account.mFlags & ~ACCOUNT_MAILBOX_CHANGE_FLAG);
        context.getContentResolver().update(
                ContentUris.withAppendedId(Account.CONTENT_URI, account.mId), cv, null, null);
    }

    /**
     * Indicate that the specified account is starting the process of changing its mailbox list
     * @param context the caller's context
     * @param accountId the account that is starting to change its mailbox list
     */
    public static void startMailboxChanges(Context context, long accountId) {
        setAccountSyncAdapterFlag(context, accountId, true);
    }

    /**
     * Indicate that the specified account is ending the process of changing its mailbox list
     * @param context the caller's context
     * @param accountId the account that is finished with changes to its mailbox list
     */
    public static void endMailboxChanges(Context context, long accountId) {
        setAccountSyncAdapterFlag(context, accountId, false);
    }

    /**
     * Check that we didn't leave the account's mailboxes in a (possibly) inconsistent state
     * If we did, make them consistent again
     * @param context the caller's context
     * @param accountId the account whose mailboxes are to be checked
     */
    public static void checkMailboxConsistency(Context context, long accountId) {
        // If our temporary flag is set, we were interrupted during an update
        // First, make sure we're current (really fast w/ caching)
        Account account = Account.restoreAccountWithId(context, accountId);
        if (account == null) return;
        if ((account.mFlags & ACCOUNT_MAILBOX_CHANGE_FLAG) != 0) {
            Log.w(Logging.LOG_TAG, "Account " + account.mDisplayName +
                    " has inconsistent mailbox data; fixing up...");
            // Set all account mailboxes to uninitialized parent key
            ContentValues values = new ContentValues();
            values.put(Mailbox.PARENT_KEY, Mailbox.PARENT_KEY_UNINITIALIZED);
            String accountSelector = Mailbox.ACCOUNT_KEY + "=" + account.mId;
            ContentResolver resolver = context.getContentResolver();
            resolver.update(Mailbox.CONTENT_URI, values, accountSelector, null);
            // Fix up keys and flags
            MailboxUtilities.fixupUninitializedParentKeys(context, accountSelector);
            // Clear the temporary flag
            endMailboxChanges(context, accountId);
        }
    }
}
