/*
 * 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.content.AbstractThreadedSyncAdapter;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SyncResult;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.IBinder;

import com.android.emailcommon.Api;
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.IEmailService;
import com.android.emailcommon.service.IEmailServiceCallback;
import com.android.emailcommon.service.SearchParams;
import com.android.emailcommon.utility.Utility;
import com.android.exchange.Eas;
import com.android.exchange.adapter.PingParser;
import com.android.exchange.adapter.Search;
import com.android.exchange.eas.EasFolderSync;
import com.android.exchange.eas.EasOperation;
import com.android.exchange.eas.EasPing;
import com.android.mail.providers.UIProvider.AccountCapabilities;
import com.android.mail.utils.LogUtils;

import java.util.HashMap;

/**
 * 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 = "EASEmailSyncAdaptSvc";

    /**
     * If sync extras do not include a mailbox id, then we want to perform a full sync.
     */
    private static final long FULL_ACCOUNT_SYNC = Mailbox.NO_MAILBOX;

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

    /**
     * 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 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;
            }

            // If a ping is currently running, tell it to restart to pick up new params.
            final PingTask pingSyncHandler = mPingHandlers.get(account.mId);
            if (pingSyncHandler != null) {
                pingSyncHandler.restart();
                return;
            }

            // If we're here, then there's neither a sync nor a ping running. Start a new ping.
            final EmailSyncAdapterService service = EmailSyncAdapterService.this;
            if (account.mSyncInterval == Account.CHECK_INTERVAL_PUSH) {
                // TODO: Also check if we have any mailboxes that WANT push.
                // This account needs to 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.
                final PingTask pingHandler = new PingTask(service, account, 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));
            }
        }

        /**
         * Updates the synchronization bookkeeping when a sync is done.
         * @param account The account whose sync just finished.
         */
        public synchronized void syncComplete(final Account account) {
            mPingHandlers.remove(account.mId);
            // Syncs can interrupt pings, so we should check if we need to start one now.
            modifyPing(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.

            if (pingStatus == EasOperation.RESULT_REQUEST_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");
            return new EasFolderSync(EmailSyncAdapterService.this, hostAuth).validate();
        }

        @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);
            final String emailAddress = getEmailAddressForAccount(accountId);
            if (emailAddress != null) {
                ContentResolver.requestSync(new android.accounts.Account(
                        emailAddress, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE),
                        EmailContent.AUTHORITY, new Bundle());
            }
        }

        @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 int getCapabilities(final Account acct) {
            String easVersion = acct.mProtocolVersion;
            Double easVersionDouble = 2.5D;
            if (easVersion != null) {
                try {
                    easVersionDouble = Double.parseDouble(easVersion);
                } catch (NumberFormatException e) {
                    // Stick with 2.5
                }
            }
            if (easVersionDouble >= 12.0D) {
                return AccountCapabilities.SYNCABLE_FOLDERS |
                        AccountCapabilities.SERVER_SEARCH |
                        AccountCapabilities.FOLDER_SERVER_SEARCH |
                        AccountCapabilities.SANITIZED_HTML |
                        AccountCapabilities.SMART_REPLY |
                        AccountCapabilities.SERVER_SEARCH |
                        AccountCapabilities.UNDO |
                        AccountCapabilities.DISCARD_CONVERSATION_DRAFTS;
            } else {
                return AccountCapabilities.SYNCABLE_FOLDERS |
                        AccountCapabilities.SANITIZED_HTML |
                        AccountCapabilities.SMART_REPLY |
                        AccountCapabilities.UNDO |
                        AccountCapabilities.DISCARD_CONVERSATION_DRAFTS;
            }
        }

        @Override
        public void serviceUpdated(final String emailAddress) {
            // Not required for EAS
        }

        // All IEmailService messages below are UNCALLED in Email.
        // TODO: Remove.
        @Deprecated
        @Override
        public int getApiLevel() {
            return Api.LEVEL;
        }

        @Deprecated
        @Override
        public void startSync(long mailboxId, boolean userRequest, int deltaMessageCount) {}

        @Deprecated
        @Override
        public void stopSync(long mailboxId) {}

        @Deprecated
        @Override
        public void loadMore(long messageId) {}

        @Deprecated
        @Override
        public boolean createFolder(long accountId, String name) {
            return false;
        }

        @Deprecated
        @Override
        public boolean deleteFolder(long accountId, String name) {
            return false;
        }

        @Deprecated
        @Override
        public boolean renameFolder(long accountId, String oldName, String newName) {
            return false;
        }

        @Deprecated
        @Override
        public void hostChanged(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(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() {
        super.onCreate();
        // Restart push for all accounts that need it.
        new RestartPingsTask(getContentResolver(), mSyncHandlerMap).executeOnExecutor(
                AsyncTask.THREAD_POOL_EXECUTOR);
    }

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

    @Override
    protected AbstractThreadedSyncAdapter newSyncAdapter() {
        return new SyncAdapterImpl(this);
    }

    // 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) {
            LogUtils.i(TAG, "performSync: extras = %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.
                    return;
                }
                account = new Account();
                account.restore(accountCursor);
            } finally {
                accountCursor.close();
            }
            // Get the mailbox that we want to sync.
            // There are four possibilities for Mailbox.SYNC_EXTRA_MAILBOX_ID:
            // 1) Mailbox.SYNC_EXTRA_MAILBOX_ID_PUSH_ONLY: Restart push if appropriate.
            // 2) Mailbox.SYNC_EXTRA_MAILBOX_ID_ACCOUNT_ONLY: Sync only the account data.
            // 3) Not present: Perform a full account sync.
            // 4) Non-negative value: It's an actual mailbox id, sync that mailbox only.
            final long mailboxId = extras.getLong(Mailbox.SYNC_EXTRA_MAILBOX_ID, FULL_ACCOUNT_SYNC);

            // If we're just twiddling the push, we do the lightweight thing and just bail.
            if (mailboxId == Mailbox.SYNC_EXTRA_MAILBOX_ID_PUSH_ONLY) {
                mSyncHandlerMap.modifyPing(account);
                return;
            }

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

            // TODO: Should we refresh the 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 (mailboxId == FULL_ACCOUNT_SYNC ||
                    mailboxId == Mailbox.SYNC_EXTRA_MAILBOX_ID_ACCOUNT_ONLY) {
                final EasFolderSync folderSync = new EasFolderSync(context, account);
                folderSync.doFolderSync(syncResult);

                if (mailboxId == FULL_ACCOUNT_SYNC) {
                    // Full account sync includes all mailboxes that participate in system sync.
                    final Cursor c = Mailbox.getMailboxIdsForSync(cr, account.mId);
                    if (c != null) {
                        try {
                            while (c.moveToNext()) {
                                syncMailbox(context, cr, acct, account, c.getLong(0), extras,
                                        syncResult, false);
                            }
                        } finally {
                            c.close();
                        }
                    }
                }
            } else {
                // Sync the mailbox that was explicitly requested.
                syncMailbox(context, cr, acct, account, mailboxId, extras, syncResult, true);
            }

            // Clean up the bookkeeping, including restarting ping if necessary.
            mSyncHandlerMap.syncComplete(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.
        }

        /**
         * 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 boolean isMailboxSync) {
            final Mailbox mailbox = Mailbox.restoreMailboxWithId(context, mailboxId);
            if (mailbox == null) {
                return false;
            }

            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);
                success = (syncHandler != null);
                if (syncHandler != null) {
                    syncHandler.performSync();
                }
            } else {
                success = false;
            }
            updateMailbox(context, mailbox, cv, EmailContent.SYNC_STATUS_NONE);
            return success;
        }
    }
}
