/*
 * 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.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.provider.Settings;
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 = 5;
    // 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 = 5;

    private final static long NOT_A_DOWNLOAD_ID = -1;

    public static final String METADATA_TABLE_NAME = "pendingUpdates";
    private 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_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_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 = getDb(context, null);
        final Cursor cursor = defaultDb.query(CLIENT_TABLE_NAME,
                new String[] { CLIENT_METADATA_URI_COLUMN },
                CLIENT_CLIENT_ID_COLUMN + " = ?", new String[] { clientId },
                null, null, null, null);
        try {
            if (!cursor.moveToFirst()) return null;
            return cursor.getString(0); // Only one column, return it
        } finally {
            cursor.close();
        }
    }

    /**
     * Update the last metadata update time for all clients using a particular URI.
     *
     * All clients using this metadata URI will be indicated as having been updated now.
     * 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(),
                context);
        final ContentValues values = new ContentValues();
        values.put(CLIENT_LAST_UPDATE_DATE_COLUMN, System.currentTimeMillis());
        final SQLiteDatabase defaultDb = getDb(context, null);
        defaultDb.update(CLIENT_TABLE_NAME, values,
                CLIENT_METADATA_URI_COLUMN + " = ?", new String[] { uri });
    }

    /**
     * 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 only the metadata URI, but 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.
     * The passed values must also include a non-empty metadata URI in the
     * CLIENT_METADATA_URI_COLUMN column.
     * 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);
        // Empty string is a valid client ID, but external apps may not configure it.
        // Empty string is a valid metadata URI if the client does not want updates.
        if (TextUtils.isEmpty(valuesClientId) || null == valuesMetadataUri) {
            // We need both 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
     * register the download ID for all clients using this metadata URI 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, "");
        defaultDb.update(CLIENT_TABLE_NAME, values,
                CLIENT_METADATA_URI_COLUMN + " = ?", new String[] { uri });
    }

    /**
     * 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);
    }
}
