package android.content;

import com.google.android.net.NetStats;

import android.database.SQLException;
import android.os.Bundle;
import android.os.Debug;
import android.os.Parcelable;
import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Config;
import android.util.EventLog;
import android.util.Log;
import android.util.TimingLogger;

/**
 * @hide
 */
public abstract class TempProviderSyncAdapter extends SyncAdapter {
    private static final String TAG = "Sync";

    private static final int MAX_GET_SERVER_DIFFS_LOOP_COUNT = 20;
    private static final int MAX_UPLOAD_CHANGES_LOOP_COUNT = 10;
    private static final int NUM_ALLOWED_SIMULTANEOUS_DELETIONS = 5;
    private static final long PERCENT_ALLOWED_SIMULTANEOUS_DELETIONS = 20;

    private volatile SyncableContentProvider mProvider;
    private volatile SyncThread mSyncThread = null;
    private volatile boolean mProviderSyncStarted;
    private volatile boolean mAdapterSyncStarted;
    
    public TempProviderSyncAdapter(SyncableContentProvider provider) {
        super();
        mProvider = provider;
    }

    /**
     * Used by getServerDiffs() to track the sync progress for a given
     * sync adapter. Implementations of SyncAdapter generally specialize
     * this class in order to track specific data about that SyncAdapter's
     * sync. If an implementation of SyncAdapter doesn't need to store
     * any data for a sync it may use TrivialSyncData.
     */
    public static abstract class SyncData implements Parcelable {

    }

    public final void setContext(Context context) {
        mContext = context;
    }

    /**
     * Retrieve the Context this adapter is running in.  Only available
     * once onSyncStarting() is called (not available from constructor).
     */
    final public Context getContext() {
        return mContext;
    }

    /**
     * Called right before a sync is started.
     *
     * @param context allows you to publish status and interact with the
     * @param account the account to sync
     * @param forced if true then the sync was forced
     * @param result information to track what happened during this sync attempt
     * @return true, if the sync was successfully started. One reason it can
     *   fail to start is if there is no user configured on the device.
     */
    public abstract void onSyncStarting(SyncContext context, String account, boolean forced,
            SyncResult result);

    /**
     * Called right after a sync is completed
     *
     * @param context allows you to publish status and interact with the
     *                user during interactive syncs.
     * @param success true if the sync suceeded, false if an error occured
     */
    public abstract void onSyncEnding(SyncContext context, boolean success);

    /**
     * Implement this to return true if the data in your content provider
     * is read only.
     */
    public abstract boolean isReadOnly();

    /**
     * Get diffs from the server since the last completed sync and put them
     * into a temporary provider.
     *
     * @param context allows you to publish status and interact with the
     *                user during interactive syncs.
     * @param syncData used to track the progress this client has made in syncing data
     *   from the server
     * @param tempProvider this is where the diffs should be stored
     * @param extras any extra data describing the sync that is desired
     * @param syncInfo sync adapter-specific data that is used during a single sync operation
     * @param syncResult information to track what happened during this sync attempt
     */
    public abstract void getServerDiffs(SyncContext context,
            SyncData syncData, SyncableContentProvider tempProvider,
            Bundle extras, Object syncInfo, SyncResult syncResult);

    /**
     * Send client diffs to the server, optionally receiving more diffs from the server
     *
     * @param context allows you to publish status and interact with the
     *                user during interactive syncs.
     * @param clientDiffs the diffs from the client
     * @param serverDiffs the SyncableContentProvider that should be populated with
*   the entries that were returned in response to an insert/update/delete request
*   to the server
     * @param syncResult information to track what happened during this sync attempt
     * @param dontActuallySendDeletes
     */
    public abstract void sendClientDiffs(SyncContext context,
            SyncableContentProvider clientDiffs,
            SyncableContentProvider serverDiffs, SyncResult syncResult,
            boolean dontActuallySendDeletes);

    /**
     * Reads the sync data from the ContentProvider
     * @param contentProvider the ContentProvider to read from
     * @return the SyncData for the provider. This may be null.
     */
    public SyncData readSyncData(SyncableContentProvider contentProvider) {
        return null;
    }

    /**
     * Create and return a new, empty SyncData object
     */
    public SyncData newSyncData() {
        return null;
    }

    /**
     * Stores the sync data in the Sync Stats database, keying it by
     * the account that was set in the last call to onSyncStarting()
     */
    public void writeSyncData(SyncData syncData, SyncableContentProvider contentProvider) {}

    /**
     * Indicate to the SyncAdapter that the last sync that was started has
     * been cancelled.
     */
    public abstract void onSyncCanceled();

    /**
     * Initializes the temporary content providers used during
     * {@link TempProviderSyncAdapter#sendClientDiffs}.
     * May copy relevant data from the underlying db into this provider so
     * joins, etc., can work.
     *
     * @param cp The ContentProvider to initialize.
     */
    protected void initTempProvider(SyncableContentProvider cp) {}

    protected Object createSyncInfo() {
        return null;
    }

    /**
     * Called when the accounts list possibly changed, to give the
     * SyncAdapter a chance to do any necessary bookkeeping, e.g.
     * to make sure that any required SubscribedFeeds subscriptions
     * exist.
     * @param accounts the list of accounts
     */
    public abstract void onAccountsChanged(String[] accounts);

    private Context mContext;

    private class SyncThread extends Thread {
        private final String mAccount;
        private final Bundle mExtras;
        private final SyncContext mSyncContext;
        private volatile boolean mIsCanceled = false;
        private long[] mNetStats;
        private final SyncResult mResult;

        SyncThread(SyncContext syncContext, String account, Bundle extras) {
            super("SyncThread");
            mAccount = account;
            mExtras = extras;
            mSyncContext = syncContext;
            mResult = new SyncResult();
        }

        void cancelSync() {
            mIsCanceled = true;
            if (mAdapterSyncStarted) onSyncCanceled();
            if (mProviderSyncStarted) mProvider.onSyncCanceled();
            // We may lose the last few sync events when canceling.  Oh well.
            long[] newNetStats = NetStats.getStats();
            logSyncDetails(newNetStats[0] - mNetStats[0], newNetStats[1] - mNetStats[1], mResult);
        }
        
        @Override
        public void run() {
            android.os.Process.setThreadPriority(android.os.Process.myTid(),
                    android.os.Process.THREAD_PRIORITY_BACKGROUND);
            mNetStats = NetStats.getStats();
            try {
                sync(mSyncContext, mAccount, mExtras);
            } catch (SQLException e) {
                Log.e(TAG, "Sync failed", e);
                mResult.databaseError = true;
            } finally {
                mSyncThread = null;
                if (!mIsCanceled) {
                    long[] newNetStats = NetStats.getStats();
                    logSyncDetails(newNetStats[0] - mNetStats[0], newNetStats[1] - mNetStats[1], mResult);
                    mSyncContext.onFinished(mResult);
                }
            }
        }

        private void sync(SyncContext syncContext, String account, Bundle extras) {
            mIsCanceled = false;

            mProviderSyncStarted = false;
            mAdapterSyncStarted = false;
            String message = null;

            boolean syncForced = extras.getBoolean(ContentResolver.SYNC_EXTRAS_FORCE, false);

            try {
                mProvider.onSyncStart(syncContext, account);
                mProviderSyncStarted = true;
                onSyncStarting(syncContext, account, syncForced, mResult);
                if (mResult.hasError()) {
                    message = "SyncAdapter failed while trying to start sync";
                    return;
                }
                mAdapterSyncStarted = true;
                if (mIsCanceled) {
                    return;
                }
                final String syncTracingEnabledValue = SystemProperties.get(TAG + "Tracing");
                final boolean syncTracingEnabled = !TextUtils.isEmpty(syncTracingEnabledValue);
                try {
                    if (syncTracingEnabled) {
                        System.gc();
                        System.gc();
                        Debug.startMethodTracing("synctrace." + System.currentTimeMillis());
                    }
                    runSyncLoop(syncContext, account, extras);
                } finally {
                    if (syncTracingEnabled) Debug.stopMethodTracing();
                }
                onSyncEnding(syncContext, !mResult.hasError());
                mAdapterSyncStarted = false;
                mProvider.onSyncStop(syncContext, true);
                mProviderSyncStarted = false;
            } finally {
                if (mAdapterSyncStarted) {
                    mAdapterSyncStarted = false;
                    onSyncEnding(syncContext, false);
                }
                if (mProviderSyncStarted) {
                    mProviderSyncStarted = false;
                    mProvider.onSyncStop(syncContext, false);
                }
                if (!mIsCanceled) {
                    if (message != null) syncContext.setStatusText(message);
                }
            }
        }

        private void runSyncLoop(SyncContext syncContext, String account, Bundle extras) {
            TimingLogger syncTimer = new TimingLogger(TAG + "Profiling", "sync");
            syncTimer.addSplit("start");
            int loopCount = 0;
            boolean tooManyGetServerDiffsAttempts = false;

            final boolean overrideTooManyDeletions =
                    extras.getBoolean(ContentResolver.SYNC_EXTRAS_OVERRIDE_TOO_MANY_DELETIONS,
                            false);
            final boolean discardLocalDeletions =
                    extras.getBoolean(ContentResolver.SYNC_EXTRAS_DISCARD_LOCAL_DELETIONS, false);
            boolean uploadOnly = extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD,
                    false /* default this flag to false */);
            SyncableContentProvider serverDiffs = null;
            TempProviderSyncResult result = new TempProviderSyncResult();
            try {
                if (!uploadOnly) {
                    /**
                     * This loop repeatedly calls SyncAdapter.getServerDiffs()
                     * (to get changes from the feed) followed by
                     * ContentProvider.merge() (to incorporate these changes
                     * into the provider), stopping when the SyncData returned
                     * from getServerDiffs() indicates that all the data was
                     * fetched.
                     */
                    while (!mIsCanceled) {
                        // Don't let a bad sync go forever
                        if (loopCount++ == MAX_GET_SERVER_DIFFS_LOOP_COUNT) {
                            Log.e(TAG, "runSyncLoop: Hit max loop count while getting server diffs "
                                    + getClass().getName());
                            // TODO: change the structure here to schedule a new sync
                            // with a backoff time, keeping track to be sure
                            // we don't keep doing this forever (due to some bug or
                            // mismatch between the client and the server)
                            tooManyGetServerDiffsAttempts = true;
                            break;
                        }

                        // Get an empty content provider to put the diffs into
                        if (serverDiffs != null) serverDiffs.close();
                        serverDiffs = mProvider.getTemporaryInstance();

                        // Get records from the server which will be put into the serverDiffs
                        initTempProvider(serverDiffs);
                        Object syncInfo = createSyncInfo();
                        SyncData syncData = readSyncData(serverDiffs);
                        // syncData will only be null if there was a demarshalling error
                        // while reading the sync data.
                        if (syncData == null) {
                            mProvider.wipeAccount(account);
                            syncData = newSyncData();
                        }
                        mResult.clear();
                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
                            Log.v(TAG, "runSyncLoop: running getServerDiffs using syncData "
                                    + syncData.toString());
                        }
                        getServerDiffs(syncContext, syncData, serverDiffs, extras, syncInfo,
                                mResult);

                        if (mIsCanceled) return;
                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
                            Log.v(TAG, "runSyncLoop: result: " + mResult);
                        }
                        if (mResult.hasError()) return;
                        if (mResult.partialSyncUnavailable) {
                            if (Config.LOGD) {
                                Log.d(TAG, "partialSyncUnavailable is set, setting "
                                        + "ignoreSyncData and retrying");
                            }
                            mProvider.wipeAccount(account);
                            continue;
                        }

                        // write the updated syncData back into the temp provider
                        writeSyncData(syncData, serverDiffs);

                        // apply the downloaded changes to the provider
                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
                            Log.v(TAG, "runSyncLoop: running merge");
                        }
                        mProvider.merge(syncContext, serverDiffs,
                                null /* don't return client diffs */, mResult);
                        if (mIsCanceled) return;
                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
                            Log.v(TAG, "runSyncLoop: result: " + mResult);
                        }

                        // if the server has no more changes then break out of the loop
                        if (!mResult.moreRecordsToGet) {
                            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                                Log.v(TAG, "runSyncLoop: fetched all data, moving on");
                            }
                            break;
                        }
                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
                            Log.v(TAG, "runSyncLoop: more data to fetch, looping");
                        }
                    }
                }

                /**
                 * This loop repeatedly calls ContentProvider.merge() followed
                 * by SyncAdapter.merge() until either indicate that there is
                 * no more work to do by returning null.
                 * <p>
                 * The initial ContentProvider.merge() returns a temporary
                 * ContentProvider that contains any local changes that need
                 * to be committed to the server.
                 * <p>
                 * The SyncAdapter.merge() calls upload the changes to the server
                 * and populates temporary provider (the serverDiffs) with the
                 * result.
                 * <p>
                 * Subsequent calls to ContentProvider.merge() incoporate the
                 * result of previous SyncAdapter.merge() calls into the
                 * real ContentProvider and again return a temporary
                 * ContentProvider that contains any local changes that need
                 * to be committed to the server.
                 */
                loopCount = 0;
                boolean readOnly = isReadOnly();
                long previousNumModifications = 0;
                if (serverDiffs != null) {
                    serverDiffs.close();
                    serverDiffs = null;
                }

                // If we are discarding local deletions then we need to redownload all the items
                // again (since some of them might have been deleted). We do this by deleting the
                // sync data for the current account by writing in a null one.
                if (discardLocalDeletions) {
                    serverDiffs = mProvider.getTemporaryInstance();
                    initTempProvider(serverDiffs);
                    writeSyncData(null, serverDiffs);
                }

                while (!mIsCanceled) {
                    if (Config.LOGV) {
                        Log.v(TAG, "runSyncLoop: Merging diffs from server to client");
                    }
                    if (result.tempContentProvider != null) {
                        result.tempContentProvider.close();
                        result.tempContentProvider = null;
                    }
                    mResult.clear();
                    mProvider.merge(syncContext, serverDiffs, readOnly ? null : result,
                            mResult);
                    if (mIsCanceled) return;
                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
                        Log.v(TAG, "runSyncLoop: result: " + mResult);
                    }

                    SyncableContentProvider clientDiffs =
                            readOnly ? null : result.tempContentProvider;
                    if (clientDiffs == null) {
                        // Nothing to commit back to the server
                        if (Config.LOGV) Log.v(TAG, "runSyncLoop: No client diffs");
                        break;
                    }

                    long numModifications = mResult.stats.numUpdates
                            + mResult.stats.numDeletes
                            + mResult.stats.numInserts;

                    // as long as we are making progress keep resetting the loop count
                    if (numModifications < previousNumModifications) {
                        loopCount = 0;
                    }
                    previousNumModifications = numModifications;

                    // Don't let a bad sync go forever
                    if (loopCount++ >= MAX_UPLOAD_CHANGES_LOOP_COUNT) {
                        Log.e(TAG, "runSyncLoop: Hit max loop count while syncing "
                                + getClass().getName());
                        mResult.tooManyRetries = true;
                        break;
                    }

                    if (!overrideTooManyDeletions && !discardLocalDeletions
                            && hasTooManyDeletions(mResult.stats)) {
                        if (Config.LOGD) {
                            Log.d(TAG, "runSyncLoop: Too many deletions were found in provider "
                                    + getClass().getName() + ", not doing any more updates");
                        }
                        long numDeletes = mResult.stats.numDeletes;
                        mResult.stats.clear();
                        mResult.tooManyDeletions = true;
                        mResult.stats.numDeletes = numDeletes;
                        break;
                    }

                    if (Config.LOGV) Log.v(TAG, "runSyncLoop: Merging diffs from client to server");
                    if (serverDiffs != null) serverDiffs.close();
                    serverDiffs = clientDiffs.getTemporaryInstance();
                    initTempProvider(serverDiffs);
                    mResult.clear();
                    sendClientDiffs(syncContext, clientDiffs, serverDiffs, mResult,
                            discardLocalDeletions);
                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
                        Log.v(TAG, "runSyncLoop: result: " + mResult);
                    }

                    if (!mResult.madeSomeProgress()) {
                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
                            Log.v(TAG, "runSyncLoop: No data from client diffs merge");
                        }
                        break;
                    }
                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
                        Log.v(TAG, "runSyncLoop: made some progress, looping");
                    }
                }

                // add in any status codes that we saved from earlier
                mResult.tooManyRetries |= tooManyGetServerDiffsAttempts;
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.v(TAG, "runSyncLoop: final result: " + mResult);
                }
            } finally {
                // do this in the finally block to guarantee that is is set and not overwritten
                if (discardLocalDeletions) {
                    mResult.fullSyncRequested = true;
                }
                if (serverDiffs != null) serverDiffs.close();
                if (result.tempContentProvider != null) result.tempContentProvider.close();
                syncTimer.addSplit("stop");
                syncTimer.dumpToLog();
            }
        }
    }

    /**
     * Logs details on the sync.
     * Normally this will be overridden by a subclass that will provide
     * provider-specific details.
     * 
     * @param bytesSent number of bytes the sync sent over the network
     * @param bytesReceived number of bytes the sync received over the network
     * @param result The SyncResult object holding info on the sync
     */
    protected void logSyncDetails(long bytesSent, long bytesReceived, SyncResult result) {
        EventLog.writeEvent(SyncAdapter.LOG_SYNC_DETAILS, TAG, bytesSent, bytesReceived, "");
    }

    public void startSync(SyncContext syncContext, String account, Bundle extras) {
        if (mSyncThread != null) {
            syncContext.onFinished(SyncResult.ALREADY_IN_PROGRESS);
            return;
        }

        mSyncThread = new SyncThread(syncContext, account, extras);
        mSyncThread.start();
    }

    public void cancelSync() {
        if (mSyncThread != null) {
            mSyncThread.cancelSync();
        }
    }

    protected boolean hasTooManyDeletions(SyncStats stats) {
        long numEntries = stats.numEntries;
        long numDeletedEntries = stats.numDeletes;

        long percentDeleted = (numDeletedEntries == 0)
                ? 0
                : (100 * numDeletedEntries /
                        (numEntries + numDeletedEntries));
        boolean tooManyDeletions =
                (numDeletedEntries > NUM_ALLOWED_SIMULTANEOUS_DELETIONS)
                && (percentDeleted > PERCENT_ALLOWED_SIMULTANEOUS_DELETIONS);
        return tooManyDeletions;
    }
}
