/*
 * Copyright (C) 2014 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.Service;
import android.content.Context;
import android.content.Intent;
import android.support.v4.util.LongSparseArray;

import com.android.emailcommon.provider.Account;
import com.android.exchange.Eas;
import com.android.exchange.eas.EasPing;
import com.android.mail.utils.LogUtils;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Bookkeeping for handling synchronization between pings and other sync related operations.
 * "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 extended to IMAP.
 *
 * Basic rules of how these interact (note that all rules are per account):
 * - Only one operation (ping or other active sync operation) may run at a time.
 * - For shorthand, this class uses "sync" to mean "non-ping operation"; most such operations are
 *   sync ops, but some may not be (e.g. EAS Settings).
 * - Syncs can come from many sources concurrently; this class must serialize them.
 *
 * WHEN A SYNC STARTS:
 * - If nothing is running, proceed.
 * - If something is already running: wait until it's done.
 * - If the running thing is a ping task: interrupt it.
 *
 * WHEN A SYNC ENDS:
 * - If there are waiting syncs: signal one to proceed.
 * - If there are no waiting syncs and this account is configured for push: start a ping.
 * - Otherwise: This account is now idle.
 *
 * WHEN A PING TASK ENDS:
 * - A ping task loops until either it's interrupted by a sync (in which case, there will be one or
 *   more waiting syncs when the ping terminates), or encounters an error.
 * - If there are waiting syncs, and we were interrupted: signal one to proceed.
 * - If there are waiting syncs, but the ping terminated with an error: TODO: How to handle?
 * - If there are no waiting syncs and this account is configured for push: This means the ping task
 *   was terminated due to an error. Handle this by sending a sync request through the SyncManager
 *   that doesn't actually do any syncing, and whose only effect is to restart the ping.
 * - Otherwise: This account is now idle.
 *
 * WHEN AN ACCOUNT WANTS TO START OR CHANGE ITS PUSH BEHAVIOR:
 * - If nothing is running, start a new ping task.
 * - If a ping task is currently running, restart it with the new settings.
 * - If a sync is currently running, do nothing.
 *
 * WHEN AN ACCOUNT WANTS TO STOP GETTING PUSH:
 * - If nothing is running, do nothing.
 * - If a ping task is currently running, interrupt it.
 */
public class PingSyncSynchronizer {

    private static final String TAG = Eas.LOG_TAG;

    /**
     * This class handles bookkeeping for a single account.
     */
    private static class AccountSyncState {
        /** The currently running {@link PingTask}, or null if we aren't in the middle of a Ping. */
        private PingTask mPingTask;

        /**
         * Tracks whether this account wants to get push notifications, based on calls to
         * {@link #pushModify} and {@link #pushStop} (i.e. it tracks the last requested push state).
         */
        private boolean mPushEnabled;

        /**
         * The number of syncs that are blocked waiting for the current operation to complete.
         * Unlike Pings, sync operations do not start their own tasks and are assumed to run in
         * whatever thread calls into this class.
         */
        private int mSyncCount;

        /** The condition on which to block syncs that need to wait. */
        private Condition mCondition;

        public AccountSyncState(final Lock lock ) {
            mPingTask = null;
            mPushEnabled = false;
            mSyncCount = 0;
            mCondition = lock.newCondition();
        }

        /**
         * Update bookkeeping for a new sync:
         * - Stop the Ping if there is one.
         * - Wait until there's nothing running for this account before proceeding.
         */
        public void syncStart() {
            ++mSyncCount;
            if (mPingTask != null) {
                // Syncs are higher priority than Ping -- terminate the Ping.
                LogUtils.d(TAG, "Sync is pre-empting a ping");
                mPingTask.stop();
            }
            if (mPingTask != null || mSyncCount > 1) {
                // There’s something we need to wait for before we can proceed.
                try {
                    LogUtils.d(TAG, "Sync needs to wait: Ping: %s, Pending tasks: %d",
                            mPingTask != null ? "yes" : "no", mSyncCount);
                    mCondition.await();
                } catch (final InterruptedException e) {
                    // TODO: Handle this properly. Not catching it might be the right answer.
                }
            }
        }

        /**
         * Update bookkeeping when a sync completes. This includes signaling pending ops to
         * go ahead, or starting the ping if appropriate and there are no waiting ops.
         * @return Whether this account is now idle.
         */
        public boolean syncEnd(final Account account, final PingSyncSynchronizer synchronizer) {
            --mSyncCount;
            if (mSyncCount > 0) {
                LogUtils.d(TAG, "Signalling a pending sync to proceed.");
                mCondition.signal();
                return false;
            } else {
                if (mPushEnabled) {
                    final android.accounts.Account amAccount =
                            new android.accounts.Account(account.mEmailAddress,
                                    Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE);
                    mPingTask = new PingTask(synchronizer.getContext(), account, amAccount,
                            synchronizer);
                    mPingTask.start();
                    return false;
                }
            }
            return true;
        }

        /**
         * Update bookkeeping when the ping task terminates, including signaling any waiting ops.
         * @return Whether this account is now idle.
         */
        public boolean pingEnd(final android.accounts.Account amAccount) {
            mPingTask = null;
            if (mSyncCount > 0) {
                mCondition.signal();
                return false;
            } else {
                if (mPushEnabled) {
                    /**
                     * This situation only arises if we encountered some sort of error that
                     * stopped our ping but not due to a sync interruption. In this scenario
                     * we'll leverage the SyncManager to request a push only sync that will
                     * restart the ping when the time is right. */
                    EasPing.requestPing(amAccount);
                    return false;
                }
            }
            return true;
        }

        /**
         * Modifies or starts a ping for this account if no syncs are running.
         */
        public void pushModify(final Account account, final PingSyncSynchronizer synchronizer) {
            mPushEnabled = true;
            if (mSyncCount == 0) {
                if (mPingTask == null) {
                    // No ping, no running syncs -- start a new ping.
                    final android.accounts.Account amAccount =
                            new android.accounts.Account(account.mEmailAddress,
                                    Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE);
                    mPingTask = new PingTask(synchronizer.getContext(), account, amAccount,
                            synchronizer);
                    mPingTask.start();
                } else {
                    // Ping is already running, so tell it to restart to pick up any new params.
                    mPingTask.restart();
                }
            }
        }

        /**
         * Stop the currently running ping.
         */
        public void pushStop() {
            mPushEnabled = false;
            if (mPingTask != null) {
                mPingTask.stop();
            }
        }
    }

    /**
     * Lock for access to {@link #mAccountStateMap}, also used to create the {@link Condition}s for
     * each Account.
     */
    private final ReentrantLock mLock;

    /**
     * Map from account ID -> {@link AccountSyncState} for accounts with a running operation.
     * An account is in this map only when this account is active, i.e. has a ping or sync running
     * or pending. If an account is not in the middle of a sync and is not configured for push,
     * it will not be here. This allows to use emptiness of this map to know whether the service
     * needs to be running, and is also handy when debugging.
     */
    private final LongSparseArray<AccountSyncState> mAccountStateMap;

    /** The {@link Service} that this object is managing. */
    private final Service mService;

    public PingSyncSynchronizer(final Service service) {
        mLock = new ReentrantLock();
        mAccountStateMap = new LongSparseArray<AccountSyncState>();
        mService = service;
    }

    public Context getContext() {
        return mService;
    }

    /**
     * Gets the {@link AccountSyncState} for an account.
     * The caller must hold {@link #mLock}.
     * @param accountId The id for the account we're interested in.
     * @param createIfNeeded If true, create the account state if it's not already there.
     * @return The {@link AccountSyncState} for that account, or null if the account is idle and
     *         createIfNeeded is false.
     */
    private AccountSyncState getAccountState(final long accountId, final boolean createIfNeeded) {
        assert mLock.isHeldByCurrentThread();
        AccountSyncState state = mAccountStateMap.get(accountId);
        if (state == null && createIfNeeded) {
            LogUtils.d(TAG, "PSS adding account state for %d", accountId);
            state = new AccountSyncState(mLock);
            mAccountStateMap.put(accountId, state);
            // TODO: Is this too late to startService?
            if (mAccountStateMap.size() == 1) {
                LogUtils.i(TAG, "PSS added first account, starting service");
                mService.startService(new Intent(mService, mService.getClass()));
            }
        }
        return state;
    }

    /**
     * Remove an account from the map. If this was the last account, then also stop this service.
     * The caller must hold {@link #mLock}.
     * @param accountId The id for the account we're removing.
     */
    private void removeAccount(final long accountId) {
        assert mLock.isHeldByCurrentThread();
        LogUtils.d(TAG, "PSS removing account state for %d", accountId);
        mAccountStateMap.delete(accountId);
        if (mAccountStateMap.size() == 0) {
            LogUtils.i(TAG, "PSS removed last account; stopping service.");
            mService.stopSelf();
        }
    }

    public void syncStart(final long accountId) {
        mLock.lock();
        try {
            LogUtils.d(TAG, "PSS syncStart for account %d", accountId);
            final AccountSyncState accountState = getAccountState(accountId, true);
            accountState.syncStart();
        } finally {
            mLock.unlock();
        }
    }

    public void syncEnd(final Account account) {
        mLock.lock();
        try {
            final long accountId = account.getId();
            LogUtils.d(TAG, "PSS syncEnd for account %d", account.getId());
            final AccountSyncState accountState = getAccountState(accountId, false);
            if (accountState == null) {
                LogUtils.w(TAG, "PSS syncEnd for account %d but no state found", accountId);
                return;
            }
            if (accountState.syncEnd(account, this)) {
                removeAccount(accountId);
            }
        } finally {
            mLock.unlock();
        }
    }

    public void pingEnd(final long accountId, final android.accounts.Account amAccount) {
        mLock.lock();
        try {
            LogUtils.d(TAG, "PSS pingEnd for account %d", accountId);
            final AccountSyncState accountState = getAccountState(accountId, false);
            if (accountState == null) {
                LogUtils.w(TAG, "PSS pingEnd for account %d but no state found", accountId);
                return;
            }
            if (accountState.pingEnd(amAccount)) {
                removeAccount(accountId);
            }
        } finally {
            mLock.unlock();
        }
    }

    public void pushModify(final Account account) {
        mLock.lock();
        try {
            final long accountId = account.getId();
            LogUtils.d(TAG, "PSS pushModify for account %d", accountId);
            final AccountSyncState accountState = getAccountState(accountId, true);
            accountState.pushModify(account, this);
        } finally {
            mLock.unlock();
        }
    }

    public void pushStop(final long accountId) {
        mLock.lock();
        try {
            LogUtils.d(TAG, "PSS pushStop for account %d", accountId);
            final AccountSyncState accountState = getAccountState(accountId, false);
            if (accountState != null) {
                accountState.pushStop();
            }
        } finally {
            mLock.unlock();
        }
    }

    /**
     * Stops our service if our map contains no active accounts.
     */
    public void stopServiceIfIdle() {
        mLock.lock();
        try {
            LogUtils.d(TAG, "PSS stopIfIdle");
            if (mAccountStateMap.size() == 0) {
                LogUtils.i(TAG, "PSS has no active accounts; stopping service.");
                mService.stopSelf();
            }
        } finally {
            mLock.unlock();
        }
    }

    /**
     * Tells all running ping tasks to stop.
     */
    public void stopAllPings() {
        mLock.lock();
        try {
            for (int i = 0; i < mAccountStateMap.size(); ++i) {
                mAccountStateMap.valueAt(i).pushStop();
            }
        } finally {
            mLock.unlock();
        }
    }
}
