package android.content;

import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteDatabase;
import android.database.Cursor;
import android.net.Uri;
import android.accounts.AccountMonitor;
import android.accounts.AccountMonitorListener;
import android.provider.SyncConstValue;
import android.util.Config;
import android.util.Log;
import android.os.Bundle;
import android.text.TextUtils;

import java.util.Collections;
import java.util.Map;
import java.util.HashMap;
import java.util.Vector;
import java.util.ArrayList;

/**
 * A specialization of the ContentProvider that centralizes functionality
 * used by ContentProviders that are syncable. It also wraps calls to the ContentProvider
 * inside of database transactions.
 *
 * @hide
 */
public abstract class AbstractSyncableContentProvider extends SyncableContentProvider {
    private static final String TAG = "SyncableContentProvider";
    protected SQLiteOpenHelper mOpenHelper;
    protected SQLiteDatabase mDb;
    private final String mDatabaseName;
    private final int mDatabaseVersion;
    private final Uri mContentUri;
    private AccountMonitor mAccountMonitor;

    /** the account set in the last call to onSyncStart() */
    private String mSyncingAccount;

    private SyncStateContentProviderHelper mSyncState = null;

    private static final String[] sAccountProjection = new String[] {SyncConstValue._SYNC_ACCOUNT};

    private boolean mIsTemporary;

    private AbstractTableMerger mCurrentMerger = null;
    private boolean mIsMergeCancelled = false;

    private static final String SYNC_ACCOUNT_WHERE_CLAUSE = SyncConstValue._SYNC_ACCOUNT + "=?";

    protected boolean isTemporary() {
        return mIsTemporary;
    }

    /**
     * Indicates whether or not this ContentProvider contains a full
     * set of data or just diffs. This knowledge comes in handy when
     * determining how to incorporate the contents of a temporary
     * provider into a real provider.
     */
    private boolean mContainsDiffs;

    /**
     * Initializes the AbstractSyncableContentProvider
     * @param dbName the filename of the database
     * @param dbVersion the current version of the database schema
     * @param contentUri The base Uri of the syncable content in this provider
     */
    public AbstractSyncableContentProvider(String dbName, int dbVersion, Uri contentUri) {
        super();

        mDatabaseName = dbName;
        mDatabaseVersion = dbVersion;
        mContentUri = contentUri;
        mIsTemporary = false;
        setContainsDiffs(false);
        if (Config.LOGV) {
            Log.v(TAG, "created SyncableContentProvider " + this);
        }
    }

    /**
     * Close resources that must be closed. You must call this to properly release
     * the resources used by the AbstractSyncableContentProvider.
     */
    public void close() {
        if (mOpenHelper != null) {
            mOpenHelper.close();  // OK to call .close() repeatedly.
        }
    }

    /**
     * Override to create your schema and do anything else you need to do with a new database.
     * This is run inside a transaction (so you don't need to use one).
     * This method may not use getDatabase(), or call content provider methods, it must only
     * use the database handle passed to it.
     */
    protected void bootstrapDatabase(SQLiteDatabase db) {}

    /**
     * Override to upgrade your database from an old version to the version you specified.
     * Don't set the DB version; this will automatically be done after the method returns.
     * This method may not use getDatabase(), or call content provider methods, it must only
     * use the database handle passed to it.
     *
     * @param oldVersion version of the existing database
     * @param newVersion current version to upgrade to
     * @return true if the upgrade was lossless, false if it was lossy
     */
    protected abstract boolean upgradeDatabase(SQLiteDatabase db, int oldVersion, int newVersion);

    /**
     * Override to do anything (like cleanups or checks) you need to do after opening a database.
     * Does nothing by default.  This is run inside a transaction (so you don't need to use one).
     * This method may not use getDatabase(), or call content provider methods, it must only
     * use the database handle passed to it.
     */
    protected void onDatabaseOpened(SQLiteDatabase db) {}

    private class DatabaseHelper extends SQLiteOpenHelper {
        DatabaseHelper(Context context, String name) {
            // Note: context and name may be null for temp providers
            super(context, name, null, mDatabaseVersion);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            bootstrapDatabase(db);
            mSyncState.createDatabase(db);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            if (!upgradeDatabase(db, oldVersion, newVersion)) {
                mSyncState.discardSyncData(db, null /* all accounts */);
                getContext().getContentResolver().startSync(mContentUri, new Bundle());
            }
        }

        @Override
        public void onOpen(SQLiteDatabase db) {
            onDatabaseOpened(db);
            mSyncState.onDatabaseOpened(db);
        }
    }

    @Override
    public boolean onCreate() {
        if (isTemporary()) throw new IllegalStateException("onCreate() called for temp provider");
        mOpenHelper = new AbstractSyncableContentProvider.DatabaseHelper(getContext(),
                mDatabaseName);
        mSyncState = new SyncStateContentProviderHelper(mOpenHelper);

        AccountMonitorListener listener = new AccountMonitorListener() {
            public void onAccountsUpdated(String[] accounts) {
                // Some providers override onAccountsChanged(); give them a database to work with.
                mDb = mOpenHelper.getWritableDatabase();
                onAccountsChanged(accounts);
                TempProviderSyncAdapter syncAdapter = (TempProviderSyncAdapter)getSyncAdapter();
                if (syncAdapter != null) {
                    syncAdapter.onAccountsChanged(accounts);
                }
            }
        };
        mAccountMonitor = new AccountMonitor(getContext(), listener);

        return true;
    }

    /**
     * Get a non-persistent instance of this content provider.
     * You must call {@link #close} on the returned
     * SyncableContentProvider when you are done with it.
     *
     * @return a non-persistent content provider with the same layout as this
     * provider.
     */
    public AbstractSyncableContentProvider getTemporaryInstance() {
        AbstractSyncableContentProvider temp;
        try {
            temp = getClass().newInstance();
        } catch (InstantiationException e) {
            throw new RuntimeException("unable to instantiate class, "
                    + "this should never happen", e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(
                    "IllegalAccess while instantiating class, "
                            + "this should never happen", e);
        }

        // Note: onCreate() isn't run for the temp provider, and it has no Context.
        temp.mIsTemporary = true;
        temp.setContainsDiffs(true);
        temp.mOpenHelper = temp.new DatabaseHelper(null, null);
        temp.mSyncState = new SyncStateContentProviderHelper(temp.mOpenHelper);
        if (!isTemporary()) {
            mSyncState.copySyncState(
                    mOpenHelper.getReadableDatabase(),
                    temp.mOpenHelper.getWritableDatabase(),
                    getSyncingAccount());
        }
        return temp;
    }

    public SQLiteDatabase getDatabase() {
       if (mDb == null) mDb = mOpenHelper.getWritableDatabase();
       return mDb;
    }

    public boolean getContainsDiffs() {
        return mContainsDiffs;
    }

    public void setContainsDiffs(boolean containsDiffs) {
        if (containsDiffs && !isTemporary()) {
            throw new IllegalStateException(
                    "only a temporary provider can contain diffs");
        }
        mContainsDiffs = containsDiffs;
    }

    /**
     * Each subclass of this class should define a subclass of {@link
     * android.content.AbstractTableMerger} for each table they wish to merge.  It
     * should then override this method and return one instance of
     * each merger, in sequence.  Their {@link
     * android.content.AbstractTableMerger#merge merge} methods will be called, one at a
     * time, in the order supplied.
     *
     * <p>The default implementation returns an empty list, so that no
     * merging will occur.
     * @return A sequence of subclasses of {@link
     * android.content.AbstractTableMerger}, one for each table that should be merged.
     */
    protected Iterable<? extends AbstractTableMerger> getMergers() {
        return Collections.emptyList();
    }

    /**
     * <p>
     * Call mOpenHelper.getWritableDatabase() and mDb.beginTransaction().
     * {@link #endTransaction} MUST be called after calling this method.
     * Those methods should be used like this:
     * </p>
     *
     * <pre class="prettyprint">
     * boolean successful = false;
     * beginTransaction();
     * try {
     *     // Do something related to mDb
     *     successful = true;
     *     return ret;
     * } finally {
     *     endTransaction(successful);
     * }
     * </pre>
     *
     * @hide This method is dangerous from the view of database manipulation, though using
     * this makes batch insertion/update/delete much faster.
     */
    public final void beginTransaction() {
        mDb = mOpenHelper.getWritableDatabase();
        mDb.beginTransaction();
    }

    /**
     * <p>
     * Call mDb.endTransaction(). If successful is true, try to call
     * mDb.setTransactionSuccessful() before calling mDb.endTransaction().
     * This method MUST be used with {@link #beginTransaction()}.
     * </p>
     *
     * @hide This method is dangerous from the view of database manipulation, though using
     * this makes batch insertion/update/delete much faster.
     */
    public final void endTransaction(boolean successful) {
        try {
            if (successful) {
                // setTransactionSuccessful() must be called just once during opening the
                // transaction.
                mDb.setTransactionSuccessful();
            }
        } finally {
            mDb.endTransaction();
        }
    }

    @Override
    public final int update(final Uri uri, final ContentValues values,
            final String selection, final String[] selectionArgs) {
        boolean successful = false;
        beginTransaction();
        try {
            int ret = nonTransactionalUpdate(uri, values, selection, selectionArgs);
            successful = true;
            return  ret;
        } finally {
            endTransaction(successful);
        }
    }

    /**
     * @hide
     */
    public final int nonTransactionalUpdate(final Uri uri, final ContentValues values,
            final String selection, final String[] selectionArgs) {
        if (isTemporary() && mSyncState.matches(uri)) {
            int numRows = mSyncState.asContentProvider().update(
                    uri, values, selection, selectionArgs);
            return numRows;
        }

        int result = updateInternal(uri, values, selection, selectionArgs);
        if (!isTemporary() && result > 0) {
            getContext().getContentResolver().notifyChange(uri, null /* observer */,
                    changeRequiresLocalSync(uri));
        }

        return result;
    }

    @Override
    public final int delete(final Uri uri, final String selection,
            final String[] selectionArgs) {
        boolean successful = false;
        beginTransaction();
        try {
            int ret = nonTransactionalDelete(uri, selection, selectionArgs);
            successful = true;
            return ret;
        } finally {
            endTransaction(successful);
        }
    }

    /**
     * @hide
     */
    public final int nonTransactionalDelete(final Uri uri, final String selection,
            final String[] selectionArgs) {
        if (isTemporary() && mSyncState.matches(uri)) {
            int numRows = mSyncState.asContentProvider().delete(uri, selection, selectionArgs);
            return numRows;
        }
        int result = deleteInternal(uri, selection, selectionArgs);
        if (!isTemporary() && result > 0) {
            getContext().getContentResolver().notifyChange(uri, null /* observer */,
                    changeRequiresLocalSync(uri));
        }
        return result;
    }

    @Override
    public final Uri insert(final Uri uri, final ContentValues values) {
        boolean successful = false;
        beginTransaction();
        try {
            Uri ret = nonTransactionalInsert(uri, values);
            successful = true;
            return ret;
        } finally {
            endTransaction(successful);
        }
    }

    /**
     * @hide
     */
    public final Uri nonTransactionalInsert(final Uri uri, final ContentValues values) {
        if (isTemporary() && mSyncState.matches(uri)) {
            Uri result = mSyncState.asContentProvider().insert(uri, values);
            return result;
        }
        Uri result = insertInternal(uri, values);
        if (!isTemporary() && result != null) {
            getContext().getContentResolver().notifyChange(uri, null /* observer */,
                    changeRequiresLocalSync(uri));
        }
        return result;
    }

    @Override
    public final int bulkInsert(final Uri uri, final ContentValues[] values) {
        int size = values.length;
        int completed = 0;
        final boolean isSyncStateUri = mSyncState.matches(uri);
        mDb = mOpenHelper.getWritableDatabase();
        mDb.beginTransaction();
        try {
            for (int i = 0; i < size; i++) {
                Uri result;
                if (isTemporary() && isSyncStateUri) {
                    result = mSyncState.asContentProvider().insert(uri, values[i]);
                } else {
                    result = insertInternal(uri, values[i]);
                    mDb.yieldIfContended();
                }
                if (result != null) {
                    completed++;
                }
            }
            mDb.setTransactionSuccessful();
        } finally {
            mDb.endTransaction();
        }
        if (!isTemporary() && completed == size) {
            getContext().getContentResolver().notifyChange(uri, null /* observer */,
                    changeRequiresLocalSync(uri));
        }
        return completed;
    }

    /**
     * Check if changes to this URI can be syncable changes.
     * @param uri the URI of the resource that was changed
     * @return true if changes to this URI can be syncable changes, false otherwise
     */
    public boolean changeRequiresLocalSync(Uri uri) {
        return true;
    }

    @Override
    public final Cursor query(final Uri url, final String[] projection,
            final String selection, final String[] selectionArgs,
            final String sortOrder) {
        mDb = mOpenHelper.getReadableDatabase();
        if (isTemporary() && mSyncState.matches(url)) {
            return mSyncState.asContentProvider().query(
                    url, projection, selection,  selectionArgs, sortOrder);
        }
        return queryInternal(url, projection, selection, selectionArgs, sortOrder);
    }

    /**
     * Called right before a sync is started.
     *
     * @param context the sync context for the operation
     * @param account
     */
    public void onSyncStart(SyncContext context, String account) {
        if (TextUtils.isEmpty(account)) {
            throw new IllegalArgumentException("you passed in an empty account");
        }
        mSyncingAccount = account;
    }

    /**
     * Called right after a sync is completed
     *
     * @param context the sync context for the operation
     * @param success true if the sync succeeded, false if an error occurred
     */
    public void onSyncStop(SyncContext context, boolean success) {
    }

    /**
     * The account of the most recent call to onSyncStart()
     * @return the account
     */
    public String getSyncingAccount() {
        return mSyncingAccount;
    }

    /**
     * Merge diffs from a sync source with this content provider.
     *
     * @param context the SyncContext within which this merge is taking place
     * @param diffs A temporary content provider containing diffs from a sync
     *   source.
     * @param result a MergeResult that contains information about the merge, including
     *   a temporary content provider with the same layout as this provider containing
     * @param syncResult
     */
    public void merge(SyncContext context, SyncableContentProvider diffs,
            TempProviderSyncResult result, SyncResult syncResult) {
        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        db.beginTransaction();
        try {
            synchronized(this) {
                mIsMergeCancelled = false;
            }
            Iterable<? extends AbstractTableMerger> mergers = getMergers();
            try {
                for (AbstractTableMerger merger : mergers) {
                    synchronized(this) {
                        if (mIsMergeCancelled) break;
                        mCurrentMerger = merger;
                    }
                    merger.merge(context, getSyncingAccount(), diffs, result, syncResult, this);
                }
                if (mIsMergeCancelled) return;
                if (diffs != null) {
                    mSyncState.copySyncState(
                        ((AbstractSyncableContentProvider)diffs).mOpenHelper.getReadableDatabase(),
                        mOpenHelper.getWritableDatabase(),
                        getSyncingAccount());
                }
            } finally {
                synchronized (this) {
                    mCurrentMerger = null;
                }
            }
            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();
        }
    }


    /**
     * Invoked when the active sync has been canceled. Sets the sync state of this provider and
     * its merger to canceled.
     */
    public void onSyncCanceled() {
        synchronized (this) {
            mIsMergeCancelled = true;
            if (mCurrentMerger != null) {
                mCurrentMerger.onMergeCancelled();
            }
        }
    }


    public boolean isMergeCancelled() {
        return mIsMergeCancelled;
    }

    /**
     * Subclasses should override this instead of update(). See update()
     * for details.
     *
     * <p> This method is called within a acquireDbLock()/releaseDbLock() block,
     * which means a database transaction will be active during the call;
     */
    protected abstract int updateInternal(Uri url, ContentValues values,
            String selection, String[] selectionArgs);

    /**
     * Subclasses should override this instead of delete(). See delete()
     * for details.
     *
     * <p> This method is called within a acquireDbLock()/releaseDbLock() block,
     * which means a database transaction will be active during the call;
     */
    protected abstract int deleteInternal(Uri url, String selection, String[] selectionArgs);

    /**
     * Subclasses should override this instead of insert(). See insert()
     * for details.
     *
     * <p> This method is called within a acquireDbLock()/releaseDbLock() block,
     * which means a database transaction will be active during the call;
     */
    protected abstract Uri insertInternal(Uri url, ContentValues values);

    /**
     * Subclasses should override this instead of query(). See query()
     * for details.
     *
     * <p> This method is *not* called within a acquireDbLock()/releaseDbLock()
     * block for performance reasons. If an implementation needs atomic access
     * to the database the lock can be acquired then.
     */
    protected abstract Cursor queryInternal(Uri url, String[] projection,
            String selection, String[] selectionArgs, String sortOrder);

    /**
     * Make sure that there are no entries for accounts that no longer exist
     * @param accountsArray the array of currently-existing accounts
     */
    protected void onAccountsChanged(String[] accountsArray) {
        Map<String, Boolean> accounts = new HashMap<String, Boolean>();
        for (String account : accountsArray) {
            accounts.put(account, false);
        }
        accounts.put(SyncConstValue.NON_SYNCABLE_ACCOUNT, false);

        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        Map<String, String> tableMap = db.getSyncedTables();
        Vector<String> tables = new Vector<String>();
        tables.addAll(tableMap.keySet());
        tables.addAll(tableMap.values());

        db.beginTransaction();
        try {
            mSyncState.onAccountsChanged(accountsArray);
            for (String table : tables) {
                deleteRowsForRemovedAccounts(accounts, table,
                        SyncConstValue._SYNC_ACCOUNT);
            }
            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();
        }
    }

    /**
     * A helper method to delete all rows whose account is not in the accounts
     * map. The accountColumnName is the name of the column that is expected
     * to hold the account. If a row has an empty account it is never deleted.
     *
     * @param accounts a map of existing accounts
     * @param table the table to delete from
     * @param accountColumnName the name of the column that is expected
     * to hold the account.
     */
    protected void deleteRowsForRemovedAccounts(Map<String, Boolean> accounts,
            String table, String accountColumnName) {
        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        Cursor c = db.query(table, sAccountProjection, null, null,
                accountColumnName, null, null);
        try {
            while (c.moveToNext()) {
                String account = c.getString(0);
                if (TextUtils.isEmpty(account)) {
                    continue;
                }
                if (!accounts.containsKey(account)) {
                    int numDeleted;
                    numDeleted = db.delete(table, accountColumnName + "=?", new String[]{account});
                    if (Config.LOGV) {
                        Log.v(TAG, "deleted " + numDeleted
                                + " records from table " + table
                                + " for account " + account);
                    }
                }
            }
        } finally {
            c.close();
        }
    }

    /**
     * Called when the sync system determines that this provider should no longer
     * contain records for the specified account.
     */
    public void wipeAccount(String account) {
        SQLiteDatabase db = mOpenHelper.getWritableDatabase();
        Map<String, String> tableMap = db.getSyncedTables();
        ArrayList<String> tables = new ArrayList<String>();
        tables.addAll(tableMap.keySet());
        tables.addAll(tableMap.values());

        db.beginTransaction();

        try {
            // remove the SyncState data
            mSyncState.discardSyncData(db, account);

            // remove the data in the synced tables
            for (String table : tables) {
                db.delete(table, SYNC_ACCOUNT_WHERE_CLAUSE, new String[]{account});
            }
            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();
        }
    }

    /**
     * Retrieves the SyncData bytes for the given account. The byte array returned may be null.
     */
    public byte[] readSyncDataBytes(String account) {
        return mSyncState.readSyncDataBytes(mOpenHelper.getReadableDatabase(), account);
    }

    /**
     * Sets the SyncData bytes for the given account. The byte array may be null.
     */
    public void writeSyncDataBytes(String account, byte[] data) {
        mSyncState.writeSyncDataBytes(mOpenHelper.getWritableDatabase(), account, data);
    }
}
