/*
 * 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.exchange.service;

import android.app.AlarmManager;
import android.app.Notification;
import android.app.Notification.Builder;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.AbstractThreadedSyncAdapter;
import android.content.ComponentName;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.SyncResult;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.CalendarContract;
import android.provider.ContactsContract;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.Log;

import com.android.emailcommon.TempDirectory;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.AccountColumns;
import com.android.emailcommon.provider.HostAuth;
import com.android.emailcommon.provider.Mailbox;
import com.android.emailcommon.service.EmailServiceStatus;
import com.android.emailcommon.service.IEmailService;
import com.android.emailcommon.service.IEmailServiceCallback;
import com.android.emailcommon.service.SearchParams;
import com.android.emailcommon.service.ServiceProxy;
import com.android.emailcommon.utility.IntentUtilities;
import com.android.emailcommon.utility.Utility;
import com.android.exchange.Eas;
import com.android.exchange.R.drawable;
import com.android.exchange.R.string;
import com.android.exchange.adapter.PingParser;
import com.android.exchange.adapter.Search;
import com.android.exchange.eas.EasFolderSync;
import com.android.exchange.eas.EasMoveItems;
import com.android.exchange.eas.EasOperation;
import com.android.exchange.eas.EasPing;
import com.android.exchange.eas.EasSync;
import com.android.mail.providers.UIProvider;
import com.android.mail.utils.LogUtils;

import java.util.HashMap;
import java.util.HashSet;

/**
 * Service for communicating with Exchange servers. There are three main parts of this class:
 * TODO: Flesh out these comments.
 * 1) An {@link AbstractThreadedSyncAdapter} to handle actually performing syncs.
 * 2) Bookkeeping for running Ping requests, which handles push notifications.
 * 3) An {@link IEmailService} Stub to handle RPC from the UI.
 */
public class EmailSyncAdapterService extends AbstractSyncAdapterService {

    private static final String TAG = Eas.LOG_TAG;

    /**
     * Temporary while converting to EasService. Do not check in set to true.
     * When true, delegates various operations to {@link EasService}, for use while developing the
     * new service.
     * The two following fields are used to support what happens when this is true.
     */
    private static final boolean DELEGATE_TO_EAS_SERVICE = false;
    private IEmailService mEasService;
    private ServiceConnection mConnection;

    private static final String EXTRA_START_PING = "START_PING";
    private static final String EXTRA_PING_ACCOUNT = "PING_ACCOUNT";
    private static final long SYNC_ERROR_BACKOFF_MILLIS = 5 * DateUtils.MINUTE_IN_MILLIS;

    /**
     * The amount of time between periodic syncs intended to ensure that push hasn't died.
     */
    private static final long KICK_SYNC_INTERVAL =
            DateUtils.HOUR_IN_MILLIS / DateUtils.SECOND_IN_MILLIS;

    /** Controls whether we do a periodic "kick" to restart the ping. */
    private static final boolean SCHEDULE_KICK = true;

    /** Projection used for getting email address for an account. */
    private static final String[] ACCOUNT_EMAIL_PROJECTION = { AccountColumns.EMAIL_ADDRESS };

    private static final Object sSyncAdapterLock = new Object();
    private static AbstractThreadedSyncAdapter sSyncAdapter = null;

    /**
     * Bookkeeping for handling synchronization between pings and syncs.
     * "Ping" refers to a hanging POST or GET that is used to receive push notifications. Ping is
     * the term for the Exchange command, but this code should be generic enough to be easily
     * extended to IMAP.
     * "Sync" refers to an actual sync command to either fetch mail state, account state, or send
     * mail (send is implemented as "sync the outbox").
     * TODO: Outbox sync probably need not stop a ping in progress.
     * Basic rules of how these interact (note that all rules are per account):
     * - Only one ping or sync may run at a time.
     * - Due to how {@link AbstractThreadedSyncAdapter} works, sync requests will not occur while
     *   a sync is in progress.
     * - On the other hand, ping requests may come in while handling a ping.
     * - "Ping request" is shorthand for "a request to change our ping parameters", which includes
     *   a request to stop receiving push notifications.
     * - If neither a ping nor a sync is running, then a request for either will run it.
     * - If a sync is running, new ping requests block until the sync completes.
     * - If a ping is running, a new sync request stops the ping and creates a pending ping
     *   (which blocks until the sync completes).
     * - If a ping is running, a new ping request stops the ping and either starts a new one or
     *   does nothing, as appopriate (since a ping request can be to stop pushing).
     * - As an optimization, while a ping request is waiting to run, subsequent ping requests are
     *   ignored (the pending ping will pick up the latest ping parameters at the time it runs).
     */
    public class SyncHandlerSynchronizer {
        /**
         * Map of account id -> ping handler.
         * For a given account id, there are three possible states:
         * 1) If no ping or sync is currently running, there is no entry in the map for the account.
         * 2) If a ping is running, there is an entry with the appropriate ping handler.
         * 3) If there is a sync running, there is an entry with null as the value.
         * We cannot have more than one ping or sync running at a time.
         */
        private final HashMap<Long, PingTask> mPingHandlers = new HashMap<Long, PingTask>();

        /**
         * Wait until neither a sync nor a ping is running on this account, and then return.
         * If there's a ping running, actively stop it. (For syncs, we have to just wait.)
         * @param accountId The account we want to wait for.
         */
        private synchronized void waitUntilNoActivity(final long accountId) {
            while (mPingHandlers.containsKey(accountId)) {
                final PingTask pingHandler = mPingHandlers.get(accountId);
                if (pingHandler != null) {
                    pingHandler.stop();
                }
                try {
                    wait();
                } catch (final InterruptedException e) {
                    // TODO: When would this happen, and how should I handle it?
                }
            }
        }

        /**
         * Use this to see if we're currently syncing, as opposed to pinging or doing nothing.
         * @param accountId The account to check.
         * @return Whether that account is currently running a sync.
         */
        private synchronized boolean isRunningSync(final long accountId) {
            return (mPingHandlers.containsKey(accountId) && mPingHandlers.get(accountId) == null);
        }

        /**
         * If there are no running pings, stop the service.
         */
        private void stopServiceIfNoPings() {
            for (final PingTask pingHandler : mPingHandlers.values()) {
                if (pingHandler != null) {
                    return;
                }
            }
            EmailSyncAdapterService.this.stopSelf();
        }

        /**
         * Called prior to starting a sync to update our bookkeeping. We don't actually run the sync
         * here; the caller must do that.
         * @param accountId The account on which we are running a sync.
         */
        public synchronized void startSync(final long accountId) {
            waitUntilNoActivity(accountId);
            mPingHandlers.put(accountId, null);
        }

        /**
         * Starts or restarts a ping for an account, if the current account state indicates that it
         * wants to push.
         * @param account The account whose ping is being modified.
         */
        public synchronized void modifyPing(final boolean lastSyncHadError,
                final Account account) {
            // If a sync is currently running, it will start a ping when it's done, so there's no
            // need to do anything right now.
            if (isRunningSync(account.mId)) {
                return;
            }

            // Don't ping if we're on security hold.
            if ((account.mFlags & Account.FLAGS_SECURITY_HOLD) != 0) {
                return;
            }

            // Don't ping for accounts that haven't performed initial sync.
            if (EmailContent.isInitialSyncKey(account.mSyncKey)) {
                return;
            }

            // Determine if this account needs pushes. All of the following must be true:
            // - The account's sync interval must indicate that it wants push.
            // - At least one content type must be sync-enabled in the account manager.
            // - At least one mailbox of a sync-enabled type must have automatic sync enabled.
            final EmailSyncAdapterService service = EmailSyncAdapterService.this;
            final android.accounts.Account amAccount = new android.accounts.Account(
                            account.mEmailAddress, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE);
            boolean pushNeeded = false;
            if (account.mSyncInterval == Account.CHECK_INTERVAL_PUSH) {
                final HashSet<String> authsToSync = getAuthsToSync(amAccount);
                // If we have at least one sync-enabled content type, check for syncing mailboxes.
                if (!authsToSync.isEmpty()) {
                    final Cursor c = Mailbox.getMailboxesForPush(service.getContentResolver(),
                            account.mId);
                    if (c != null) {
                        try {
                            while (c.moveToNext()) {
                                final int mailboxType = c.getInt(Mailbox.CONTENT_TYPE_COLUMN);
                                if (authsToSync.contains(Mailbox.getAuthority(mailboxType))) {
                                    pushNeeded = true;
                                    break;
                                }
                            }
                        } finally {
                            c.close();
                        }
                    }
                }
            }

            // Stop, start, or restart the ping as needed, as well as the ping kicker periodic sync.
            final PingTask pingSyncHandler = mPingHandlers.get(account.mId);
            final Bundle extras = new Bundle(1);
            extras.putBoolean(Mailbox.SYNC_EXTRA_PUSH_ONLY, true);
            if (pushNeeded) {
                // First start or restart the ping as appropriate.
                if (pingSyncHandler != null) {
                    pingSyncHandler.restart();
                } else {
                    // Start a new ping.
                    // Note: unlike startSync, we CANNOT allow the caller to do the actual work.
                    // If we return before the ping starts, there's a race condition where another
                    // ping or sync might start first. It only works for startSync because sync is
                    // higher priority than ping (i.e. a ping can't start while a sync is pending)
                    // and only one sync can run at a time.
                    if (lastSyncHadError) {
                        // Schedule an alarm to set up the ping in 5 minutes
                        final Intent intent = new Intent(service, EmailSyncAdapterService.class);
                        intent.setAction(Eas.EXCHANGE_SERVICE_INTENT_ACTION);
                        intent.putExtra(EXTRA_START_PING, true);
                        intent.putExtra(EXTRA_PING_ACCOUNT, amAccount);
                        final PendingIntent pi = PendingIntent.getService(
                                EmailSyncAdapterService.this, 0, intent,
                                PendingIntent.FLAG_ONE_SHOT);
                        final AlarmManager am = (AlarmManager)getSystemService(
                                Context.ALARM_SERVICE);
                        final long atTime = SystemClock.elapsedRealtime() +
                                SYNC_ERROR_BACKOFF_MILLIS;
                        am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, atTime, pi);
                    } else {
                        final PingTask pingHandler = new PingTask(service, account, amAccount,
                                this);
                        mPingHandlers.put(account.mId, pingHandler);
                        pingHandler.start();
                        // Whenever we have a running ping, make sure this service stays running.
                        service.startService(new Intent(service, EmailSyncAdapterService.class));
                    }
                }
                if (SCHEDULE_KICK) {
                    ContentResolver.addPeriodicSync(amAccount, EmailContent.AUTHORITY, extras,
                               KICK_SYNC_INTERVAL);
                }
            } else {
                if (pingSyncHandler != null) {
                    pingSyncHandler.stop();
                }
                if (SCHEDULE_KICK) {
                    ContentResolver.removePeriodicSync(amAccount, EmailContent.AUTHORITY, extras);
                }
            }
        }

        /**
         * Updates the synchronization bookkeeping when a sync is done.
         * @param account The account whose sync just finished.
         */
        public synchronized void syncComplete(final boolean lastSyncHadError,
                final Account account) {
            LogUtils.d(TAG, "syncComplete, err: " + lastSyncHadError);
            mPingHandlers.remove(account.mId);
            // Syncs can interrupt pings, so we should check if we need to start one now.
            // If the last sync had a fatal error, we will not immediately recreate the ping.
            // Instead, we'll set an alarm that will restart them in a few minutes. This prevents
            // a battery draining spin if there is some kind of protocol error or other
            // non-transient failure. (Actually, immediately pinging even for a transient error
            // isn't great)
            modifyPing(lastSyncHadError, account);
            stopServiceIfNoPings();
            notifyAll();
        }

        /**
         * Updates the synchronization bookkeeping when a ping is done. Also requests a ping-only
         * sync if necessary.
         * @param amAccount The {@link android.accounts.Account} for this account.
         * @param accountId The account whose ping just finished.
         * @param pingStatus The status value from {@link PingParser} for the last ping performed.
         *                   This cannot be one of the values that results in another ping, so this
         *                   function only needs to handle the terminal statuses.
         */
        public synchronized void pingComplete(final android.accounts.Account amAccount,
                final long accountId, final int pingStatus) {
            mPingHandlers.remove(accountId);

            // TODO: if (pingStatus == PingParser.STATUS_FAILED), notify UI.
            // TODO: if (pingStatus == PingParser.STATUS_REQUEST_TOO_MANY_FOLDERS), notify UI.

            // TODO: Should this just re-request ping if status < 0? This would do the wrong thing
            // for e.g. auth errors, though.
            if (pingStatus == EasOperation.RESULT_REQUEST_FAILURE ||
                    pingStatus == EasOperation.RESULT_OTHER_FAILURE) {
                // Request a new ping through the SyncManager. This will do the right thing if the
                // exception was due to loss of network connectivity, etc. (i.e. it will wait for
                // network to restore and then request it).
                EasPing.requestPing(amAccount);
            } else {
                stopServiceIfNoPings();
            }

            // TODO: It might be the case that only STATUS_CHANGES_FOUND and
            // STATUS_FOLDER_REFRESH_NEEDED need to notifyAll(). Think this through.
            notifyAll();
        }

    }
    private final SyncHandlerSynchronizer mSyncHandlerMap = new SyncHandlerSynchronizer();

    /**
     * The binder for IEmailService.
     */
    private final IEmailService.Stub mBinder = new IEmailService.Stub() {

        private String getEmailAddressForAccount(final long accountId) {
            final String emailAddress = Utility.getFirstRowString(EmailSyncAdapterService.this,
                    Account.CONTENT_URI, ACCOUNT_EMAIL_PROJECTION, Account.ID_SELECTION,
                    new String[] {Long.toString(accountId)}, null, 0);
            if (emailAddress == null) {
                LogUtils.e(TAG, "Could not find email address for account %d", accountId);
            }
            return emailAddress;
        }

        @Override
        public Bundle validate(final HostAuth hostAuth) {
            LogUtils.d(TAG, "IEmailService.validate");
            if (mEasService != null) {
                try {
                    return mEasService.validate(hostAuth);
                } catch (final RemoteException re) {
                    LogUtils.e(TAG, re, "While asking EasService to handle validate");
                }
            }
            return new EasFolderSync(EmailSyncAdapterService.this, hostAuth).doValidate();
        }

        @Override
        public Bundle autoDiscover(final String username, final String password) {
            LogUtils.d(TAG, "IEmailService.autoDiscover");
            return new EasAutoDiscover(EmailSyncAdapterService.this, username, password)
                    .doAutodiscover();
        }

        @Override
        public void updateFolderList(final long accountId) {
            LogUtils.d(TAG, "IEmailService.updateFolderList: %d", accountId);
            if (mEasService != null) {
                try {
                    mEasService.updateFolderList(accountId);
                    return;
                } catch (final RemoteException re) {
                    LogUtils.e(TAG, re, "While asking EasService to updateFolderList");
                }
            }
            final String emailAddress = getEmailAddressForAccount(accountId);
            if (emailAddress != null) {
                final Bundle extras = new Bundle(1);
                extras.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true);
                ContentResolver.requestSync(new android.accounts.Account(
                        emailAddress, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE),
                        EmailContent.AUTHORITY, extras);
            }
        }

        @Override
        public void setLogging(final int flags) {
            // TODO: fix this?
            // Protocol logging
            Eas.setUserDebug(flags);
            // Sync logging
            //setUserDebug(flags);
        }

        @Override
        public void loadAttachment(final IEmailServiceCallback callback, final long attachmentId,
                final boolean background) {
            LogUtils.d(TAG, "IEmailService.loadAttachment: %d", attachmentId);
            // TODO: Prevent this from happening in parallel with a sync?
            EasAttachmentLoader.loadAttachment(EmailSyncAdapterService.this, attachmentId,
                    callback);
        }

        @Override
        public void sendMeetingResponse(final long messageId, final int response) {
            LogUtils.d(TAG, "IEmailService.sendMeetingResponse: %d, %d", messageId, response);
            EasMeetingResponder.sendMeetingResponse(EmailSyncAdapterService.this, messageId,
                    response);
        }

        /**
         * Delete PIM (calendar, contacts) data for the specified account
         *
         * @param emailAddress the email address for the account whose data should be deleted
         */
        @Override
        public void deleteAccountPIMData(final String emailAddress) {
            LogUtils.d(TAG, "IEmailService.deleteAccountPIMData");
            if (emailAddress != null) {
                final Context context = EmailSyncAdapterService.this;
                EasContactsSyncHandler.wipeAccountFromContentProvider(context, emailAddress);
                EasCalendarSyncHandler.wipeAccountFromContentProvider(context, emailAddress);
            }
            // TODO: Run account reconciler?
        }

        @Override
        public int searchMessages(final long accountId, final SearchParams searchParams,
                final long destMailboxId) {
            LogUtils.d(TAG, "IEmailService.searchMessages");
            return Search.searchMessages(EmailSyncAdapterService.this, accountId, searchParams,
                    destMailboxId);
            // TODO: may need an explicit callback to replace the one to IEmailServiceCallback.
        }

        @Override
        public void sendMail(final long accountId) {}

        @Override
        public void pushModify(final long accountId) {}
    };

    public EmailSyncAdapterService() {
        super();
    }

    /**
     * {@link AsyncTask} for restarting pings for all accounts that need it.
     */
    private static final String PUSH_ACCOUNTS_SELECTION =
            AccountColumns.SYNC_INTERVAL + "=" + Integer.toString(Account.CHECK_INTERVAL_PUSH);
    private class RestartPingsTask extends AsyncTask<Void, Void, Void> {

        private final ContentResolver mContentResolver;
        private final SyncHandlerSynchronizer mSyncHandlerMap;
        private boolean mAnyAccounts;

        public RestartPingsTask(final ContentResolver contentResolver,
                final SyncHandlerSynchronizer syncHandlerMap) {
            mContentResolver = contentResolver;
            mSyncHandlerMap = syncHandlerMap;
        }

        @Override
        protected Void doInBackground(Void... params) {
            final Cursor c = mContentResolver.query(Account.CONTENT_URI,
                    Account.CONTENT_PROJECTION, PUSH_ACCOUNTS_SELECTION, null, null);
            if (c != null) {
                try {
                    mAnyAccounts = (c.getCount() != 0);
                    while (c.moveToNext()) {
                        final Account account = new Account();
                        account.restore(c);
                        mSyncHandlerMap.modifyPing(false, account);
                    }
                } finally {
                    c.close();
                }
            } else {
                mAnyAccounts = false;
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void result) {
            if (!mAnyAccounts) {
                LogUtils.d(TAG, "stopping for no accounts");
                EmailSyncAdapterService.this.stopSelf();
            }
        }
    }

    @Override
    public void onCreate() {
        LogUtils.v(TAG, "onCreate()");
        super.onCreate();
        startService(new Intent(this, EmailSyncAdapterService.class));
        // Restart push for all accounts that need it.
        new RestartPingsTask(getContentResolver(), mSyncHandlerMap).executeOnExecutor(
                AsyncTask.THREAD_POOL_EXECUTOR);
        if (DELEGATE_TO_EAS_SERVICE) {
            // TODO: This block is temporary to support the transition to EasService.
            mConnection = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name,  IBinder binder) {
                    mEasService = IEmailService.Stub.asInterface(binder);
                }

                @Override
                public void onServiceDisconnected(ComponentName name) {
                    mEasService = null;
                }
            };
            bindService(new Intent(this, EasService.class), mConnection, Context.BIND_AUTO_CREATE);
        }
    }

    @Override
    public void onDestroy() {
        LogUtils.v(TAG, "onDestroy()");
        super.onDestroy();
        for (PingTask task : mSyncHandlerMap.mPingHandlers.values()) {
            if (task != null) {
                task.stop();
            }
        }
        if (DELEGATE_TO_EAS_SERVICE) {
            // TODO: This block is temporary to support the transition to EasService.
            unbindService(mConnection);
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        if (intent.getAction().equals(Eas.EXCHANGE_SERVICE_INTENT_ACTION)) {
            return mBinder;
        }
        return super.onBind(intent);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent != null &&
                TextUtils.equals(Eas.EXCHANGE_SERVICE_INTENT_ACTION, intent.getAction())) {
            if (intent.getBooleanExtra(ServiceProxy.EXTRA_FORCE_SHUTDOWN, false)) {
                // We've been asked to forcibly shutdown. This happens if email accounts are
                // deleted, otherwise we can get errors if services are still running for
                // accounts that are now gone.
                // TODO: This is kind of a hack, it would be nicer if we could handle it correctly
                // if accounts disappear out from under us.
                LogUtils.d(TAG, "Forced shutdown, killing process");
                System.exit(-1);
            } else if (intent.getBooleanExtra(EXTRA_START_PING, false)) {
                LogUtils.d(TAG, "Restarting ping from alarm");
                // We've been woken up by an alarm to restart our ping. This happens if a sync
                // fails, rather that instantly starting the ping, we'll hold off for a few minutes.
                final android.accounts.Account account =
                        intent.getParcelableExtra(EXTRA_PING_ACCOUNT);
                EasPing.requestPing(account);
            }
        }
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    protected AbstractThreadedSyncAdapter getSyncAdapter() {
        synchronized (sSyncAdapterLock) {
            if (sSyncAdapter == null) {
                sSyncAdapter = new SyncAdapterImpl(this);
            }
            return sSyncAdapter;
        }
    }

    // TODO: Handle cancelSync() appropriately.
    private class SyncAdapterImpl extends AbstractThreadedSyncAdapter {
        public SyncAdapterImpl(Context context) {
            super(context, true /* autoInitialize */);
        }

        @Override
        public void onPerformSync(final android.accounts.Account acct, final Bundle extras,
                final String authority, final ContentProviderClient provider,
                final SyncResult syncResult) {
            if (LogUtils.isLoggable(TAG, Log.DEBUG)) {
                LogUtils.d(TAG, "onPerformSync: %s, %s", acct.toString(), extras.toString());
            } else {
                LogUtils.i(TAG, "onPerformSync: %s", extras.toString());
            }
            TempDirectory.setTempDirectory(EmailSyncAdapterService.this);

            // TODO: Perform any connectivity checks, bail early if we don't have proper network
            // for this sync operation.

            final Context context = getContext();
            final ContentResolver cr = context.getContentResolver();

            // Get the EmailContent Account
            final Account account;
            final Cursor accountCursor = cr.query(Account.CONTENT_URI, Account.CONTENT_PROJECTION,
                    AccountColumns.EMAIL_ADDRESS + "=?", new String[] {acct.name}, null);
            try {
                if (!accountCursor.moveToFirst()) {
                    // Could not load account.
                    // TODO: improve error handling.
                    LogUtils.w(TAG, "onPerformSync: could not load account");
                    return;
                }
                account = new Account();
                account.restore(accountCursor);
            } finally {
                accountCursor.close();
            }

            // Figure out what we want to sync, based on the extras and our account sync status.
            final boolean isInitialSync = EmailContent.isInitialSyncKey(account.mSyncKey);
            final long[] mailboxIds = Mailbox.getMailboxIdsFromBundle(extras);
            final int mailboxType = extras.getInt(Mailbox.SYNC_EXTRA_MAILBOX_TYPE,
                    Mailbox.TYPE_NONE);
            final boolean hasCallbackMethod =
                    extras.containsKey(EmailServiceStatus.SYNC_EXTRAS_CALLBACK_METHOD);
            if (hasCallbackMethod && mailboxIds != null) {
                for (long mailboxId : mailboxIds) {
                    EmailServiceStatus.syncMailboxStatus(cr, extras, mailboxId,
                            EmailServiceStatus.IN_PROGRESS, 0, UIProvider.LastSyncResult.SUCCESS);
                }
            }

            // Push only means this sync request should only refresh the ping (either because
            // settings changed, or we need to restart it for some reason).
            final boolean pushOnly = Mailbox.isPushOnlyExtras(extras);
            // Account only means just do a FolderSync.
            final boolean accountOnly = Mailbox.isAccountOnlyExtras(extras);

            // A "full sync" means that we didn't request a more specific type of sync.
            final boolean isFullSync = (!pushOnly && !accountOnly && mailboxIds == null &&
                    mailboxType == Mailbox.TYPE_NONE);

            // A FolderSync is necessary for full sync, initial sync, and account only sync.
            final boolean isFolderSync = (isFullSync || isInitialSync || accountOnly);

            // If we're just twiddling the push, we do the lightweight thing and bail early.
            if (pushOnly && !isFolderSync) {
                mSyncHandlerMap.modifyPing(false, account);
                LogUtils.d(TAG, "onPerformSync: mailbox push only");
                return;
            }

            // Do the bookkeeping for starting a sync, including stopping a ping if necessary.
            mSyncHandlerMap.startSync(account.mId);

            // Perform a FolderSync if necessary.
            // TODO: We permit FolderSync even during security hold, because it's necessary to
            // resolve some holds. Ideally we would only do it for the holds that require it.
            if (isFolderSync) {
                final EasFolderSync folderSync = new EasFolderSync(context, account);
                folderSync.doFolderSync(syncResult);
            }

            boolean lastSyncHadError = false;

            if ((account.mFlags & Account.FLAGS_SECURITY_HOLD) == 0) {
                // Perform email upsync for this account. Moves first, then state changes.
                if (!isInitialSync) {
                    EasMoveItems move = new EasMoveItems(context, account);
                    move.upsyncMovedMessages(syncResult);
                    // TODO: EasSync should eventually handle both up and down; for now, it's used
                    // purely for upsync.
                    EasSync upsync = new EasSync(context, account);
                    upsync.upsync(syncResult);
                }

                // TODO: Should we refresh account here? It may have changed while waiting for any
                // pings to stop. It may not matter since the things that may have been twiddled
                // might not affect syncing.

                if (mailboxIds != null) {
                    long numIoExceptions = 0;
                    long numAuthExceptions = 0;
                    // Sync the mailbox that was explicitly requested.
                    for (final long mailboxId : mailboxIds) {
                        final boolean success = syncMailbox(context, cr, acct, account, mailboxId,
                                extras, syncResult, null, true);
                        if (!success) {
                            lastSyncHadError = true;
                        }
                        if (hasCallbackMethod) {
                            final int result;
                            if (syncResult.hasError()) {
                                if (syncResult.stats.numIoExceptions > numIoExceptions) {
                                    result = UIProvider.LastSyncResult.CONNECTION_ERROR;
                                    numIoExceptions = syncResult.stats.numIoExceptions;
                                } else if (syncResult.stats.numAuthExceptions> numAuthExceptions) {
                                    result = UIProvider.LastSyncResult.AUTH_ERROR;
                                    numAuthExceptions= syncResult.stats.numAuthExceptions;
                                }  else {
                                    result = UIProvider.LastSyncResult.INTERNAL_ERROR;
                                }
                            } else {
                                result = UIProvider.LastSyncResult.SUCCESS;
                            }
                            EmailServiceStatus.syncMailboxStatus(
                                    cr, extras, mailboxId,EmailServiceStatus.SUCCESS, 0, result);
                        }
                    }
                } else if (!accountOnly && !pushOnly) {
                    // We have to sync multiple folders.
                    final Cursor c;
                    if (isFullSync) {
                        // Full account sync includes all mailboxes that participate in system sync.
                        c = Mailbox.getMailboxIdsForSync(cr, account.mId);
                    } else {
                        // Type-filtered sync should only get the mailboxes of a specific type.
                        c = Mailbox.getMailboxIdsForSyncByType(cr, account.mId, mailboxType);
                    }
                    if (c != null) {
                        try {
                            final HashSet<String> authsToSync = getAuthsToSync(acct);
                            while (c.moveToNext()) {
                                boolean success = syncMailbox(context, cr, acct, account,
                                        c.getLong(0), extras, syncResult, authsToSync, false);
                                if (!success) {
                                    lastSyncHadError = true;
                                }
                            }
                        } finally {
                            c.close();
                        }
                    }
                }
            }

            // Clean up the bookkeeping, including restarting ping if necessary.
            mSyncHandlerMap.syncComplete(lastSyncHadError, account);

            // TODO: It may make sense to have common error handling here. Two possible mechanisms:
            // 1) performSync return value can signal some useful info.
            // 2) syncResult can contain useful info.
            LogUtils.d(TAG, "onPerformSync: finished");
        }

        /**
         * Update the mailbox's sync status with the provider and, if we're finished with the sync,
         * write the last sync time as well.
         * @param context Our {@link Context}.
         * @param mailbox The mailbox whose sync status to update.
         * @param cv A {@link ContentValues} object to use for updating the provider.
         * @param syncStatus The status for the current sync.
         */
        private void updateMailbox(final Context context, final Mailbox mailbox,
                final ContentValues cv, final int syncStatus) {
            cv.put(Mailbox.UI_SYNC_STATUS, syncStatus);
            if (syncStatus == EmailContent.SYNC_STATUS_NONE) {
                cv.put(Mailbox.SYNC_TIME, System.currentTimeMillis());
            }
            mailbox.update(context, cv);
        }

        private boolean syncMailbox(final Context context, final ContentResolver cr,
                final android.accounts.Account acct, final Account account, final long mailboxId,
                final Bundle extras, final SyncResult syncResult, final HashSet<String> authsToSync,
                final boolean isMailboxSync) {
            final Mailbox mailbox = Mailbox.restoreMailboxWithId(context, mailboxId);
            if (mailbox == null) {
                return false;
            }

            if (mailbox.mAccountKey != account.mId) {
                LogUtils.e(TAG, "Mailbox does not match account: %s, %s", acct.toString(),
                        extras.toString());
                return false;
            }
            if (authsToSync != null && !authsToSync.contains(Mailbox.getAuthority(mailbox.mType))) {
                // We are asking for an account sync, but this mailbox type is not configured for
                // sync. Do NOT treat this as a sync error for ping backoff purposes.
                return true;
            }

            if (mailbox.mType == Mailbox.TYPE_DRAFTS) {
                // TODO: Because we don't have bidirectional sync working, trying to downsync
                // the drafts folder is confusing. b/11158759
                // For now, just disable all syncing of DRAFTS type folders.
                // Automatic syncing should always be disabled, but we also stop it here to ensure
                // that we won't sync even if the user attempts to force a sync from the UI.
                // Do NOT treat as a sync error for ping backoff purposes.
                LogUtils.d(TAG, "Skipping sync of DRAFTS folder");
                return true;
            }
            final boolean success;
            // Non-mailbox syncs are whole account syncs initiated by the AccountManager and are
            // treated as background syncs.
            // TODO: Push will be treated as "user" syncs, and probably should be background.
            final ContentValues cv = new ContentValues(2);
            updateMailbox(context, mailbox, cv, isMailboxSync ?
                    EmailContent.SYNC_STATUS_USER : EmailContent.SYNC_STATUS_BACKGROUND);
            if (mailbox.mType == Mailbox.TYPE_OUTBOX) {
                final EasOutboxSyncHandler outboxSyncHandler =
                        new EasOutboxSyncHandler(context, account, mailbox);
                outboxSyncHandler.performSync();
                success = true;
            } else if(mailbox.isSyncable()) {
                final EasSyncHandler syncHandler = EasSyncHandler.getEasSyncHandler(context, cr,
                        acct, account, mailbox, extras, syncResult);
                if (syncHandler != null) {
                    success = syncHandler.performSync(syncResult);
                } else {
                    success = false;
                }
            } else {
                success = false;
            }
            updateMailbox(context, mailbox, cv, EmailContent.SYNC_STATUS_NONE);

            if (syncResult.stats.numAuthExceptions > 0) {
                showAuthNotification(account.mId, account.mEmailAddress);
            }
            return success;
        }
    }
    private void showAuthNotification(long accountId, String accountName) {
        final PendingIntent pendingIntent = PendingIntent.getActivity(
                this,
                0,
                createAccountSettingsIntent(accountId, accountName),
                0);

        final Notification notification = new Builder(this)
                .setContentTitle(this.getString(string.auth_error_notification_title))
                .setContentText(this.getString(
                        string.auth_error_notification_text, accountName))
                .setSmallIcon(drawable.stat_notify_auth)
                .setContentIntent(pendingIntent)
                .setAutoCancel(true)
                .build();

        final NotificationManager nm = (NotificationManager)
                this.getSystemService(Context.NOTIFICATION_SERVICE);
        nm.notify("AuthError", 0, notification);
    }

    /**
     * Create and return an intent to display (and edit) settings for a specific account, or -1
     * for any/all accounts.  If an account name string is provided, a warning dialog will be
     * displayed as well.
     */
    public static Intent createAccountSettingsIntent(long accountId, String accountName) {
        final Uri.Builder builder = IntentUtilities.createActivityIntentUrlBuilder(
                IntentUtilities.PATH_SETTINGS);
        IntentUtilities.setAccountId(builder, accountId);
        IntentUtilities.setAccountName(builder, accountName);
        return new Intent(Intent.ACTION_EDIT, builder.build());
    }

    /**
     * Determine which content types are set to sync for an account.
     * @param account The account whose sync settings we're looking for.
     * @return The authorities for the content types we want to sync for account.
     */
    private static HashSet<String> getAuthsToSync(final android.accounts.Account account) {
        final HashSet<String> authsToSync = new HashSet();
        if (ContentResolver.getSyncAutomatically(account, EmailContent.AUTHORITY)) {
            authsToSync.add(EmailContent.AUTHORITY);
        }
        if (ContentResolver.getSyncAutomatically(account, CalendarContract.AUTHORITY)) {
            authsToSync.add(CalendarContract.AUTHORITY);
        }
        if (ContentResolver.getSyncAutomatically(account, ContactsContract.AUTHORITY)) {
            authsToSync.add(ContactsContract.AUTHORITY);
        }
        return authsToSync;
    }
}
