/*
 * Copyright (C) 2011 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.inputmethod.dictionarypack;

import android.app.DownloadManager;
import android.app.DownloadManager.Request;
import android.content.ContentValues;
import android.content.Context;
import android.content.res.Resources;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

import com.android.inputmethod.compat.DownloadManagerCompatUtils;
import com.android.inputmethod.latin.R;

import java.util.LinkedList;
import java.util.Queue;

/**
 * Object representing an upgrade from one state to another.
 *
 * This implementation basically encapsulates a list of Runnable objects. In the future
 * it may manage dependencies between them. Concretely, it does not use Runnable because the
 * actions need an argument.
 */
/*

The state of a word list follows the following scheme.

       |                                   ^
  MakeAvailable                            |
       |        .------------Forget--------'
       V        |
 STATUS_AVAILABLE  <-------------------------.
       |                                     |
StartDownloadAction                  FinishDeleteAction
       |                                     |
       V                                     |
STATUS_DOWNLOADING      EnableAction-- STATUS_DELETING
       |                     |               ^
InstallAfterDownloadAction   |               |
       |     .---------------'        StartDeleteAction
       |     |                               |
       V     V                               |
 STATUS_INSTALLED  <--EnableAction--   STATUS_DISABLED
                    --DisableAction-->

  It may also be possible that DisableAction or StartDeleteAction or
  DownloadAction run when the file is still downloading.  This cancels
  the download and returns to STATUS_AVAILABLE.
  Also, an UpdateDataAction may apply in any state. It does not affect
  the state in any way (nor type, local filename, id or version) but
  may update other attributes like description or remote filename.

  Forget is an DB maintenance action that removes the entry if it is not installed or disabled.
  This happens when the word list information disappeared from the server, or when a new version
  is available and we should forget about the old one.
*/
public final class ActionBatch {
    /**
     * A piece of update.
     *
     * Action is basically like a Runnable that takes an argument.
     */
    public interface Action {
        /**
         * Execute this action NOW.
         * @param context the context to get system services, resources, databases
         */
        public void execute(final Context context);
    }

    /**
     * An action that starts downloading an available word list.
     */
    public static final class StartDownloadAction implements Action {
        static final String TAG = "DictionaryProvider:" + StartDownloadAction.class.getSimpleName();

        private final String mClientId;
        // The data to download. May not be null.
        final WordListMetadata mWordList;
        final boolean mForceStartNow;
        public StartDownloadAction(final String clientId,
                final WordListMetadata wordList, final boolean forceStartNow) {
            Utils.l("New download action for client ", clientId, " : ", wordList);
            mClientId = clientId;
            mWordList = wordList;
            mForceStartNow = forceStartNow;
        }

        @Override
        public void execute(final Context context) {
            if (null == mWordList) { // This should never happen
                Log.e(TAG, "UpdateAction with a null parameter!");
                return;
            }
            Utils.l("Downloading word list");
            final SQLiteDatabase db = MetadataDbHelper.getDb(context, mClientId);
            final ContentValues values = MetadataDbHelper.getContentValuesByWordListId(db,
                    mWordList.mId, mWordList.mVersion);
            final int status = values.getAsInteger(MetadataDbHelper.STATUS_COLUMN);
            final DownloadManager manager =
                    (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
            if (MetadataDbHelper.STATUS_DOWNLOADING == status) {
                // The word list is still downloading. Cancel the download and revert the
                // word list status to "available".
                if (null != manager) {
                    // DownloadManager is disabled (or not installed?). We can't cancel - there
                    // is nothing we can do. We still need to mark the entry as available.
                    manager.remove(values.getAsLong(MetadataDbHelper.PENDINGID_COLUMN));
                }
                MetadataDbHelper.markEntryAsAvailable(db, mWordList.mId, mWordList.mVersion);
            } else if (MetadataDbHelper.STATUS_AVAILABLE != status) {
                // Should never happen
                Log.e(TAG, "Unexpected state of the word list '" + mWordList.mId + "' : " + status
                        + " for an upgrade action. Fall back to download.");
            }
            // Download it.
            Utils.l("Upgrade word list, downloading", mWordList.mRemoteFilename);

            // TODO: if DownloadManager is disabled or not installed, download by ourselves
            if (null == manager) return;

            // This is an upgraded word list: we should download it.
            final Uri uri = Uri.parse(mWordList.mRemoteFilename);
            final Request request = new Request(uri);

            final Resources res = context.getResources();
            if (!mForceStartNow) {
                if (DownloadManagerCompatUtils.hasSetAllowedOverMetered()) {
                    final boolean allowOverMetered;
                    switch (UpdateHandler.getDownloadOverMeteredSetting(context)) {
                    case UpdateHandler.DOWNLOAD_OVER_METERED_DISALLOWED:
                        // User said no: don't allow.
                        allowOverMetered = false;
                        break;
                    case UpdateHandler.DOWNLOAD_OVER_METERED_ALLOWED:
                        // User said yes: allow.
                        allowOverMetered = true;
                        break;
                    default: // UpdateHandler.DOWNLOAD_OVER_METERED_SETTING_UNKNOWN
                        // Don't know: use the default value from configuration.
                        allowOverMetered = res.getBoolean(R.bool.allow_over_metered);
                    }
                    DownloadManagerCompatUtils.setAllowedOverMetered(request, allowOverMetered);
                } else {
                    request.setAllowedNetworkTypes(Request.NETWORK_WIFI);
                }
                request.setAllowedOverRoaming(res.getBoolean(R.bool.allow_over_roaming));
            } // if mForceStartNow, then allow all network types and roaming, which is the default.
            request.setTitle(mWordList.mDescription);
            request.setNotificationVisibility(
                    res.getBoolean(R.bool.display_notification_for_auto_update)
                            ? Request.VISIBILITY_VISIBLE : Request.VISIBILITY_HIDDEN);
            request.setVisibleInDownloadsUi(
                    res.getBoolean(R.bool.dict_downloads_visible_in_download_UI));

            final long downloadId = UpdateHandler.registerDownloadRequest(manager, request, db,
                    mWordList.mId, mWordList.mVersion);
            Utils.l("Starting download of", uri, "with id", downloadId);
            PrivateLog.log("Starting download of " + uri + ", id : " + downloadId, context);
        }
    }

    /**
     * An action that updates the database to reflect the status of a newly installed word list.
     */
    public static final class InstallAfterDownloadAction implements Action {
        static final String TAG = "DictionaryProvider:"
                + InstallAfterDownloadAction.class.getSimpleName();
        private final String mClientId;
        // The state to upgrade from. May not be null.
        final ContentValues mWordListValues;

        public InstallAfterDownloadAction(final String clientId,
                final ContentValues wordListValues) {
            Utils.l("New InstallAfterDownloadAction for client ", clientId, " : ", wordListValues);
            mClientId = clientId;
            mWordListValues = wordListValues;
        }

        @Override
        public void execute(final Context context) {
            if (null == mWordListValues) {
                Log.e(TAG, "InstallAfterDownloadAction with a null parameter!");
                return;
            }
            final int status = mWordListValues.getAsInteger(MetadataDbHelper.STATUS_COLUMN);
            if (MetadataDbHelper.STATUS_DOWNLOADING != status) {
                final String id = mWordListValues.getAsString(MetadataDbHelper.WORDLISTID_COLUMN);
                Log.e(TAG, "Unexpected state of the word list '" + id + "' : " + status
                        + " for an InstallAfterDownload action. Bailing out.");
                return;
            }
            Utils.l("Setting word list as installed");
            final SQLiteDatabase db = MetadataDbHelper.getDb(context, mClientId);
            MetadataDbHelper.markEntryAsFinishedDownloadingAndInstalled(db, mWordListValues);
        }
    }

    /**
     * An action that enables an existing word list.
     */
    public static final class EnableAction implements Action {
        static final String TAG = "DictionaryProvider:" + EnableAction.class.getSimpleName();
        private final String mClientId;
        // The state to upgrade from. May not be null.
        final WordListMetadata mWordList;

        public EnableAction(final String clientId, final WordListMetadata wordList) {
            Utils.l("New EnableAction for client ", clientId, " : ", wordList);
            mClientId = clientId;
            mWordList = wordList;
        }

        @Override
        public void execute(final Context context) {
            if (null == mWordList) {
                Log.e(TAG, "EnableAction with a null parameter!");
                return;
            }
            Utils.l("Enabling word list");
            final SQLiteDatabase db = MetadataDbHelper.getDb(context, mClientId);
            final ContentValues values = MetadataDbHelper.getContentValuesByWordListId(db,
                    mWordList.mId, mWordList.mVersion);
            final int status = values.getAsInteger(MetadataDbHelper.STATUS_COLUMN);
            if (MetadataDbHelper.STATUS_DISABLED != status
                    && MetadataDbHelper.STATUS_DELETING != status) {
                Log.e(TAG, "Unexpected state of the word list '" + mWordList.mId + " : " + status
                      + " for an enable action. Cancelling");
                return;
            }
            MetadataDbHelper.markEntryAsEnabled(db, mWordList.mId, mWordList.mVersion);
        }
    }

    /**
     * An action that disables a word list.
     */
    public static final class DisableAction implements Action {
        static final String TAG = "DictionaryProvider:" + DisableAction.class.getSimpleName();
        private final String mClientId;
        // The word list to disable. May not be null.
        final WordListMetadata mWordList;
        public DisableAction(final String clientId, final WordListMetadata wordlist) {
            Utils.l("New Disable action for client ", clientId, " : ", wordlist);
            mClientId = clientId;
            mWordList = wordlist;
        }

        @Override
        public void execute(final Context context) {
            if (null == mWordList) { // This should never happen
                Log.e(TAG, "DisableAction with a null word list!");
                return;
            }
            Utils.l("Disabling word list : " + mWordList);
            final SQLiteDatabase db = MetadataDbHelper.getDb(context, mClientId);
            final ContentValues values = MetadataDbHelper.getContentValuesByWordListId(db,
                    mWordList.mId, mWordList.mVersion);
            final int status = values.getAsInteger(MetadataDbHelper.STATUS_COLUMN);
            if (MetadataDbHelper.STATUS_INSTALLED == status) {
                // Disabling an installed word list
                MetadataDbHelper.markEntryAsDisabled(db, mWordList.mId, mWordList.mVersion);
            } else {
                if (MetadataDbHelper.STATUS_DOWNLOADING != status) {
                    Log.e(TAG, "Unexpected state of the word list '" + mWordList.mId + "' : "
                            + status + " for a disable action. Fall back to marking as available.");
                }
                // The word list is still downloading. Cancel the download and revert the
                // word list status to "available".
                final DownloadManager manager =
                        (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
                if (null != manager) {
                    // If we can't cancel the download because DownloadManager is not available,
                    // we still need to mark the entry as available.
                    manager.remove(values.getAsLong(MetadataDbHelper.PENDINGID_COLUMN));
                }
                MetadataDbHelper.markEntryAsAvailable(db, mWordList.mId, mWordList.mVersion);
            }
        }
    }

    /**
     * An action that makes a word list available.
     */
    public static final class MakeAvailableAction implements Action {
        static final String TAG = "DictionaryProvider:" + MakeAvailableAction.class.getSimpleName();
        private final String mClientId;
        // The word list to make available. May not be null.
        final WordListMetadata mWordList;
        public MakeAvailableAction(final String clientId, final WordListMetadata wordlist) {
            Utils.l("New MakeAvailable action", clientId, " : ", wordlist);
            mClientId = clientId;
            mWordList = wordlist;
        }

        @Override
        public void execute(final Context context) {
            if (null == mWordList) { // This should never happen
                Log.e(TAG, "MakeAvailableAction with a null word list!");
                return;
            }
            final SQLiteDatabase db = MetadataDbHelper.getDb(context, mClientId);
            if (null != MetadataDbHelper.getContentValuesByWordListId(db,
                    mWordList.mId, mWordList.mVersion)) {
                Log.e(TAG, "Unexpected state of the word list '" + mWordList.mId + "' "
                        + " for a makeavailable action. Marking as available anyway.");
            }
            Utils.l("Making word list available : " + mWordList);
            // If mLocalFilename is null, then it's a remote file that hasn't been downloaded
            // yet, so we set the local filename to the empty string.
            final ContentValues values = MetadataDbHelper.makeContentValues(0,
                    MetadataDbHelper.TYPE_BULK, MetadataDbHelper.STATUS_AVAILABLE,
                    mWordList.mId, mWordList.mLocale, mWordList.mDescription,
                    null == mWordList.mLocalFilename ? "" : mWordList.mLocalFilename,
                    mWordList.mRemoteFilename, mWordList.mLastUpdate, mWordList.mChecksum,
                    mWordList.mFileSize, mWordList.mVersion, mWordList.mFormatVersion);
            PrivateLog.log("Insert 'available' record for " + mWordList.mDescription
                    + " and locale " + mWordList.mLocale, context);
            db.insert(MetadataDbHelper.METADATA_TABLE_NAME, null, values);
        }
    }

    /**
     * An action that marks a word list as pre-installed.
     *
     * This is almost the same as MakeAvailableAction, as it only inserts a line with parameters
     * received from outside.
     * Unlike MakeAvailableAction, the parameters are not received from a downloaded metadata file
     * but from the client directly; it marks a word list as being "installed" and not "available".
     * It also explicitly sets the filename to the empty string, so that we don't try to open
     * it on our side.
     */
    public static final class MarkPreInstalledAction implements Action {
        static final String TAG = "DictionaryProvider:"
                + MarkPreInstalledAction.class.getSimpleName();
        private final String mClientId;
        // The word list to mark pre-installed. May not be null.
        final WordListMetadata mWordList;
        public MarkPreInstalledAction(final String clientId, final WordListMetadata wordlist) {
            Utils.l("New MarkPreInstalled action", clientId, " : ", wordlist);
            mClientId = clientId;
            mWordList = wordlist;
        }

        @Override
        public void execute(final Context context) {
            if (null == mWordList) { // This should never happen
                Log.e(TAG, "MarkPreInstalledAction with a null word list!");
                return;
            }
            final SQLiteDatabase db = MetadataDbHelper.getDb(context, mClientId);
            if (null != MetadataDbHelper.getContentValuesByWordListId(db,
                    mWordList.mId, mWordList.mVersion)) {
                Log.e(TAG, "Unexpected state of the word list '" + mWordList.mId + "' "
                        + " for a markpreinstalled action. Marking as preinstalled anyway.");
            }
            Utils.l("Marking word list preinstalled : " + mWordList);
            // This word list is pre-installed : we don't have its file. We should reset
            // the local file name to the empty string so that we don't try to open it
            // accidentally. The remote filename may be set by the application if it so wishes.
            final ContentValues values = MetadataDbHelper.makeContentValues(0,
                    MetadataDbHelper.TYPE_BULK, MetadataDbHelper.STATUS_INSTALLED,
                    mWordList.mId, mWordList.mLocale, mWordList.mDescription,
                    "", mWordList.mRemoteFilename, mWordList.mLastUpdate,
                    mWordList.mChecksum, mWordList.mFileSize, mWordList.mVersion,
                    mWordList.mFormatVersion);
            PrivateLog.log("Insert 'preinstalled' record for " + mWordList.mDescription
                    + " and locale " + mWordList.mLocale, context);
            db.insert(MetadataDbHelper.METADATA_TABLE_NAME, null, values);
        }
    }

    /**
     * An action that updates information about a word list - description, locale etc
     */
    public static final class UpdateDataAction implements Action {
        static final String TAG = "DictionaryProvider:" + UpdateDataAction.class.getSimpleName();
        private final String mClientId;
        final WordListMetadata mWordList;
        public UpdateDataAction(final String clientId, final WordListMetadata wordlist) {
            Utils.l("New UpdateData action for client ", clientId, " : ", wordlist);
            mClientId = clientId;
            mWordList = wordlist;
        }

        @Override
        public void execute(final Context context) {
            if (null == mWordList) { // This should never happen
                Log.e(TAG, "UpdateDataAction with a null word list!");
                return;
            }
            final SQLiteDatabase db = MetadataDbHelper.getDb(context, mClientId);
            ContentValues oldValues = MetadataDbHelper.getContentValuesByWordListId(db,
                    mWordList.mId, mWordList.mVersion);
            if (null == oldValues) {
                Log.e(TAG, "Trying to update data about a non-existing word list. Bailing out.");
                return;
            }
            Utils.l("Updating data about a word list : " + mWordList);
            final ContentValues values = MetadataDbHelper.makeContentValues(
                    oldValues.getAsInteger(MetadataDbHelper.PENDINGID_COLUMN),
                    oldValues.getAsInteger(MetadataDbHelper.TYPE_COLUMN),
                    oldValues.getAsInteger(MetadataDbHelper.STATUS_COLUMN),
                    mWordList.mId, mWordList.mLocale, mWordList.mDescription,
                    oldValues.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN),
                    mWordList.mRemoteFilename, mWordList.mLastUpdate, mWordList.mChecksum,
                    mWordList.mFileSize, mWordList.mVersion, mWordList.mFormatVersion);
            PrivateLog.log("Updating record for " + mWordList.mDescription
                    + " and locale " + mWordList.mLocale, context);
            db.update(MetadataDbHelper.METADATA_TABLE_NAME, values,
                    MetadataDbHelper.WORDLISTID_COLUMN + " = ? AND "
                            + MetadataDbHelper.VERSION_COLUMN + " = ?",
                    new String[] { mWordList.mId, Integer.toString(mWordList.mVersion) });
        }
    }

    /**
     * An action that deletes the metadata about a word list if possible.
     *
     * This is triggered when a specific word list disappeared from the server, or when a fresher
     * word list is available and the old one was not installed.
     * If the word list has not been installed, it's possible to delete its associated metadata.
     * Otherwise, the settings are retained so that the user can still administrate it.
     */
    public static final class ForgetAction implements Action {
        static final String TAG = "DictionaryProvider:" + ForgetAction.class.getSimpleName();
        private final String mClientId;
        // The word list to remove. May not be null.
        final WordListMetadata mWordList;
        final boolean mHasNewerVersion;
        public ForgetAction(final String clientId, final WordListMetadata wordlist,
                final boolean hasNewerVersion) {
            Utils.l("New TryRemove action for client ", clientId, " : ", wordlist);
            mClientId = clientId;
            mWordList = wordlist;
            mHasNewerVersion = hasNewerVersion;
        }

        @Override
        public void execute(final Context context) {
            if (null == mWordList) { // This should never happen
                Log.e(TAG, "TryRemoveAction with a null word list!");
                return;
            }
            Utils.l("Trying to remove word list : " + mWordList);
            final SQLiteDatabase db = MetadataDbHelper.getDb(context, mClientId);
            final ContentValues values = MetadataDbHelper.getContentValuesByWordListId(db,
                    mWordList.mId, mWordList.mVersion);
            if (null == values) {
                Log.e(TAG, "Trying to update the metadata of a non-existing wordlist. Cancelling.");
                return;
            }
            final int status = values.getAsInteger(MetadataDbHelper.STATUS_COLUMN);
            if (mHasNewerVersion && MetadataDbHelper.STATUS_AVAILABLE != status) {
                // If we have a newer version of this word list, we should be here ONLY if it was
                // not installed - else we should be upgrading it.
                Log.e(TAG, "Unexpected status for forgetting a word list info : " + status
                        + ", removing URL to prevent re-download");
            }
            if (MetadataDbHelper.STATUS_INSTALLED == status
                    || MetadataDbHelper.STATUS_DISABLED == status
                    || MetadataDbHelper.STATUS_DELETING == status) {
                // If it is installed or disabled, then we cannot remove the entry lest the user
                // lose the ability to delete the file or otherwise administrate it. We will thus
                // leave it as is, but remove the URI from the database since it is not supposed to
                // be accessible any more.
                // If it is deleting and we don't have a new version, then we have to wait until
                // Android Keyboard actually has deleted it before we can remove its metadata.
                values.put(MetadataDbHelper.REMOTE_FILENAME_COLUMN, "");
                db.update(MetadataDbHelper.METADATA_TABLE_NAME, values,
                        MetadataDbHelper.WORDLISTID_COLUMN + " = ? AND "
                                + MetadataDbHelper.VERSION_COLUMN + " = ?",
                        new String[] { mWordList.mId, Integer.toString(mWordList.mVersion) });
            } else {
                // If it's AVAILABLE or DOWNLOADING or even UNKNOWN, delete the entry.
                db.delete(MetadataDbHelper.METADATA_TABLE_NAME,
                        MetadataDbHelper.WORDLISTID_COLUMN + " = ? AND "
                                + MetadataDbHelper.VERSION_COLUMN + " = ?",
                        new String[] { mWordList.mId, Integer.toString(mWordList.mVersion) });
            }
        }
    }

    /**
     * An action that sets the word list for deletion as soon as possible.
     *
     * This is triggered when the user requests deletion of a word list. This will mark it as
     * deleted in the database, and fire an intent for Android Keyboard to take notice and
     * reload its dictionaries right away if it is up. If it is not up now, then it will
     * delete the actual file the next time it gets up.
     * A file marked as deleted causes the content provider to supply a zero-sized file to
     * Android Keyboard, which will overwrite any existing file and provide no words for this
     * word list. This is not exactly a "deletion", since there is an actual file which takes up
     * a few bytes on the disk, but this allows to override a default dictionary with an empty
     * dictionary. This way, there is no need for the user to make a distinction between
     * dictionaries installed by default and add-on dictionaries.
     */
    public static final class StartDeleteAction implements Action {
        static final String TAG = "DictionaryProvider:" + StartDeleteAction.class.getSimpleName();
        private final String mClientId;
        // The word list to delete. May not be null.
        final WordListMetadata mWordList;
        public StartDeleteAction(final String clientId, final WordListMetadata wordlist) {
            Utils.l("New StartDelete action for client ", clientId, " : ", wordlist);
            mClientId = clientId;
            mWordList = wordlist;
        }

        @Override
        public void execute(final Context context) {
            if (null == mWordList) { // This should never happen
                Log.e(TAG, "StartDeleteAction with a null word list!");
                return;
            }
            Utils.l("Trying to delete word list : " + mWordList);
            final SQLiteDatabase db = MetadataDbHelper.getDb(context, mClientId);
            final ContentValues values = MetadataDbHelper.getContentValuesByWordListId(db,
                    mWordList.mId, mWordList.mVersion);
            if (null == values) {
                Log.e(TAG, "Trying to set a non-existing wordlist for removal. Cancelling.");
                return;
            }
            final int status = values.getAsInteger(MetadataDbHelper.STATUS_COLUMN);
            if (MetadataDbHelper.STATUS_DISABLED != status) {
                Log.e(TAG, "Unexpected status for deleting a word list info : " + status);
            }
            MetadataDbHelper.markEntryAsDeleting(db, mWordList.mId, mWordList.mVersion);
        }
    }

    /**
     * An action that validates a word list as deleted.
     *
     * This will restore the word list as available if it still is, or remove the entry if
     * it is not any more.
     */
    public static final class FinishDeleteAction implements Action {
        static final String TAG = "DictionaryProvider:" + FinishDeleteAction.class.getSimpleName();
        private final String mClientId;
        // The word list to delete. May not be null.
        final WordListMetadata mWordList;
        public FinishDeleteAction(final String clientId, final WordListMetadata wordlist) {
            Utils.l("New FinishDelete action for client", clientId, " : ", wordlist);
            mClientId = clientId;
            mWordList = wordlist;
        }

        @Override
        public void execute(final Context context) {
            if (null == mWordList) { // This should never happen
                Log.e(TAG, "FinishDeleteAction with a null word list!");
                return;
            }
            Utils.l("Trying to delete word list : " + mWordList);
            final SQLiteDatabase db = MetadataDbHelper.getDb(context, mClientId);
            final ContentValues values = MetadataDbHelper.getContentValuesByWordListId(db,
                    mWordList.mId, mWordList.mVersion);
            if (null == values) {
                Log.e(TAG, "Trying to set a non-existing wordlist for removal. Cancelling.");
                return;
            }
            final int status = values.getAsInteger(MetadataDbHelper.STATUS_COLUMN);
            if (MetadataDbHelper.STATUS_DELETING != status) {
                Log.e(TAG, "Unexpected status for finish-deleting a word list info : " + status);
            }
            final String remoteFilename =
                    values.getAsString(MetadataDbHelper.REMOTE_FILENAME_COLUMN);
            // If there isn't a remote filename any more, then we don't know where to get the file
            // from any more, so we remove the entry entirely. As a matter of fact, if the file was
            // marked DELETING but disappeared from the metadata on the server, it ended up
            // this way.
            if (TextUtils.isEmpty(remoteFilename)) {
                db.delete(MetadataDbHelper.METADATA_TABLE_NAME,
                        MetadataDbHelper.WORDLISTID_COLUMN + " = ? AND "
                                + MetadataDbHelper.VERSION_COLUMN + " = ?",
                        new String[] { mWordList.mId, Integer.toString(mWordList.mVersion) });
            } else {
                MetadataDbHelper.markEntryAsAvailable(db, mWordList.mId, mWordList.mVersion);
            }
        }
    }

    // An action batch consists of an ordered queue of Actions that can execute.
    private final Queue<Action> mActions;

    public ActionBatch() {
        mActions = new LinkedList<Action>();
    }

    public void add(final Action a) {
        mActions.add(a);
    }

    /**
     * Append all the actions of another action batch.
     * @param that the upgrade to merge into this one.
     */
    public void append(final ActionBatch that) {
        for (final Action a : that.mActions) {
            add(a);
        }
    }

    /**
     * Execute this batch.
     *
     * @param context the context for getting resources, databases, system services.
     * @param reporter a Reporter to send errors to.
     */
    public void execute(final Context context, final ProblemReporter reporter) {
        Utils.l("Executing a batch of actions");
        Queue<Action> remainingActions = mActions;
        while (!remainingActions.isEmpty()) {
            final Action a = remainingActions.poll();
            try {
                a.execute(context);
            } catch (Exception e) {
                if (null != reporter)
                    reporter.report(e);
            }
        }
    }
}
