/*
 * 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.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.text.TextUtils;
import android.util.Log;

import com.android.inputmethod.latin.R;

import java.io.File;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeMap;

/**
 * Various helper functions for the state database
 */
public class MetadataDbHelper extends SQLiteOpenHelper {

    @SuppressWarnings("unused")
    private static final String TAG = MetadataDbHelper.class.getSimpleName();

    // This was the initial release version of the database. It should never be
    // changed going forward.
    private static final int METADATA_DATABASE_INITIAL_VERSION = 3;
    // This is the first released version of the database that implements CLIENTID. It is
    // used to identify the versions for upgrades. This should never change going forward.
    private static final int METADATA_DATABASE_VERSION_WITH_CLIENTID = 6;
    // This is the current database version. It should be updated when the database schema
    // gets updated. It is passed to the framework constructor of SQLiteOpenHelper, so
    // that's what the framework uses to track our database version.
    private static final int METADATA_DATABASE_VERSION = 6;

    private final static long NOT_A_DOWNLOAD_ID = -1;

    public static final String METADATA_TABLE_NAME = "pendingUpdates";
    static final String CLIENT_TABLE_NAME = "clients";
    public static final String PENDINGID_COLUMN = "pendingid"; // Download Manager ID
    public static final String TYPE_COLUMN = "type";
    public static final String STATUS_COLUMN = "status";
    public static final String LOCALE_COLUMN = "locale";
    public static final String WORDLISTID_COLUMN = "id";
    public static final String DESCRIPTION_COLUMN = "description";
    public static final String LOCAL_FILENAME_COLUMN = "filename";
    public static final String REMOTE_FILENAME_COLUMN = "url";
    public static final String DATE_COLUMN = "date";
    public static final String CHECKSUM_COLUMN = "checksum";
    public static final String FILESIZE_COLUMN = "filesize";
    public static final String VERSION_COLUMN = "version";
    public static final String FORMATVERSION_COLUMN = "formatversion";
    public static final String FLAGS_COLUMN = "flags";
    public static final int COLUMN_COUNT = 13;

    private static final String CLIENT_CLIENT_ID_COLUMN = "clientid";
    private static final String CLIENT_METADATA_URI_COLUMN = "uri";
    private static final String CLIENT_METADATA_ADDITIONAL_ID_COLUMN = "additionalid";
    private static final String CLIENT_LAST_UPDATE_DATE_COLUMN = "lastupdate";
    private static final String CLIENT_PENDINGID_COLUMN = "pendingid"; // Download Manager ID

    public static final String METADATA_DATABASE_NAME_STEM = "pendingUpdates";
    public static final String METADATA_UPDATE_DESCRIPTION = "metadata";

    public static final String DICTIONARIES_ASSETS_PATH = "dictionaries";

    // Statuses, for storing in the STATUS_COLUMN
    // IMPORTANT: The following are used as index arrays in ../WordListPreference
    // Do not change their values without updating the matched code.
    // Unknown status: this should never happen.
    public static final int STATUS_UNKNOWN = 0;
    // Available: this word list is available, but it is not downloaded (not downloading), because
    // it is set not to be used.
    public static final int STATUS_AVAILABLE = 1;
    // Downloading: this word list is being downloaded.
    public static final int STATUS_DOWNLOADING = 2;
    // Installed: this word list is installed and usable.
    public static final int STATUS_INSTALLED = 3;
    // Disabled: this word list is installed, but has been disabled by the user.
    public static final int STATUS_DISABLED = 4;
    // Deleting: the user marked this word list to be deleted, but it has not been yet because
    // Latin IME is not up yet.
    public static final int STATUS_DELETING = 5;

    // Types, for storing in the TYPE_COLUMN
    // This is metadata about what is available.
    public static final int TYPE_METADATA = 1;
    // This is a bulk file. It should replace older files.
    public static final int TYPE_BULK = 2;
    // This is an incremental update, expected to be small, and meaningless on its own.
    public static final int TYPE_UPDATE = 3;

    private static final String METADATA_TABLE_CREATE =
            "CREATE TABLE " + METADATA_TABLE_NAME + " ("
            + PENDINGID_COLUMN + " INTEGER, "
            + TYPE_COLUMN + " INTEGER, "
            + STATUS_COLUMN + " INTEGER, "
            + WORDLISTID_COLUMN + " TEXT, "
            + LOCALE_COLUMN + " TEXT, "
            + DESCRIPTION_COLUMN + " TEXT, "
            + LOCAL_FILENAME_COLUMN + " TEXT, "
            + REMOTE_FILENAME_COLUMN + " TEXT, "
            + DATE_COLUMN + " INTEGER, "
            + CHECKSUM_COLUMN + " TEXT, "
            + FILESIZE_COLUMN + " INTEGER, "
            + VERSION_COLUMN + " INTEGER,"
            + FORMATVERSION_COLUMN + " INTEGER,"
            + FLAGS_COLUMN + " INTEGER,"
            + "PRIMARY KEY (" + WORDLISTID_COLUMN + "," + VERSION_COLUMN + "));";
    private static final String METADATA_CREATE_CLIENT_TABLE =
            "CREATE TABLE IF NOT EXISTS " + CLIENT_TABLE_NAME + " ("
            + CLIENT_CLIENT_ID_COLUMN + " TEXT, "
            + CLIENT_METADATA_URI_COLUMN + " TEXT, "
            + CLIENT_METADATA_ADDITIONAL_ID_COLUMN + " TEXT, "
            + CLIENT_LAST_UPDATE_DATE_COLUMN + " INTEGER NOT NULL DEFAULT 0, "
            + CLIENT_PENDINGID_COLUMN + " INTEGER, "
            + FLAGS_COLUMN + " INTEGER, "
            + "PRIMARY KEY (" + CLIENT_CLIENT_ID_COLUMN + "));";

    // List of all metadata table columns.
    static final String[] METADATA_TABLE_COLUMNS = { PENDINGID_COLUMN, TYPE_COLUMN,
            STATUS_COLUMN, WORDLISTID_COLUMN, LOCALE_COLUMN, DESCRIPTION_COLUMN,
            LOCAL_FILENAME_COLUMN, REMOTE_FILENAME_COLUMN, DATE_COLUMN, CHECKSUM_COLUMN,
            FILESIZE_COLUMN, VERSION_COLUMN, FORMATVERSION_COLUMN, FLAGS_COLUMN };
    // List of all client table columns.
    static final String[] CLIENT_TABLE_COLUMNS = { CLIENT_CLIENT_ID_COLUMN,
            CLIENT_METADATA_URI_COLUMN, CLIENT_PENDINGID_COLUMN, FLAGS_COLUMN };
    // List of public columns returned to clients. Everything that is not in this list is
    // private and implementation-dependent.
    static final String[] DICTIONARIES_LIST_PUBLIC_COLUMNS = { STATUS_COLUMN, WORDLISTID_COLUMN,
            LOCALE_COLUMN, DESCRIPTION_COLUMN, DATE_COLUMN, FILESIZE_COLUMN, VERSION_COLUMN };

    // This class exhibits a singleton-like behavior by client ID, so it is getInstance'd
    // and has a private c'tor.
    private static TreeMap<String, MetadataDbHelper> sInstanceMap = null;
    public static synchronized MetadataDbHelper getInstance(final Context context,
            final String clientIdOrNull) {
        // As a backward compatibility feature, null can be passed here to retrieve the "default"
        // database. Before multi-client support, the dictionary packed used only one database
        // and would not be able to handle several dictionary sets. Passing null here retrieves
        // this legacy database. New clients should make sure to always pass a client ID so as
        // to avoid conflicts.
        final String clientId = null != clientIdOrNull ? clientIdOrNull : "";
        if (null == sInstanceMap) sInstanceMap = new TreeMap<String, MetadataDbHelper>();
        MetadataDbHelper helper = sInstanceMap.get(clientId);
        if (null == helper) {
            helper = new MetadataDbHelper(context, clientId);
            sInstanceMap.put(clientId, helper);
        }
        return helper;
    }
    private MetadataDbHelper(final Context context, final String clientId) {
        super(context,
                METADATA_DATABASE_NAME_STEM + (TextUtils.isEmpty(clientId) ? "" : "." + clientId),
                null, METADATA_DATABASE_VERSION);
        mContext = context;
        mClientId = clientId;
    }

    private final Context mContext;
    private final String mClientId;

    /**
     * Get the database itself. This always returns the same object for any client ID. If the
     * client ID is null, a default database is returned for backward compatibility. Don't
     * pass null for new calls.
     *
     * @param context the context to create the database from. This is ignored after the first call.
     * @param clientId the client id to retrieve the database of. null for default (deprecated)
     * @return the database.
     */
    public static SQLiteDatabase getDb(final Context context, final String clientId) {
        return getInstance(context, clientId).getWritableDatabase();
    }

    private void createClientTable(final SQLiteDatabase db) {
        // The clients table only exists in the primary db, the one that has an empty client id
        if (!TextUtils.isEmpty(mClientId)) return;
        db.execSQL(METADATA_CREATE_CLIENT_TABLE);
        final String defaultMetadataUri = mContext.getString(R.string.default_metadata_uri);
        if (!TextUtils.isEmpty(defaultMetadataUri)) {
            final ContentValues defaultMetadataValues = new ContentValues();
            defaultMetadataValues.put(CLIENT_CLIENT_ID_COLUMN, "");
            defaultMetadataValues.put(CLIENT_METADATA_URI_COLUMN, defaultMetadataUri);
            db.insert(CLIENT_TABLE_NAME, null, defaultMetadataValues);
        }
    }

    /**
     * Create the table and populate it with the resources found inside the apk.
     *
     * @see SQLiteOpenHelper#onCreate(SQLiteDatabase)
     *
     * @param db the database to create and populate.
     */
    @Override
    public void onCreate(final SQLiteDatabase db) {
        db.execSQL(METADATA_TABLE_CREATE);
        createClientTable(db);
    }

    /**
     * Upgrade the database. Upgrade from version 3 is supported.
     */
    @Override
    public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
        if (METADATA_DATABASE_INITIAL_VERSION == oldVersion
                && METADATA_DATABASE_VERSION_WITH_CLIENTID == newVersion) {
            // Upgrade from version METADATA_DATABASE_INITIAL_VERSION to version
            // METADATA_DATABASE_VERSION_WITH_CLIENT_ID
            if (TextUtils.isEmpty(mClientId)) {
                // Only the default database should contain the client table.
                // Anyway in version 3 only the default table existed so the emptyness
                // test should always be true, but better check to be sure.
                createClientTable(db);
            }
        } else {
            // Version 3 was the earliest version, so we should never come here. If we do, we
            // have no idea what this database is, so we'd better wipe it off.
            db.execSQL("DROP TABLE IF EXISTS " + METADATA_TABLE_NAME);
            db.execSQL("DROP TABLE IF EXISTS " + CLIENT_TABLE_NAME);
            onCreate(db);
        }
    }

    /**
     * Downgrade the database. This drops and recreates the table in all cases.
     */
    @Override
    public void onDowngrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
        // No matter what the numerical values of oldVersion and newVersion are, we know this
        // is a downgrade (newVersion < oldVersion). There is no way to know what the future
        // databases will look like, but we know it's extremely likely that it's okay to just
        // drop the tables and start from scratch. Hence, we ignore the versions and just wipe
        // everything we want to use.
        if (oldVersion <= newVersion) {
            Log.e(TAG, "onDowngrade database but new version is higher? " + oldVersion + " <= "
                    + newVersion);
        }
        db.execSQL("DROP TABLE IF EXISTS " + METADATA_TABLE_NAME);
        db.execSQL("DROP TABLE IF EXISTS " + CLIENT_TABLE_NAME);
        onCreate(db);
    }

    /**
     * Given a client ID, returns whether this client exists.
     *
     * @param context a context to open the database
     * @param clientId the client ID to check
     * @return true if the client is known, false otherwise
     */
    public static boolean isClientKnown(final Context context, final String clientId) {
        // If the client is known, they'll have a non-null metadata URI. An empty string is
        // allowed as a metadata URI, if the client doesn't want any updates to happen.
        return null != getMetadataUriAsString(context, clientId);
    }

    /**
     * Returns the metadata URI as a string.
     *
     * If the client is not known, this will return null. If it is known, it will return
     * the URI as a string. Note that the empty string is a valid value.
     *
     * @param context a context instance to open the database on
     * @param clientId the ID of the client we want the metadata URI of
     * @return the string representation of the URI
     */
    public static String getMetadataUriAsString(final Context context, final String clientId) {
        SQLiteDatabase defaultDb = MetadataDbHelper.getDb(context, null);
        final Cursor cursor = defaultDb.query(MetadataDbHelper.CLIENT_TABLE_NAME,
                new String[] { MetadataDbHelper.CLIENT_METADATA_URI_COLUMN,
                        MetadataDbHelper.CLIENT_METADATA_ADDITIONAL_ID_COLUMN },
                MetadataDbHelper.CLIENT_CLIENT_ID_COLUMN + " = ?", new String[] { clientId },
                null, null, null, null);
        try {
            if (!cursor.moveToFirst()) return null;
            return MetadataUriGetter.getUri(context, cursor.getString(0), cursor.getString(1));
        } finally {
            cursor.close();
        }
    }

    /**
     * Update the last metadata update time for all clients using a particular URI.
     *
     * This method searches for all clients using a particular URI and updates the last
     * update time for this client.
     * The current time is used as the latest update time. This saved date will be what
     * is returned henceforth by {@link #getLastUpdateDateForClient(Context, String)},
     * until this method is called again.
     *
     * @param context a context instance to open the database on
     * @param uri the metadata URI we just downloaded
     */
    public static void saveLastUpdateTimeOfUri(final Context context, final String uri) {
        PrivateLog.log("Save last update time of URI : " + uri + " " + System.currentTimeMillis());
        final ContentValues values = new ContentValues();
        values.put(CLIENT_LAST_UPDATE_DATE_COLUMN, System.currentTimeMillis());
        final SQLiteDatabase defaultDb = getDb(context, null);
        final Cursor cursor = MetadataDbHelper.queryClientIds(context);
        if (null == cursor) return;
        try {
            if (!cursor.moveToFirst()) return;
            do {
                final String clientId = cursor.getString(0);
                final String metadataUri =
                        MetadataDbHelper.getMetadataUriAsString(context, clientId);
                if (metadataUri.equals(uri)) {
                    defaultDb.update(CLIENT_TABLE_NAME, values,
                            CLIENT_CLIENT_ID_COLUMN + " = ?", new String[] { clientId });
                }
            } while (cursor.moveToNext());
        } finally {
            cursor.close();
        }
    }

    /**
     * Retrieves the last date at which we updated the metadata for this client.
     *
     * The returned date is in milliseconds from the EPOCH; this is the same unit as
     * returned by {@link System#currentTimeMillis()}.
     *
     * @param context a context instance to open the database on
     * @param clientId the client ID to get the latest update date of
     * @return the last date at which this client was updated, as a long.
     */
    public static long getLastUpdateDateForClient(final Context context, final String clientId) {
        SQLiteDatabase defaultDb = getDb(context, null);
        final Cursor cursor = defaultDb.query(CLIENT_TABLE_NAME,
                new String[] { CLIENT_LAST_UPDATE_DATE_COLUMN },
                CLIENT_CLIENT_ID_COLUMN + " = ?",
                new String[] { null == clientId ? "" : clientId },
                null, null, null, null);
        try {
            if (!cursor.moveToFirst()) return 0;
            return cursor.getLong(0); // Only one column, return it
        } finally {
            cursor.close();
        }
    }

    /**
     * Get the metadata download ID for a client ID.
     *
     * This will retrieve the download ID for the metadata file associated with a client ID.
     * If there is no metadata download in progress for this client, it will return NOT_AN_ID.
     *
     * @param context a context instance to open the database on
     * @param clientId the client ID to retrieve the metadata download ID of
     * @return the metadata download ID, or NOT_AN_ID if no download is in progress
     */
    public static long getMetadataDownloadIdForClient(final Context context,
            final String clientId) {
        SQLiteDatabase defaultDb = getDb(context, null);
        final Cursor cursor = defaultDb.query(CLIENT_TABLE_NAME,
                new String[] { CLIENT_PENDINGID_COLUMN },
                CLIENT_CLIENT_ID_COLUMN + " = ?", new String[] { clientId },
                null, null, null, null);
        try {
            if (!cursor.moveToFirst()) return UpdateHandler.NOT_AN_ID;
            return cursor.getInt(0); // Only one column, return it
        } finally {
            cursor.close();
        }
    }

    public static long getOldestUpdateTime(final Context context) {
        SQLiteDatabase defaultDb = getDb(context, null);
        final Cursor cursor = defaultDb.query(CLIENT_TABLE_NAME,
                new String[] { CLIENT_LAST_UPDATE_DATE_COLUMN },
                null, null, null, null, null);
        try {
            if (!cursor.moveToFirst()) return 0;
            final int columnIndex = 0; // Only one column queried
            // Initialize the earliestTime to the largest possible value.
            long earliestTime = Long.MAX_VALUE; // Almost 300 million years in the future
            do {
                final long thisTime = cursor.getLong(columnIndex);
                earliestTime = Math.min(thisTime, earliestTime);
            } while (cursor.moveToNext());
            return earliestTime;
        } finally {
            cursor.close();
        }
    }

    /**
     * Helper method to make content values to write into the database.
     * @return content values with all the arguments put with the right column names.
     */
    public static ContentValues makeContentValues(final int pendingId, final int type,
            final int status, final String wordlistId, final String locale,
            final String description, final String filename, final String url, final long date,
            final String checksum, final long filesize, final int version,
            final int formatVersion) {
        final ContentValues result = new ContentValues(COLUMN_COUNT);
        result.put(PENDINGID_COLUMN, pendingId);
        result.put(TYPE_COLUMN, type);
        result.put(WORDLISTID_COLUMN, wordlistId);
        result.put(STATUS_COLUMN, status);
        result.put(LOCALE_COLUMN, locale);
        result.put(DESCRIPTION_COLUMN, description);
        result.put(LOCAL_FILENAME_COLUMN, filename);
        result.put(REMOTE_FILENAME_COLUMN, url);
        result.put(DATE_COLUMN, date);
        result.put(CHECKSUM_COLUMN, checksum);
        result.put(FILESIZE_COLUMN, filesize);
        result.put(VERSION_COLUMN, version);
        result.put(FORMATVERSION_COLUMN, formatVersion);
        result.put(FLAGS_COLUMN, 0);
        return result;
    }

    /**
     * Helper method to fill in an incomplete ContentValues with default values.
     * A wordlist ID and a locale are required, otherwise BadFormatException is thrown.
     * @return the same object that was passed in, completed with default values.
     */
    public static ContentValues completeWithDefaultValues(final ContentValues result)
            throws BadFormatException {
        if (!result.containsKey(WORDLISTID_COLUMN) || !result.containsKey(LOCALE_COLUMN)) {
            throw new BadFormatException();
        }
        // 0 for the pending id, because there is none
        if (!result.containsKey(PENDINGID_COLUMN)) result.put(PENDINGID_COLUMN, 0);
        // This is a binary blob of a dictionary
        if (!result.containsKey(TYPE_COLUMN)) result.put(TYPE_COLUMN, TYPE_BULK);
        // This word list is unknown, but it's present, else we wouldn't be here, so INSTALLED
        if (!result.containsKey(STATUS_COLUMN)) result.put(STATUS_COLUMN, STATUS_INSTALLED);
        // No description unless specified, because we can't guess it
        if (!result.containsKey(DESCRIPTION_COLUMN)) result.put(DESCRIPTION_COLUMN, "");
        // File name - this is an asset, so it works as an already deleted file.
        //     hence, we need to supply a non-existent file name. Anything will
        //     do as long as it returns false when tested with File#exist(), and
        //     the empty string does not, so it's set to "_".
        if (!result.containsKey(LOCAL_FILENAME_COLUMN)) result.put(LOCAL_FILENAME_COLUMN, "_");
        // No remote file name : this can't be downloaded. Unless specified.
        if (!result.containsKey(REMOTE_FILENAME_COLUMN)) result.put(REMOTE_FILENAME_COLUMN, "");
        // 0 for the update date : 1970/1/1. Unless specified.
        if (!result.containsKey(DATE_COLUMN)) result.put(DATE_COLUMN, 0);
        // Checksum unknown unless specified
        if (!result.containsKey(CHECKSUM_COLUMN)) result.put(CHECKSUM_COLUMN, "");
        // No filesize unless specified
        if (!result.containsKey(FILESIZE_COLUMN)) result.put(FILESIZE_COLUMN, 0);
        // Smallest possible version unless specified
        if (!result.containsKey(VERSION_COLUMN)) result.put(VERSION_COLUMN, 1);
        // Assume current format unless specified
        if (!result.containsKey(FORMATVERSION_COLUMN))
            result.put(FORMATVERSION_COLUMN, UpdateHandler.MAXIMUM_SUPPORTED_FORMAT_VERSION);
        // No flags unless specified
        if (!result.containsKey(FLAGS_COLUMN)) result.put(FLAGS_COLUMN, 0);
        return result;
    }

    /**
     * Reads a column in a Cursor as a String and stores it in a ContentValues object.
     * @param result the ContentValues object to store the result in.
     * @param cursor the Cursor to read the column from.
     * @param columnId the column ID to read.
     */
    private static void putStringResult(ContentValues result, Cursor cursor, String columnId) {
        result.put(columnId, cursor.getString(cursor.getColumnIndex(columnId)));
    }

    /**
     * Reads a column in a Cursor as an int and stores it in a ContentValues object.
     * @param result the ContentValues object to store the result in.
     * @param cursor the Cursor to read the column from.
     * @param columnId the column ID to read.
     */
    private static void putIntResult(ContentValues result, Cursor cursor, String columnId) {
        result.put(columnId, cursor.getInt(cursor.getColumnIndex(columnId)));
    }

    private static ContentValues getFirstLineAsContentValues(final Cursor cursor) {
        final ContentValues result;
        if (cursor.moveToFirst()) {
            result = new ContentValues(COLUMN_COUNT);
            putIntResult(result, cursor, PENDINGID_COLUMN);
            putIntResult(result, cursor, TYPE_COLUMN);
            putIntResult(result, cursor, STATUS_COLUMN);
            putStringResult(result, cursor, WORDLISTID_COLUMN);
            putStringResult(result, cursor, LOCALE_COLUMN);
            putStringResult(result, cursor, DESCRIPTION_COLUMN);
            putStringResult(result, cursor, LOCAL_FILENAME_COLUMN);
            putStringResult(result, cursor, REMOTE_FILENAME_COLUMN);
            putIntResult(result, cursor, DATE_COLUMN);
            putStringResult(result, cursor, CHECKSUM_COLUMN);
            putIntResult(result, cursor, FILESIZE_COLUMN);
            putIntResult(result, cursor, VERSION_COLUMN);
            putIntResult(result, cursor, FORMATVERSION_COLUMN);
            putIntResult(result, cursor, FLAGS_COLUMN);
            if (cursor.moveToNext()) {
                // TODO: print the second level of the stack to the log so that we know
                // in which code path the error happened
                Log.e(TAG, "Several SQL results when we expected only one!");
            }
        } else {
            result = null;
        }
        return result;
    }

    /**
     * Gets the info about as specific download, indexed by its DownloadManager ID.
     * @param db the database to get the information from.
     * @param id the DownloadManager id.
     * @return metadata about this download. This returns all columns in the database.
     */
    public static ContentValues getContentValuesByPendingId(final SQLiteDatabase db,
            final long id) {
        final Cursor cursor = db.query(METADATA_TABLE_NAME,
                METADATA_TABLE_COLUMNS,
                PENDINGID_COLUMN + "= ?",
                new String[] { Long.toString(id) },
                null, null, null);
        // There should never be more than one result. If because of some bug there are, returning
        // only one result is the right thing to do, because we couldn't handle several anyway
        // and we should still handle one.
        final ContentValues result = getFirstLineAsContentValues(cursor);
        cursor.close();
        return result;
    }

    /**
     * Gets the info about an installed OR deleting word list with a specified id.
     *
     * Basically, this is the word list that we want to return to Android Keyboard when
     * it asks for a specific id.
     *
     * @param db the database to get the information from.
     * @param id the word list ID.
     * @return the metadata about this word list.
     */
    public static ContentValues getInstalledOrDeletingWordListContentValuesByWordListId(
            final SQLiteDatabase db, final String id) {
        final Cursor cursor = db.query(METADATA_TABLE_NAME,
                METADATA_TABLE_COLUMNS,
                WORDLISTID_COLUMN + "=? AND (" + STATUS_COLUMN + "=? OR " + STATUS_COLUMN + "=?)",
                new String[] { id, Integer.toString(STATUS_INSTALLED),
                        Integer.toString(STATUS_DELETING) },
                null, null, null);
        // There should only be one result, but if there are several, we can't tell which
        // is the best, so we just return the first one.
        final ContentValues result = getFirstLineAsContentValues(cursor);
        cursor.close();
        return result;
    }

    /**
     * Given a specific download ID, return records for all pending downloads across all clients.
     *
     * If several clients use the same metadata URL, we know to only download it once, and
     * dispatch the update process across all relevant clients when the download ends. This means
     * several clients may share a single download ID if they share a metadata URI.
     * The dispatching is done in {@link UpdateHandler#downloadFinished(Context, Intent)}, which
     * finds out about the list of relevant clients by calling this method.
     *
     * @param context a context instance to open the databases
     * @param downloadId the download ID to query about
     * @return the list of records. Never null, but may be empty.
     */
    public static ArrayList<DownloadRecord> getDownloadRecordsForDownloadId(final Context context,
            final long downloadId) {
        final SQLiteDatabase defaultDb = getDb(context, "");
        final ArrayList<DownloadRecord> results = new ArrayList<DownloadRecord>();
        final Cursor cursor = defaultDb.query(CLIENT_TABLE_NAME, CLIENT_TABLE_COLUMNS,
                null, null, null, null, null);
        try {
            if (!cursor.moveToFirst()) return results;
            final int clientIdIndex = cursor.getColumnIndex(CLIENT_CLIENT_ID_COLUMN);
            final int pendingIdColumn = cursor.getColumnIndex(CLIENT_PENDINGID_COLUMN);
            do {
                final long pendingId = cursor.getInt(pendingIdColumn);
                final String clientId = cursor.getString(clientIdIndex);
                if (pendingId == downloadId) {
                    results.add(new DownloadRecord(clientId, null));
                }
                final ContentValues valuesForThisClient =
                        getContentValuesByPendingId(getDb(context, clientId), downloadId);
                if (null != valuesForThisClient) {
                    results.add(new DownloadRecord(clientId, valuesForThisClient));
                }
            } while (cursor.moveToNext());
        } finally {
            cursor.close();
        }
        return results;
    }

    /**
     * Gets the info about a specific word list.
     *
     * @param db the database to get the information from.
     * @param id the word list ID.
     * @param version the word list version.
     * @return the metadata about this word list.
     */
    public static ContentValues getContentValuesByWordListId(final SQLiteDatabase db,
            final String id, final int version) {
        final Cursor cursor = db.query(METADATA_TABLE_NAME,
                METADATA_TABLE_COLUMNS,
                WORDLISTID_COLUMN + "= ? AND " + VERSION_COLUMN + "= ?",
                new String[] { id, Integer.toString(version) }, null, null, null);
        // This is a lookup by primary key, so there can't be more than one result.
        final ContentValues result = getFirstLineAsContentValues(cursor);
        cursor.close();
        return result;
    }

    /**
     * Gets the info about the latest word list with an id.
     *
     * @param db the database to get the information from.
     * @param id the word list ID.
     * @return the metadata about the word list with this id and the latest version number.
     */
    public static ContentValues getContentValuesOfLatestAvailableWordlistById(
            final SQLiteDatabase db, final String id) {
        final Cursor cursor = db.query(METADATA_TABLE_NAME,
                METADATA_TABLE_COLUMNS,
                WORDLISTID_COLUMN + "= ?",
                new String[] { id }, null, null, VERSION_COLUMN + " DESC", "1");
        // This is a lookup by primary key, so there can't be more than one result.
        final ContentValues result = getFirstLineAsContentValues(cursor);
        cursor.close();
        return result;
    }

    /**
     * Gets the current metadata about INSTALLED, AVAILABLE or DELETING dictionaries.
     *
     * This odd method is tailored to the needs of
     * DictionaryProvider#getDictionaryWordListsForContentUri, which needs the word list if
     * it is:
     * - INSTALLED: this should be returned to LatinIME if the file is still inside the dictionary
     * pack, so that it can be copied. If the file is not there, it's been copied already and should
     * not be returned, so getDictionaryWordListsForContentUri takes care of this.
     * - DELETING: this should be returned to LatinIME so that it can actually delete the file.
     * - AVAILABLE: this should not be returned, but should be checked for auto-installation.
     *
     * @param context the context for getting the database.
     * @param clientId the client id for retrieving the database. null for default (deprecated)
     * @return a cursor with metadata about usable dictionaries.
     */
    public static Cursor queryInstalledOrDeletingOrAvailableDictionaryMetadata(
            final Context context, final String clientId) {
        // If clientId is null, we get the defaut DB (see #getInstance() for more about this)
        final Cursor results = getDb(context, clientId).query(METADATA_TABLE_NAME,
                METADATA_TABLE_COLUMNS,
                STATUS_COLUMN + " = ? OR " + STATUS_COLUMN + " = ? OR " + STATUS_COLUMN + " = ?",
                new String[] { Integer.toString(STATUS_INSTALLED),
                        Integer.toString(STATUS_DELETING),
                        Integer.toString(STATUS_AVAILABLE) },
                null, null, LOCALE_COLUMN);
        return results;
    }

    /**
     * Gets the current metadata about all dictionaries.
     *
     * This will retrieve the metadata about all dictionaries, including
     * older files, or files not yet downloaded.
     *
     * @param context the context for getting the database.
     * @param clientId the client id for retrieving the database. null for default (deprecated)
     * @return a cursor with metadata about usable dictionaries.
     */
    public static Cursor queryCurrentMetadata(final Context context, final String clientId) {
        // If clientId is null, we get the defaut DB (see #getInstance() for more about this)
        final Cursor results = getDb(context, clientId).query(METADATA_TABLE_NAME,
                METADATA_TABLE_COLUMNS, null, null, null, null, LOCALE_COLUMN);
        return results;
    }

    /**
     * Gets the list of all dictionaries known to the dictionary provider, with only public columns.
     *
     * This will retrieve information about all known dictionaries, and their status. As such,
     * it will also return information about dictionaries on the server that have not been
     * downloaded yet, but may be requested.
     * This only returns public columns. It does not populate internal columns in the returned
     * cursor.
     * The value returned by this method is intended to be good to be returned directly for a
     * request of the list of dictionaries by a client.
     *
     * @param context the context to read the database from.
     * @param clientId the client id for retrieving the database. null for default (deprecated)
     * @return a cursor that lists all available dictionaries and their metadata.
     */
    public static Cursor queryDictionaries(final Context context, final String clientId) {
        // If clientId is null, we get the defaut DB (see #getInstance() for more about this)
        final Cursor results = getDb(context, clientId).query(METADATA_TABLE_NAME,
                DICTIONARIES_LIST_PUBLIC_COLUMNS,
                // Filter out empty locales so as not to return auxiliary data, like a
                // data line for downloading metadata:
                MetadataDbHelper.LOCALE_COLUMN + " != ?", new String[] {""},
                // TODO: Reinstate the following code for bulk, then implement partial updates
                /*                MetadataDbHelper.TYPE_COLUMN + " = ?",
                new String[] { Integer.toString(MetadataDbHelper.TYPE_BULK) }, */
                null, null, LOCALE_COLUMN);
        return results;
    }

    /**
     * Deletes all data associated with a client.
     *
     * @param context the context for opening the database
     * @param clientId the ID of the client to delete.
     * @return true if the client was successfully deleted, false otherwise.
     */
    public static boolean deleteClient(final Context context, final String clientId) {
        // Remove all metadata associated with this client
        final SQLiteDatabase db = getDb(context, clientId);
        db.execSQL("DROP TABLE IF EXISTS " + METADATA_TABLE_NAME);
        db.execSQL(METADATA_TABLE_CREATE);
        // Remove this client's entry in the clients table
        final SQLiteDatabase defaultDb = getDb(context, "");
        if (0 == defaultDb.delete(CLIENT_TABLE_NAME,
                CLIENT_CLIENT_ID_COLUMN + " = ?", new String[] { clientId })) {
            return false;
        }
        return true;
    }

    /**
     * Updates information relative to a specific client.
     *
     * Updatable information includes the metadata URI and the additional ID column. It may be
     * expanded in the future.
     * The passed values must include a client ID in the key CLIENT_CLIENT_ID_COLUMN, and it must
     * be equal to the string passed as an argument for clientId. It may not be empty.
     * The passed values must also include a non-null metadata URI in the
     * CLIENT_METADATA_URI_COLUMN column, as well as a non-null additional ID in the
     * CLIENT_METADATA_ADDITIONAL_ID_COLUMN. Both these strings may be empty.
     * If any of the above is not complied with, this function returns without updating data.
     *
     * @param context the context, to open the database
     * @param clientId the ID of the client to update
     * @param values the values to update. Must conform to the protocol (see above)
     */
    public static void updateClientInfo(final Context context, final String clientId,
            final ContentValues values) {
        // Sanity check the content values
        final String valuesClientId = values.getAsString(CLIENT_CLIENT_ID_COLUMN);
        final String valuesMetadataUri = values.getAsString(CLIENT_METADATA_URI_COLUMN);
        final String valuesMetadataAdditionalId =
                values.getAsString(CLIENT_METADATA_ADDITIONAL_ID_COLUMN);
        // Empty string is a valid client ID, but external apps may not configure it, so disallow
        // both null and empty string.
        // Empty string is a valid metadata URI if the client does not want updates, so allow
        // empty string but disallow null.
        // Empty string is a valid additional ID so allow empty string but disallow null.
        if (TextUtils.isEmpty(valuesClientId) || null == valuesMetadataUri
                || null == valuesMetadataAdditionalId) {
            // We need all these columns to be filled in
            Utils.l("Missing parameter for updateClientInfo");
            return;
        }
        if (!clientId.equals(valuesClientId)) {
            // Mismatch! The client violates the protocol.
            Utils.l("Received an updateClientInfo request for ", clientId, " but the values "
                    + "contain a different ID : ", valuesClientId);
            return;
        }
        final SQLiteDatabase defaultDb = getDb(context, "");
        if (-1 == defaultDb.insert(CLIENT_TABLE_NAME, null, values)) {
            defaultDb.update(CLIENT_TABLE_NAME, values,
                    CLIENT_CLIENT_ID_COLUMN + " = ?", new String[] { clientId });
        }
    }

    /**
     * Retrieves the list of existing client IDs.
     * @param context the context to open the database
     * @return a cursor containing only one column, and one client ID per line.
     */
    public static Cursor queryClientIds(final Context context) {
        return getDb(context, null).query(CLIENT_TABLE_NAME,
                new String[] { CLIENT_CLIENT_ID_COLUMN }, null, null, null, null, null);
    }

    /**
     * Register a download ID for a specific metadata URI.
     *
     * This method should be called when a download for a metadata URI is starting. It will
     * search for all clients using this metadata URI and will register for each of them
     * the download ID into the database for later retrieval by
     * {@link #getDownloadRecordsForDownloadId(Context, long)}.
     *
     * @param context a context for opening databases
     * @param uri the metadata URI
     * @param downloadId the download ID
     */
    public static void registerMetadataDownloadId(final Context context, final String uri,
            final long downloadId) {
        final ContentValues values = new ContentValues();
        values.put(CLIENT_PENDINGID_COLUMN, downloadId);
        final SQLiteDatabase defaultDb = getDb(context, "");
        final Cursor cursor = MetadataDbHelper.queryClientIds(context);
        if (null == cursor) return;
        try {
            if (!cursor.moveToFirst()) return;
            do {
                final String clientId = cursor.getString(0);
                final String metadataUri =
                        MetadataDbHelper.getMetadataUriAsString(context, clientId);
                if (metadataUri.equals(uri)) {
                    defaultDb.update(CLIENT_TABLE_NAME, values,
                            CLIENT_CLIENT_ID_COLUMN + " = ?", new String[] { clientId });
                }
            } while (cursor.moveToNext());
        } finally {
            cursor.close();
        }
    }

    /**
     * Marks a downloading entry as having successfully downloaded and being installed.
     *
     * The metadata database contains information about ongoing processes, typically ongoing
     * downloads. This marks such an entry as having finished and having installed successfully,
     * so it becomes INSTALLED.
     *
     * @param db the metadata database.
     * @param r content values about the entry to mark as processed.
     */
    public static void markEntryAsFinishedDownloadingAndInstalled(final SQLiteDatabase db,
            final ContentValues r) {
        switch (r.getAsInteger(TYPE_COLUMN)) {
            case TYPE_BULK:
                Utils.l("Ended processing a wordlist");
                // Updating a bulk word list is a three-step operation:
                // - Add the new entry to the table
                // - Remove the old entry from the table
                // - Erase the old file
                // We start by gathering the names of the files we should delete.
                final List<String> filenames = new LinkedList<String>();
                final Cursor c = db.query(METADATA_TABLE_NAME,
                        new String[] { LOCAL_FILENAME_COLUMN },
                        LOCALE_COLUMN + " = ? AND " +
                        WORDLISTID_COLUMN + " = ? AND " + STATUS_COLUMN + " = ?",
                        new String[] { r.getAsString(LOCALE_COLUMN),
                                r.getAsString(WORDLISTID_COLUMN),
                                Integer.toString(STATUS_INSTALLED) },
                        null, null, null);
                if (c.moveToFirst()) {
                    // There should never be more than one file, but if there are, it's a bug
                    // and we should remove them all. I think it might happen if the power of the
                    // phone is suddenly cut during an update.
                    final int filenameIndex = c.getColumnIndex(LOCAL_FILENAME_COLUMN);
                    do {
                        Utils.l("Setting for removal", c.getString(filenameIndex));
                        filenames.add(c.getString(filenameIndex));
                    } while (c.moveToNext());
                }

                r.put(STATUS_COLUMN, STATUS_INSTALLED);
                db.beginTransactionNonExclusive();
                // Delete all old entries. There should never be any stalled entries, but if
                // there are, this deletes them.
                db.delete(METADATA_TABLE_NAME,
                        WORDLISTID_COLUMN + " = ?",
                        new String[] { r.getAsString(WORDLISTID_COLUMN) });
                db.insert(METADATA_TABLE_NAME, null, r);
                db.setTransactionSuccessful();
                db.endTransaction();
                for (String filename : filenames) {
                    try {
                        final File f = new File(filename);
                        f.delete();
                    } catch (SecurityException e) {
                        // No permissions to delete. Um. Can't do anything.
                    } // I don't think anything else can be thrown
                }
                break;
            default:
                // Unknown type: do nothing.
                break;
        }
     }

    /**
     * Removes a downloading entry from the database.
     *
     * This is invoked when a download fails. Either we tried to download, but
     * we received a permanent failure and we should remove it, or we got manually
     * cancelled and we should leave it at that.
     *
     * @param db the metadata database.
     * @param id the DownloadManager id of the file.
     */
    public static void deleteDownloadingEntry(final SQLiteDatabase db, final long id) {
        db.delete(METADATA_TABLE_NAME, PENDINGID_COLUMN + " = ? AND " + STATUS_COLUMN + " = ?",
                new String[] { Long.toString(id), Integer.toString(STATUS_DOWNLOADING) });
    }

    /**
     * Forcefully removes an entry from the database.
     *
     * This is invoked when a file is broken. The file has been downloaded, but Android
     * Keyboard is telling us it could not open it.
     *
     * @param db the metadata database.
     * @param id the id of the word list.
     * @param version the version of the word list.
     */
    public static void deleteEntry(final SQLiteDatabase db, final String id, final int version) {
        db.delete(METADATA_TABLE_NAME, WORDLISTID_COLUMN + " = ? AND " + VERSION_COLUMN + " = ?",
                new String[] { id, Integer.toString(version) });
    }

    /**
     * Internal method that sets the current status of an entry of the database.
     *
     * @param db the metadata database.
     * @param id the id of the word list.
     * @param version the version of the word list.
     * @param status the status to set the word list to.
     * @param downloadId an optional download id to write, or NOT_A_DOWNLOAD_ID
     */
    private static void markEntryAs(final SQLiteDatabase db, final String id,
            final int version, final int status, final long downloadId) {
        final ContentValues values = MetadataDbHelper.getContentValuesByWordListId(db, id, version);
        values.put(STATUS_COLUMN, status);
        if (NOT_A_DOWNLOAD_ID != downloadId) {
            values.put(MetadataDbHelper.PENDINGID_COLUMN, downloadId);
        }
        db.update(METADATA_TABLE_NAME, values,
                WORDLISTID_COLUMN + " = ? AND " + VERSION_COLUMN + " = ?",
                new String[] { id, Integer.toString(version) });
    }

    /**
     * Writes the status column for the wordlist with this id as enabled. Typically this
     * means the word list is currently disabled and we want to set its status to INSTALLED.
     *
     * @param db the metadata database.
     * @param id the id of the word list.
     * @param version the version of the word list.
     */
    public static void markEntryAsEnabled(final SQLiteDatabase db, final String id,
            final int version) {
        markEntryAs(db, id, version, STATUS_INSTALLED, NOT_A_DOWNLOAD_ID);
    }

    /**
     * Writes the status column for the wordlist with this id as disabled. Typically this
     * means the word list is currently installed and we want to set its status to DISABLED.
     *
     * @param db the metadata database.
     * @param id the id of the word list.
     * @param version the version of the word list.
     */
    public static void markEntryAsDisabled(final SQLiteDatabase db, final String id,
            final int version) {
        markEntryAs(db, id, version, STATUS_DISABLED, NOT_A_DOWNLOAD_ID);
    }

    /**
     * Writes the status column for the wordlist with this id as available. This happens for
     * example when a word list has been deleted but can be downloaded again.
     *
     * @param db the metadata database.
     * @param id the id of the word list.
     * @param version the version of the word list.
     */
    public static void markEntryAsAvailable(final SQLiteDatabase db, final String id,
            final int version) {
        markEntryAs(db, id, version, STATUS_AVAILABLE, NOT_A_DOWNLOAD_ID);
    }

    /**
     * Writes the designated word list as downloadable, alongside with its download id.
     *
     * @param db the metadata database.
     * @param id the id of the word list.
     * @param version the version of the word list.
     * @param downloadId the download id.
     */
    public static void markEntryAsDownloading(final SQLiteDatabase db, final String id,
            final int version, final long downloadId) {
        markEntryAs(db, id, version, STATUS_DOWNLOADING, downloadId);
    }

    /**
     * Writes the designated word list as deleting.
     *
     * @param db the metadata database.
     * @param id the id of the word list.
     * @param version the version of the word list.
     */
    public static void markEntryAsDeleting(final SQLiteDatabase db, final String id,
            final int version) {
        markEntryAs(db, id, version, STATUS_DELETING, NOT_A_DOWNLOAD_ID);
    }
}
