/*
 * Copyright (C) 2006 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 android.content;

import android.database.Cursor;
import android.database.DatabaseUtils;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.Debug;
import android.provider.BaseColumns;
import static android.provider.SyncConstValue.*;
import android.text.TextUtils;
import android.util.Log;

/**
 * @hide
 */
public abstract class AbstractTableMerger
{
    private ContentValues mValues;

    protected SQLiteDatabase mDb;
    protected String mTable;
    protected Uri mTableURL;
    protected String mDeletedTable;
    protected Uri mDeletedTableURL;
    static protected ContentValues mSyncMarkValues;
    static private boolean TRACE;

    static {
        mSyncMarkValues = new ContentValues();
        mSyncMarkValues.put(_SYNC_MARK, 1);
        TRACE = false;
    }

    private static final String TAG = "AbstractTableMerger";
    private static final String[] syncDirtyProjection =
            new String[] {_SYNC_DIRTY, BaseColumns._ID, _SYNC_ID, _SYNC_VERSION};
    private static final String[] syncIdAndVersionProjection =
            new String[] {_SYNC_ID, _SYNC_VERSION};

    private volatile boolean mIsMergeCancelled;

    private static final String SELECT_MARKED = _SYNC_MARK + "> 0 and " + _SYNC_ACCOUNT + "=?";

    private static final String SELECT_BY_SYNC_ID_AND_ACCOUNT =
            _SYNC_ID +"=? and " + _SYNC_ACCOUNT + "=?";
    private static final String SELECT_BY_ID = BaseColumns._ID +"=?";

    private static final String SELECT_UNSYNCED = ""
            + _SYNC_DIRTY + " > 0 and (" + _SYNC_ACCOUNT + "=? or " + _SYNC_ACCOUNT + " is null)";

    public AbstractTableMerger(SQLiteDatabase database,
            String table, Uri tableURL, String deletedTable,
            Uri deletedTableURL)
    {
        mDb = database;
        mTable = table;
        mTableURL = tableURL;
        mDeletedTable = deletedTable;
        mDeletedTableURL = deletedTableURL;
        mValues = new ContentValues();
    }

    public abstract void insertRow(ContentProvider diffs,
            Cursor diffsCursor);
    public abstract void updateRow(long localPersonID,
            ContentProvider diffs, Cursor diffsCursor);
    public abstract void resolveRow(long localPersonID,
            String syncID, ContentProvider diffs, Cursor diffsCursor);

    /**
     * This is called when it is determined that a row should be deleted from the
     * ContentProvider. The localCursor is on a table from the local ContentProvider
     * and its current position is of the row that should be deleted. The localCursor
     * is only guaranteed to contain the BaseColumns.ID column so the implementation
     * of deleteRow() must query the database directly if other columns are needed.
     * <p>
     * It is the responsibility of the implementation of this method to ensure that the cursor
     * points to the next row when this method returns, either by calling Cursor.deleteRow() or
     * Cursor.next().
     *
     * @param localCursor The Cursor into the local table, which points to the row that
     *   is to be deleted.
     */
    public void deleteRow(Cursor localCursor) {
        localCursor.deleteRow();
    }

    /**
     * After {@link #merge} has completed, this method is called to send
     * notifications to {@link android.database.ContentObserver}s of changes
     * to the containing {@link ContentProvider}.  These notifications likely
     * do not want to request a sync back to the network.
     */
    protected abstract void notifyChanges();

    private static boolean findInCursor(Cursor cursor, int column, String id) {
        while (!cursor.isAfterLast() && !cursor.isNull(column)) {
            int comp = id.compareTo(cursor.getString(column));
            if (comp > 0) {
                cursor.moveToNext();
                continue;
            }
            return comp == 0;
        }
        return false;
    }

    public void onMergeCancelled() {
        mIsMergeCancelled = true;
    }

    /**
     * Carry out a merge of the given diffs, and add the results to
     * the given MergeResult.  If we are the first merge to find
     * client-side diffs, we'll use the given ContentProvider to
     * construct a temporary instance to hold them.
     */
    public void merge(final SyncContext context,
            final String account,
            final SyncableContentProvider serverDiffs,
            TempProviderSyncResult result,
            SyncResult syncResult, SyncableContentProvider temporaryInstanceFactory) {
        mIsMergeCancelled = false;
        if (serverDiffs != null) {
            if (!mDb.isDbLockedByCurrentThread()) {
                throw new IllegalStateException("this must be called from within a DB transaction");
            }
            mergeServerDiffs(context, account, serverDiffs, syncResult);
            notifyChanges();
        }

        if (result != null) {
            findLocalChanges(result, temporaryInstanceFactory, account, syncResult);
        }
        if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "merge complete");
    }

    /**
     * @hide this is public for testing purposes only
     */
    public void mergeServerDiffs(SyncContext context,
            String account, SyncableContentProvider serverDiffs, SyncResult syncResult) {
        boolean diffsArePartial = serverDiffs.getContainsDiffs();
        // mark the current rows so that we can distinguish these from new
        // inserts that occur during the merge
        mDb.update(mTable, mSyncMarkValues, null, null);
        if (mDeletedTable != null) {
            mDb.update(mDeletedTable, mSyncMarkValues, null, null);
        }

        // load the local database entries, so we can merge them with the server
        final String[] accountSelectionArgs = new String[]{account};
        Cursor localCursor = mDb.query(mTable, syncDirtyProjection,
                SELECT_MARKED, accountSelectionArgs, null, null,
                mTable + "." + _SYNC_ID);
        Cursor deletedCursor;
        if (mDeletedTable != null) {
            deletedCursor = mDb.query(mDeletedTable, syncIdAndVersionProjection,
                    SELECT_MARKED, accountSelectionArgs, null, null,
                    mDeletedTable + "." + _SYNC_ID);
        } else {
            deletedCursor =
                    mDb.rawQuery("select 'a' as _sync_id, 'b' as _sync_version limit 0", null);
        }

        // Apply updates and insertions from the server
        Cursor diffsCursor = serverDiffs.query(mTableURL,
                null, null, null, mTable + "." + _SYNC_ID);
        int deletedSyncIDColumn = deletedCursor.getColumnIndexOrThrow(_SYNC_ID);
        int deletedSyncVersionColumn = deletedCursor.getColumnIndexOrThrow(_SYNC_VERSION);
        int serverSyncIDColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_ID);
        int serverSyncVersionColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_VERSION);
        int serverSyncLocalIdColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_LOCAL_ID);

        String lastSyncId = null;
        int diffsCount = 0;
        int localCount = 0;
        localCursor.moveToFirst();
        deletedCursor.moveToFirst();
        while (diffsCursor.moveToNext()) {
            if (mIsMergeCancelled) {
                localCursor.close();
                deletedCursor.close();
                diffsCursor.close();
                return;
            }
            mDb.yieldIfContended();
            String serverSyncId = diffsCursor.getString(serverSyncIDColumn);
            String serverSyncVersion = diffsCursor.getString(serverSyncVersionColumn);
            long localRowId = 0;
            String localSyncVersion = null;

            diffsCount++;
            context.setStatusText("Processing " + diffsCount + "/"
                    + diffsCursor.getCount());
            if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "processing server entry " +
                    diffsCount + ", " + serverSyncId);

            if (TRACE) {
                if (diffsCount == 10) {
                    Debug.startMethodTracing("atmtrace");
                }
                if (diffsCount == 20) {
                    Debug.stopMethodTracing();
                }
            }

            boolean conflict = false;
            boolean update = false;
            boolean insert = false;

            if (Log.isLoggable(TAG, Log.VERBOSE)) {
                Log.v(TAG, "found event with serverSyncID " + serverSyncId);
            }
            if (TextUtils.isEmpty(serverSyncId)) {
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.e(TAG, "server entry doesn't have a serverSyncID");
                }
                continue;
            }

            // It is possible that the sync adapter wrote the same record multiple times,
            // e.g. if the same record came via multiple feeds. If this happens just ignore
            // the duplicate records.
            if (serverSyncId.equals(lastSyncId)) {
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.v(TAG, "skipping record with duplicate remote server id " + lastSyncId);
                }
                continue;
            }
            lastSyncId = serverSyncId;

            String localSyncID = null;
            boolean localSyncDirty = false;

            while (!localCursor.isAfterLast()) {
                if (mIsMergeCancelled) {
                    localCursor.deactivate();
                    deletedCursor.deactivate();
                    diffsCursor.deactivate();
                    return;
                }
                localCount++;
                localSyncID = localCursor.getString(2);

                // If the local record doesn't have a _sync_id then
                // it is new. Ignore it for now, we will send an insert
                // the the server later.
                if (TextUtils.isEmpty(localSyncID)) {
                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
                        Log.v(TAG, "local record " +
                                localCursor.getLong(1) +
                                " has no _sync_id, ignoring");
                    }
                    localCursor.moveToNext();
                    localSyncID = null;
                    continue;
                }

                int comp = serverSyncId.compareTo(localSyncID);

                // the local DB has a record that the server doesn't have
                if (comp > 0) {
                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
                        Log.v(TAG, "local record " +
                                localCursor.getLong(1) +
                                " has _sync_id " + localSyncID +
                                " that is < server _sync_id " + serverSyncId);
                    }
                    if (diffsArePartial) {
                        localCursor.moveToNext();
                    } else {
                        deleteRow(localCursor);
                        if (mDeletedTable != null) {
                            mDb.delete(mDeletedTable, _SYNC_ID +"=?", new String[] {localSyncID});
                        }
                        syncResult.stats.numDeletes++;
                        mDb.yieldIfContended();
                    }
                    localSyncID = null;
                    continue;
                }

                // the server has a record that the local DB doesn't have
                if (comp < 0) {
                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
                        Log.v(TAG, "local record " +
                                localCursor.getLong(1) +
                                " has _sync_id " + localSyncID +
                                " that is > server _sync_id " + serverSyncId);
                    }
                    localSyncID = null;
                }

                // the server and the local DB both have this record
                if (comp == 0) {
                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
                        Log.v(TAG, "local record " +
                                localCursor.getLong(1) +
                                " has _sync_id " + localSyncID +
                                " that matches the server _sync_id");
                    }
                    localSyncDirty = localCursor.getInt(0) != 0;
                    localRowId = localCursor.getLong(1);
                    localSyncVersion = localCursor.getString(3);
                    localCursor.moveToNext();
                }

                break;
            }

            // If this record is in the deleted table then update the server version
            // in the deleted table, if necessary, and then ignore it here.
            // We will send a deletion indication to the server down a
            // little further.
            if (findInCursor(deletedCursor, deletedSyncIDColumn, serverSyncId)) {
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.v(TAG, "remote record " + serverSyncId + " is in the deleted table");
                }
                final String deletedSyncVersion = deletedCursor.getString(deletedSyncVersionColumn);
                if (!TextUtils.equals(deletedSyncVersion, serverSyncVersion)) {
                    if (Log.isLoggable(TAG, Log.VERBOSE)) {
                        Log.v(TAG, "setting version of deleted record " + serverSyncId + " to "
                                + serverSyncVersion);
                    }
                    ContentValues values = new ContentValues();
                    values.put(_SYNC_VERSION, serverSyncVersion);
                    mDb.update(mDeletedTable, values, "_sync_id=?", new String[]{serverSyncId});
                }
                continue;
            }

            // If the _sync_local_id is present in the diffsCursor
            // then this record corresponds to a local record that was just
            // inserted into the server and the _sync_local_id is the row id
            // of the local record. Set these fields so that the next check
            // treats this record as an update, which will allow the
            // merger to update the record with the server's sync id
            if (!diffsCursor.isNull(serverSyncLocalIdColumn)) {
                localRowId = diffsCursor.getLong(serverSyncLocalIdColumn);
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.v(TAG, "the remote record with sync id " + serverSyncId
                            + " has a local sync id, " + localRowId);
                }
                localSyncID = serverSyncId;
                localSyncDirty = false;
                localSyncVersion = null;
            }

            if (!TextUtils.isEmpty(localSyncID)) {
                // An existing server item has changed
                boolean recordChanged = (localSyncVersion == null) ||
                        !serverSyncVersion.equals(localSyncVersion);
                if (recordChanged) {
                    if (localSyncDirty) {
                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
                            Log.v(TAG, "remote record " + serverSyncId
                                    + " conflicts with local _sync_id " + localSyncID
                                    + ", local _id " + localRowId);
                        }
                        conflict = true;
                    } else {
                        if (Log.isLoggable(TAG, Log.VERBOSE)) {
                             Log.v(TAG,
                                     "remote record " +
                                             serverSyncId +
                                     " updates local _sync_id " +
                                     localSyncID + ", local _id " +
                                     localRowId);
                         }
                         update = true;
                    }
                }
            } else {
                // the local db doesn't know about this record so add it
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.v(TAG, "remote record " + serverSyncId + " is new, inserting");
                }
                insert = true;
            }

            if (update) {
                updateRow(localRowId, serverDiffs, diffsCursor);
                syncResult.stats.numUpdates++;
            } else if (conflict) {
                resolveRow(localRowId, serverSyncId, serverDiffs, diffsCursor);
                syncResult.stats.numUpdates++;
            } else if (insert) {
                insertRow(serverDiffs, diffsCursor);
                syncResult.stats.numInserts++;
            }
        }

        if (Log.isLoggable(TAG, Log.VERBOSE)) {
            Log.v(TAG, "processed " + diffsCount + " server entries");
        }

        // If tombstones aren't in use delete any remaining local rows that
        // don't have corresponding server rows. Keep the rows that don't
        // have a sync id since those were created locally and haven't been
        // synced to the server yet.
        if (!diffsArePartial) {
            while (!localCursor.isAfterLast() && !TextUtils.isEmpty(localCursor.getString(2))) {
                if (mIsMergeCancelled) {
                    localCursor.deactivate();
                    deletedCursor.deactivate();
                    diffsCursor.deactivate();
                    return;
                }
                localCount++;
                final String localSyncId = localCursor.getString(2);
                if (Log.isLoggable(TAG, Log.VERBOSE)) {
                    Log.v(TAG,
                            "deleting local record " +
                                    localCursor.getLong(1) +
                                    " _sync_id " + localSyncId);
                }
                deleteRow(localCursor);
                if (mDeletedTable != null) {
                    mDb.delete(mDeletedTable, _SYNC_ID + "=?", new String[] {localSyncId});
                }
                syncResult.stats.numDeletes++;
                mDb.yieldIfContended();
            }
        }

        if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "checked " + localCount +
                " local entries");
        diffsCursor.deactivate();
        localCursor.deactivate();
        deletedCursor.deactivate();

        if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "applying deletions from the server");

        // Apply deletions from the server
        if (mDeletedTableURL != null) {
            diffsCursor = serverDiffs.query(mDeletedTableURL, null, null, null, null);

            while (diffsCursor.moveToNext()) {
                if (mIsMergeCancelled) {
                    diffsCursor.deactivate();
                    return;
                }
                // delete all rows that match each element in the diffsCursor
                fullyDeleteMatchingRows(diffsCursor, account, syncResult);
                mDb.yieldIfContended();
            }
            diffsCursor.deactivate();
        }
    }

    private void fullyDeleteMatchingRows(Cursor diffsCursor, String account,
            SyncResult syncResult) {
        int serverSyncIdColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_ID);
        final boolean deleteBySyncId = !diffsCursor.isNull(serverSyncIdColumn);

        // delete the rows explicitly so that the delete operation can be overridden
        final Cursor c;
        final String[] selectionArgs;
        if (deleteBySyncId) {
            selectionArgs = new String[]{diffsCursor.getString(serverSyncIdColumn), account};
            c = mDb.query(mTable, new String[]{BaseColumns._ID}, SELECT_BY_SYNC_ID_AND_ACCOUNT,
                    selectionArgs, null, null, null);
        } else {
            int serverSyncLocalIdColumn = diffsCursor.getColumnIndexOrThrow(_SYNC_LOCAL_ID);
            selectionArgs = new String[]{diffsCursor.getString(serverSyncLocalIdColumn)};
            c = mDb.query(mTable, new String[]{BaseColumns._ID}, SELECT_BY_ID, selectionArgs,
                    null, null, null);
        }
        try {
            c.moveToFirst();
            while (!c.isAfterLast()) {
                deleteRow(c); // advances the cursor
                syncResult.stats.numDeletes++;
            }
        } finally {
            c.deactivate();
        }
        if (deleteBySyncId && mDeletedTable != null) {
            mDb.delete(mDeletedTable, SELECT_BY_SYNC_ID_AND_ACCOUNT, selectionArgs);
        }
    }

    /**
     * Converts cursor into a Map, using the correct types for the values.
     */
    protected void cursorRowToContentValues(Cursor cursor, ContentValues map) {
        DatabaseUtils.cursorRowToContentValues(cursor, map);
    }

    /**
     * Finds local changes, placing the results in the given result object.
     * @param temporaryInstanceFactory As an optimization for the case
     * where there are no client-side diffs, mergeResult may initially
     * have no {@link android.content.TempProviderSyncResult#tempContentProvider}.  If this is
     * the first in the sequence of AbstractTableMergers to find
     * client-side diffs, it will use the given ContentProvider to
     * create a temporary instance and store its {@link
     * ContentProvider} in the mergeResult.
     * @param account
     * @param syncResult
     */
    private void findLocalChanges(TempProviderSyncResult mergeResult,
            SyncableContentProvider temporaryInstanceFactory, String account,
            SyncResult syncResult) {
        SyncableContentProvider clientDiffs = mergeResult.tempContentProvider;
        if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "generating client updates");

        final String[] accountSelectionArgs = new String[]{account};

        // Generate the client updates and insertions
        // Create a cursor for dirty records
        Cursor localChangesCursor = mDb.query(mTable, null, SELECT_UNSYNCED, accountSelectionArgs,
                null, null, null);
        long numInsertsOrUpdates = localChangesCursor.getCount();
        while (localChangesCursor.moveToNext()) {
            if (mIsMergeCancelled) {
                localChangesCursor.close();
                return;
            }
            if (clientDiffs == null) {
                clientDiffs = temporaryInstanceFactory.getTemporaryInstance();
            }
            mValues.clear();
            cursorRowToContentValues(localChangesCursor, mValues);
            mValues.remove("_id");
            DatabaseUtils.cursorLongToContentValues(localChangesCursor, "_id", mValues,
                    _SYNC_LOCAL_ID);
            clientDiffs.insert(mTableURL, mValues);
        }
        localChangesCursor.close();

        // Generate the client deletions
        if (Log.isLoggable(TAG, Log.VERBOSE)) Log.v(TAG, "generating client deletions");
        long numEntries = DatabaseUtils.queryNumEntries(mDb, mTable);
        long numDeletedEntries = 0;
        if (mDeletedTable != null) {
            Cursor deletedCursor = mDb.query(mDeletedTable,
                    syncIdAndVersionProjection,
                    _SYNC_ACCOUNT + "=? AND " + _SYNC_ID + " IS NOT NULL", accountSelectionArgs,
                    null, null, mDeletedTable + "." + _SYNC_ID);

            numDeletedEntries = deletedCursor.getCount();
            while (deletedCursor.moveToNext()) {
                if (mIsMergeCancelled) {
                    deletedCursor.close();
                    return;
                }
                if (clientDiffs == null) {
                    clientDiffs = temporaryInstanceFactory.getTemporaryInstance();
                }
                mValues.clear();
                DatabaseUtils.cursorRowToContentValues(deletedCursor, mValues);
                clientDiffs.insert(mDeletedTableURL, mValues);
            }
            deletedCursor.close();
        }

        if (clientDiffs != null) {
            mergeResult.tempContentProvider = clientDiffs;
        }
        syncResult.stats.numDeletes += numDeletedEntries;
        syncResult.stats.numUpdates += numInsertsOrUpdates;
        syncResult.stats.numEntries += numEntries;
    }
}
