/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.android.inputmethod.dictionarypack;

import android.app.DownloadManager;
import android.app.DownloadManager.Query;
import android.app.DownloadManager.Request;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.ConnectivityManager;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.text.TextUtils;
import android.util.Log;

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

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import java.util.TreeSet;

/**
 * Handler for the update process.
 *
 * This class is in charge of coordinating the update process for the various dictionaries
 * stored in the dictionary pack.
 */
public final class UpdateHandler {
    static final String TAG = "DictionaryProvider:" + UpdateHandler.class.getSimpleName();
    private static final boolean DEBUG = DictionaryProvider.DEBUG;

    // Used to prevent trying to read the id of the downloaded file before it is written
    static final Object sSharedIdProtector = new Object();

    // Value used to mean this is not a real DownloadManager downloaded file id
    // DownloadManager uses as an ID numbers returned out of an AUTOINCREMENT column
    // in SQLite, so it should never return anything < 0.
    public static final int NOT_AN_ID = -1;
    public static final int MAXIMUM_SUPPORTED_FORMAT_VERSION = 2;

    // Arbitrary. Probably good if it's a power of 2, and a couple thousand bytes long.
    private static final int FILE_COPY_BUFFER_SIZE = 8192;

    // Table fixed values for metadata / downloads
    final static String METADATA_NAME = "metadata";
    final static int METADATA_TYPE = 0;
    final static int WORDLIST_TYPE = 1;

    // Suffix for generated dictionary files
    private static final String DICT_FILE_SUFFIX = ".dict";
    // Name of the category for the main dictionary
    public static final String MAIN_DICTIONARY_CATEGORY = "main";

    // The id for the "dictionary available" notification.
    static final int DICT_AVAILABLE_NOTIFICATION_ID = 1;

    /**
     * An interface for UIs or services that want to know when something happened.
     *
     * This is chiefly used by the dictionary manager UI.
     */
    public interface UpdateEventListener {
        public void downloadedMetadata(boolean succeeded);
        public void wordListDownloadFinished(String wordListId, boolean succeeded);
        public void updateCycleCompleted();
    }

    /**
     * The list of currently registered listeners.
     */
    private static List<UpdateEventListener> sUpdateEventListeners
            = Collections.synchronizedList(new LinkedList<UpdateEventListener>());

    /**
     * Register a new listener to be notified of updates.
     *
     * Don't forget to call unregisterUpdateEventListener when done with it, or
     * it will leak the register.
     */
    public static void registerUpdateEventListener(final UpdateEventListener listener) {
        sUpdateEventListeners.add(listener);
    }

    /**
     * Unregister a previously registered listener.
     */
    public static void unregisterUpdateEventListener(final UpdateEventListener listener) {
        sUpdateEventListeners.remove(listener);
    }

    private static final String DOWNLOAD_OVER_METERED_SETTING_PREFS_KEY = "downloadOverMetered";

    /**
     * Write the DownloadManager ID of the currently downloading metadata to permanent storage.
     *
     * @param context to open shared prefs
     * @param uri the uri of the metadata
     * @param downloadId the id returned by DownloadManager
     */
    private static void writeMetadataDownloadId(final Context context, final String uri,
            final long downloadId) {
        MetadataDbHelper.registerMetadataDownloadId(context, uri, downloadId);
    }

    public static final int DOWNLOAD_OVER_METERED_SETTING_UNKNOWN = 0;
    public static final int DOWNLOAD_OVER_METERED_ALLOWED = 1;
    public static final int DOWNLOAD_OVER_METERED_DISALLOWED = 2;

    /**
     * Sets the setting that tells us whether we may download over a metered connection.
     */
    public static void setDownloadOverMeteredSetting(final Context context,
            final boolean shouldDownloadOverMetered) {
        final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context);
        final SharedPreferences.Editor editor = prefs.edit();
        editor.putInt(DOWNLOAD_OVER_METERED_SETTING_PREFS_KEY, shouldDownloadOverMetered
                ? DOWNLOAD_OVER_METERED_ALLOWED : DOWNLOAD_OVER_METERED_DISALLOWED);
        editor.apply();
    }

    /**
     * Gets the setting that tells us whether we may download over a metered connection.
     *
     * This returns one of the constants above.
     */
    public static int getDownloadOverMeteredSetting(final Context context) {
        final SharedPreferences prefs = CommonPreferences.getCommonPreferences(context);
        final int setting = prefs.getInt(DOWNLOAD_OVER_METERED_SETTING_PREFS_KEY,
                DOWNLOAD_OVER_METERED_SETTING_UNKNOWN);
        return setting;
    }

    /**
     * Download latest metadata from the server through DownloadManager for all known clients
     * @param context The context for retrieving resources
     * @param updateNow Whether we should update NOW, or respect bandwidth policies
     */
    public static void update(final Context context, final boolean updateNow) {
        // TODO: loop through all clients instead of only doing the default one.
        final TreeSet<String> uris = new TreeSet<String>();
        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);
                PrivateLog.log("Update for clientId " + Utils.s(clientId));
                Utils.l("Update for clientId", clientId, " which uses URI ", metadataUri);
                uris.add(metadataUri);
            } while (cursor.moveToNext());
        } finally {
            cursor.close();
        }
        for (final String metadataUri : uris) {
            if (!TextUtils.isEmpty(metadataUri)) {
                // If the metadata URI is empty, that means we should never update it at all.
                // It should not be possible to come here with a null metadata URI, because
                // it should have been rejected at the time of client registration; if there
                // is a bug and it happens anyway, doing nothing is the right thing to do.
                // For more information, {@see DictionaryProvider#insert(Uri, ContentValues)}.
                updateClientsWithMetadataUri(context, updateNow, metadataUri);
            }
        }
    }

    /**
     * Download latest metadata from the server through DownloadManager for all relevant clients
     *
     * @param context The context for retrieving resources
     * @param updateNow Whether we should update NOW, or respect bandwidth policies
     * @param metadataUri The client to update
     */
    private static void updateClientsWithMetadataUri(final Context context,
            final boolean updateNow, final String metadataUri) {
        PrivateLog.log("Update for metadata URI " + Utils.s(metadataUri));
        // Adding a disambiguator to circumvent a bug in older versions of DownloadManager.
        // DownloadManager also stupidly cuts the extension to replace with its own that it
        // gets from the content-type. We need to circumvent this.
        final String disambiguator = "#" + System.currentTimeMillis()
                + com.android.inputmethod.latin.Utils.getVersionName(context) + ".json";
        final Request metadataRequest = new Request(Uri.parse(metadataUri + disambiguator));
        Utils.l("Request =", metadataRequest);

        final Resources res = context.getResources();
        // By default, download over roaming is allowed and all network types are allowed too.
        if (!updateNow) {
            final boolean allowedOverMetered = res.getBoolean(R.bool.allow_over_metered);
            // If we don't have to update NOW, then only do it over non-metered connections.
            if (DownloadManagerCompatUtils.hasSetAllowedOverMetered()) {
                DownloadManagerCompatUtils.setAllowedOverMetered(metadataRequest,
                        allowedOverMetered);
            } else if (!allowedOverMetered) {
                metadataRequest.setAllowedNetworkTypes(Request.NETWORK_WIFI);
            }
            metadataRequest.setAllowedOverRoaming(res.getBoolean(R.bool.allow_over_roaming));
        }
        final boolean notificationVisible = updateNow
                ? res.getBoolean(R.bool.display_notification_for_user_requested_update)
                : res.getBoolean(R.bool.display_notification_for_auto_update);

        metadataRequest.setTitle(res.getString(R.string.download_description));
        metadataRequest.setNotificationVisibility(notificationVisible
                ? Request.VISIBILITY_VISIBLE : Request.VISIBILITY_HIDDEN);
        metadataRequest.setVisibleInDownloadsUi(
                res.getBoolean(R.bool.metadata_downloads_visible_in_download_UI));

        final DownloadManager manager =
                (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
        if (null == manager) {
            // Download manager is not installed or disabled.
            // TODO: fall back to self-managed download?
            return;
        }
        cancelUpdateWithDownloadManager(context, metadataUri, manager);
        final long downloadId;
        synchronized (sSharedIdProtector) {
            downloadId = manager.enqueue(metadataRequest);
            Utils.l("Metadata download requested with id", downloadId);
            // If there is already a download in progress, it's been there for a while and
            // there is probably something wrong with download manager. It's best to just
            // overwrite the id and request it again. If the old one happens to finish
            // anyway, we don't know about its ID any more, so the downloadFinished
            // method will ignore it.
            writeMetadataDownloadId(context, metadataUri, downloadId);
        }
        PrivateLog.log("Requested download with id " + downloadId);
    }

    /**
     * Cancels a pending update, if there is one.
     *
     * If none, this is a no-op.
     *
     * @param context the context to open the database on
     * @param clientId the id of the client
     * @param manager an instance of DownloadManager
     */
    private static void cancelUpdateWithDownloadManager(final Context context,
            final String clientId, final DownloadManager manager) {
        synchronized (sSharedIdProtector) {
            final long metadataDownloadId =
                    MetadataDbHelper.getMetadataDownloadIdForClient(context, clientId);
            if (NOT_AN_ID == metadataDownloadId) return;
            manager.remove(metadataDownloadId);
            writeMetadataDownloadId(context,
                    MetadataDbHelper.getMetadataUriAsString(context, clientId), NOT_AN_ID);
        }
        // Consider a cancellation as a failure. As such, inform listeners that the download
        // has failed.
        for (UpdateEventListener listener : linkedCopyOfList(sUpdateEventListeners)) {
            listener.downloadedMetadata(false);
        }
    }

    /**
     * Cancels a pending update, if there is one.
     *
     * If there is none, this is a no-op. This is a helper method that gets the
     * download manager service.
     *
     * @param context the context, to get an instance of DownloadManager
     * @param clientId the ID of the client we want to cancel the update of
     */
    public static void cancelUpdate(final Context context, final String clientId) {
        final DownloadManager manager =
                    (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
        if (null != manager) cancelUpdateWithDownloadManager(context, clientId, manager);
    }

    /**
     * Registers a download request and flags it as downloading in the metadata table.
     *
     * This is a helper method that exists to avoid race conditions where DownloadManager might
     * finish downloading the file before the data is committed to the database.
     * It registers the request with the DownloadManager service and also updates the metadata
     * database directly within a synchronized section.
     * This method has no intelligence about the data it commits to the database aside from the
     * download request id, which is not known before submitting the request to the download
     * manager. Hence, it only updates the relevant line.
     *
     * @param manager the download manager service to register the request with.
     * @param request the request to register.
     * @param db the metadata database.
     * @param id the id of the word list.
     * @param version the version of the word list.
     * @return the download id returned by the download manager.
     */
    public static long registerDownloadRequest(final DownloadManager manager, final Request request,
            final SQLiteDatabase db, final String id, final int version) {
        Utils.l("RegisterDownloadRequest for word list id : ", id, ", version ", version);
        final long downloadId;
        synchronized (sSharedIdProtector) {
            downloadId = manager.enqueue(request);
            Utils.l("Download requested with id", downloadId);
            MetadataDbHelper.markEntryAsDownloading(db, id, version, downloadId);
        }
        return downloadId;
    }

    /**
     * Retrieve information about a specific download from DownloadManager.
     */
    private static CompletedDownloadInfo getCompletedDownloadInfo(final DownloadManager manager,
            final long downloadId) {
        final Query query = new Query().setFilterById(downloadId);
        final Cursor cursor = manager.query(query);

        if (null == cursor) {
            return new CompletedDownloadInfo(null, downloadId, DownloadManager.STATUS_FAILED);
        }
        try {
            final String uri;
            final int status;
            if (cursor.moveToNext()) {
                final int columnStatus = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
                final int columnError = cursor.getColumnIndex(DownloadManager.COLUMN_REASON);
                final int columnUri = cursor.getColumnIndex(DownloadManager.COLUMN_URI);
                final int error = cursor.getInt(columnError);
                status = cursor.getInt(columnStatus);
                final String uriWithAnchor = cursor.getString(columnUri);
                int anchorIndex = uriWithAnchor.indexOf('#');
                if (anchorIndex != -1) {
                    uri = uriWithAnchor.substring(0, anchorIndex);
                } else {
                    uri = uriWithAnchor;
                }
                if (DownloadManager.STATUS_SUCCESSFUL != status) {
                    Log.e(TAG, "Permanent failure of download " + downloadId
                            + " with error code: " + error);
                }
            } else {
                uri = null;
                status = DownloadManager.STATUS_FAILED;
            }
            return new CompletedDownloadInfo(uri, downloadId, status);
        } finally {
            cursor.close();
        }
    }

    private static ArrayList<DownloadRecord> getDownloadRecordsForCompletedDownloadInfo(
            final Context context, final CompletedDownloadInfo downloadInfo) {
        // Get and check the ID of the file we are waiting for, compare them to downloaded ones
        synchronized(sSharedIdProtector) {
            final ArrayList<DownloadRecord> downloadRecords =
                    MetadataDbHelper.getDownloadRecordsForDownloadId(context,
                            downloadInfo.mDownloadId);
            // If any of these is metadata, we should update the DB
            boolean hasMetadata = false;
            for (DownloadRecord record : downloadRecords) {
                if (null == record.mAttributes) {
                    hasMetadata = true;
                    break;
                }
            }
            if (hasMetadata) {
                writeMetadataDownloadId(context, downloadInfo.mUri, NOT_AN_ID);
                MetadataDbHelper.saveLastUpdateTimeOfUri(context, downloadInfo.mUri);
            }
            return downloadRecords;
        }
    }

    /**
     * Take appropriate action after a download finished, in success or in error.
     *
     * This is called by the system upon broadcast from the DownloadManager that a file
     * has been downloaded successfully.
     * After a simple check that this is actually the file we are waiting for, this
     * method basically coordinates the parsing and comparison of metadata, and fires
     * the computation of the list of actions that should be taken then executes them.
     *
     * @param context The context for this action.
     * @param intent The intent from the DownloadManager containing details about the download.
     */
    /* package */ static void downloadFinished(final Context context, final Intent intent) {
        // Get and check the ID of the file that was downloaded
        final long fileId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, NOT_AN_ID);
        PrivateLog.log("Download finished with id " + fileId);
        Utils.l("DownloadFinished with id", fileId);
        if (NOT_AN_ID == fileId) return; // Spurious wake-up: ignore

        final DownloadManager manager =
                (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
        final CompletedDownloadInfo downloadInfo = getCompletedDownloadInfo(manager, fileId);

        final ArrayList<DownloadRecord> recordList =
                getDownloadRecordsForCompletedDownloadInfo(context, downloadInfo);
        if (null == recordList) return; // It was someone else's download.
        Utils.l("Received result for download ", fileId);

        // TODO: handle gracefully a null pointer here. This is practically impossible because
        // we come here only when DownloadManager explicitly called us when it ended a
        // download, so we are pretty sure it's alive. It's theoretically possible that it's
        // disabled right inbetween the firing of the intent and the control reaching here.

        for (final DownloadRecord record : recordList) {
            // downloadSuccessful is not final because we may still have exceptions from now on
            boolean downloadSuccessful = false;
            try {
                if (downloadInfo.wasSuccessful()) {
                    downloadSuccessful = handleDownloadedFile(context, record, manager, fileId);
                }
            } finally {
                if (record.isMetadata()) {
                    publishUpdateMetadataCompleted(context, downloadSuccessful);
                } else {
                    final SQLiteDatabase db = MetadataDbHelper.getDb(context, record.mClientId);
                    publishUpdateWordListCompleted(context, downloadSuccessful, fileId,
                            db, record.mAttributes, record.mClientId);
                }
            }
        }
        // Now that we're done using it, we can remove this download from DLManager
        manager.remove(fileId);
    }

    /**
     * Sends a broadcast informing listeners that the dictionaries were updated.
     *
     * This will call all local listeners through the UpdateEventListener#downloadedMetadata
     * callback (for example, the dictionary provider interface uses this to stop the Loading
     * animation) and send a broadcast about the metadata having been updated. For a client of
     * the dictionary pack like Latin IME, this means it should re-query the dictionary pack
     * for any relevant new data.
     *
     * @param context the context, to send the broadcast.
     * @param downloadSuccessful whether the download of the metadata was successful or not.
     */
    public static void publishUpdateMetadataCompleted(final Context context,
            final boolean downloadSuccessful) {
        // We need to warn all listeners of what happened. But some listeners may want to
        // remove themselves or re-register something in response. Hence we should take a
        // snapshot of the listener list and warn them all. This also prevents any
        // concurrent modification problem of the static list.
        for (UpdateEventListener listener : linkedCopyOfList(sUpdateEventListeners)) {
            listener.downloadedMetadata(downloadSuccessful);
        }
        publishUpdateCycleCompletedEvent(context);
    }

    private static void publishUpdateWordListCompleted(final Context context,
            final boolean downloadSuccessful, final long fileId,
            final SQLiteDatabase db, final ContentValues downloadedFileRecord,
            final String clientId) {
        synchronized(sSharedIdProtector) {
            if (downloadSuccessful) {
                final ActionBatch actions = new ActionBatch();
                actions.add(new ActionBatch.InstallAfterDownloadAction(clientId,
                        downloadedFileRecord));
                actions.execute(context, new LogProblemReporter(TAG));
            } else {
                MetadataDbHelper.deleteDownloadingEntry(db, fileId);
            }
        }
        // See comment above about #linkedCopyOfLists
        for (UpdateEventListener listener : linkedCopyOfList(sUpdateEventListeners)) {
            listener.wordListDownloadFinished(downloadedFileRecord.getAsString(
                            MetadataDbHelper.WORDLISTID_COLUMN), downloadSuccessful);
        }
        publishUpdateCycleCompletedEvent(context);
    }

    private static void publishUpdateCycleCompletedEvent(final Context context) {
        // Even if this is not successful, we have to publish the new state.
        PrivateLog.log("Publishing update cycle completed event");
        Utils.l("Publishing update cycle completed event");
        for (UpdateEventListener listener : linkedCopyOfList(sUpdateEventListeners)) {
            listener.updateCycleCompleted();
        }
        signalNewDictionaryState(context);
    }

    private static boolean handleDownloadedFile(final Context context,
            final DownloadRecord downloadRecord, final DownloadManager manager,
            final long fileId) {
        try {
            // {@link handleWordList(Context,InputStream,ContentValues)}.
            // Handle the downloaded file according to its type
            if (downloadRecord.isMetadata()) {
                Utils.l("Data D/L'd is metadata for", downloadRecord.mClientId);
                // #handleMetadata() closes its InputStream argument
                handleMetadata(context, new ParcelFileDescriptor.AutoCloseInputStream(
                        manager.openDownloadedFile(fileId)), downloadRecord.mClientId);
            } else {
                Utils.l("Data D/L'd is a word list");
                final int wordListStatus = downloadRecord.mAttributes.getAsInteger(
                        MetadataDbHelper.STATUS_COLUMN);
                if (MetadataDbHelper.STATUS_DOWNLOADING == wordListStatus) {
                    // #handleWordList() closes its InputStream argument
                    handleWordList(context, new ParcelFileDescriptor.AutoCloseInputStream(
                            manager.openDownloadedFile(fileId)), downloadRecord);
                } else {
                    Log.e(TAG, "Spurious download ended. Maybe a cancelled download?");
                }
            }
            return true;
        } catch (FileNotFoundException e) {
            Log.e(TAG, "A file was downloaded but it can't be opened", e);
        } catch (IOException e) {
            // Can't read the file... disk damage?
            Log.e(TAG, "Can't read a file", e);
            // TODO: Check with UX how we should warn the user.
        } catch (IllegalStateException e) {
            // The format of the downloaded file is incorrect. We should maybe report upstream?
            Log.e(TAG, "Incorrect data received", e);
        } catch (BadFormatException e) {
            // The format of the downloaded file is incorrect. We should maybe report upstream?
            Log.e(TAG, "Incorrect data received", e);
        }
        return false;
    }

    /**
     * Returns a copy of the specified list, with all elements copied.
     *
     * This returns a linked list.
     */
    private static <T> List<T> linkedCopyOfList(final List<T> src) {
        // Instantiation of a parameterized type is not possible in Java, so it's not possible to
        // return the same type of list that was passed - probably the same reason why Collections
        // does not do it. So we need to decide statically which concrete type to return.
        return new LinkedList<T>(src);
    }

    /**
     * Warn Android Keyboard that the state of dictionaries changed and it should refresh its data.
     */
    private static void signalNewDictionaryState(final Context context) {
        final Intent newDictBroadcast =
                new Intent(DictionaryPackConstants.NEW_DICTIONARY_INTENT_ACTION);
        context.sendBroadcast(newDictBroadcast);
    }

    /**
     * Parse metadata and take appropriate action (that is, upgrade dictionaries).
     * @param context the context to read settings.
     * @param stream an input stream pointing to the downloaded data. May not be null.
     *  Will be closed upon finishing.
     * @param clientId the ID of the client to update
     * @throws BadFormatException if the metadata is not in a known format.
     * @throws IOException if the downloaded file can't be read from the disk
     */
    private static void handleMetadata(final Context context, final InputStream stream,
            final String clientId) throws IOException, BadFormatException {
        Utils.l("Entering handleMetadata");
        final List<WordListMetadata> newMetadata;
        final InputStreamReader reader = new InputStreamReader(stream);
        try {
            // According to the doc InputStreamReader buffers, so no need to add a buffering layer
            newMetadata = MetadataHandler.readMetadata(reader);
        } finally {
            reader.close();
        }

        Utils.l("Downloaded metadata :", newMetadata);
        PrivateLog.log("Downloaded metadata\n" + newMetadata);

        final ActionBatch actions = computeUpgradeTo(context, clientId, newMetadata);
        // TODO: Check with UX how we should report to the user
        // TODO: add an action to close the database
        actions.execute(context, new LogProblemReporter(TAG));
    }

    /**
     * Handle a word list: put it in its right place, and update the passed content values.
     * @param context the context for opening files.
     * @param inputStream an input stream pointing to the downloaded data. May not be null.
     *  Will be closed upon finishing.
     * @param downloadRecord the content values to fill the file name in.
     * @throws IOException if files can't be read or written.
     * @throws BadFormatException if the md5 checksum doesn't match the metadata.
     */
    private static void handleWordList(final Context context,
            final InputStream inputStream, final DownloadRecord downloadRecord)
            throws IOException, BadFormatException {

        // DownloadManager does not have the ability to put the file directly where we want
        // it, so we had it download to a temporary place. Now we move it. It will be deleted
        // automatically by DownloadManager.
        Utils.l("Downloaded a new word list :", downloadRecord.mAttributes.getAsString(
                MetadataDbHelper.DESCRIPTION_COLUMN), "for", downloadRecord.mClientId);
        PrivateLog.log("Downloaded a new word list with description : "
                + downloadRecord.mAttributes.getAsString(MetadataDbHelper.DESCRIPTION_COLUMN)
                + " for " + downloadRecord.mClientId);

        final String locale =
                downloadRecord.mAttributes.getAsString(MetadataDbHelper.LOCALE_COLUMN);
        final String destinationFile = getTempFileName(context, locale);
        downloadRecord.mAttributes.put(MetadataDbHelper.LOCAL_FILENAME_COLUMN, destinationFile);

        FileOutputStream outputStream = null;
        try {
            outputStream = context.openFileOutput(destinationFile, Context.MODE_PRIVATE);
            copyFile(inputStream, outputStream);
        } finally {
            inputStream.close();
            if (outputStream != null) {
                outputStream.close();
            }
        }

        // TODO: Consolidate this MD5 calculation with file copying above.
        // We need to reopen the file because the inputstream bytes have been consumed, and there
        // is nothing in InputStream to reopen or rewind the stream
        FileInputStream copiedFile = null;
        final String md5sum;
        try {
            copiedFile = context.openFileInput(destinationFile);
            md5sum = MD5Calculator.checksum(copiedFile);
        } finally {
            if (copiedFile != null) {
                copiedFile.close();
            }
        }
        if (TextUtils.isEmpty(md5sum)) {
            return; // We can't compute the checksum anyway, so return and hope for the best
        }
        if (!md5sum.equals(downloadRecord.mAttributes.getAsString(
                MetadataDbHelper.CHECKSUM_COLUMN))) {
            context.deleteFile(destinationFile);
            throw new BadFormatException("MD5 checksum check failed : \"" + md5sum + "\" <> \""
                    + downloadRecord.mAttributes.getAsString(MetadataDbHelper.CHECKSUM_COLUMN)
                    + "\"");
        }
    }

    /**
     * Copies in to out using FileChannels.
     *
     * This tries to use channels for fast copying. If it doesn't work, fall back to
     * copyFileFallBack below.
     *
     * @param in the stream to copy from.
     * @param out the stream to copy to.
     * @throws IOException if both the normal and fallback methods raise exceptions.
     */
    private static void copyFile(final InputStream in, final OutputStream out)
            throws IOException {
        Utils.l("Copying files");
        if (!(in instanceof FileInputStream) || !(out instanceof FileOutputStream)) {
            Utils.l("Not the right types");
            copyFileFallback(in, out);
        } else {
            try {
                final FileChannel sourceChannel = ((FileInputStream) in).getChannel();
                final FileChannel destinationChannel = ((FileOutputStream) out).getChannel();
                sourceChannel.transferTo(0, Integer.MAX_VALUE, destinationChannel);
            } catch (IOException e) {
                // Can't work with channels, or something went wrong. Copy by hand.
                Utils.l("Won't work");
                copyFileFallback(in, out);
            }
        }
    }

    /**
     * Copies in to out with read/write methods, not FileChannels.
     *
     * @param in the stream to copy from.
     * @param out the stream to copy to.
     * @throws IOException if a read or a write fails.
     */
    private static void copyFileFallback(final InputStream in, final OutputStream out)
            throws IOException {
        Utils.l("Falling back to slow copy");
        final byte[] buffer = new byte[FILE_COPY_BUFFER_SIZE];
        for (int readBytes = in.read(buffer); readBytes >= 0; readBytes = in.read(buffer))
            out.write(buffer, 0, readBytes);
    }

    /**
     * Creates and returns a new file to store a dictionary
     * @param context the context to use to open the file.
     * @param locale the locale for this dictionary, to make the file name more readable.
     * @return the file name, or throw an exception.
     * @throws IOException if the file cannot be created.
     */
    private static String getTempFileName(final Context context, final String locale)
            throws IOException {
        Utils.l("Entering openTempFileOutput");
        final File dir = context.getFilesDir();
        final File f = File.createTempFile(locale + "___", DICT_FILE_SUFFIX, dir);
        Utils.l("File name is", f.getName());
        return f.getName();
    }

    /**
     * Compare metadata (collections of word lists).
     *
     * This method takes whole metadata sets directly and compares them, matching the wordlists in
     * each of them on the id. It creates an ActionBatch object that can be .execute()'d to perform
     * the actual upgrade from `from' to `to'.
     *
     * @param context the context to open databases on.
     * @param clientId the id of the client.
     * @param from the dictionary descriptor (as a list of wordlists) to upgrade from.
     * @param to the dictionary descriptor (as a list of wordlists) to upgrade to.
     * @return an ordered list of runnables to be called to upgrade.
     */
    private static ActionBatch compareMetadataForUpgrade(final Context context,
            final String clientId, List<WordListMetadata> from, List<WordListMetadata> to) {
        final ActionBatch actions = new ActionBatch();
        // Upgrade existing word lists
        Utils.l("Comparing dictionaries");
        final Set<String> wordListIds = new TreeSet<String>();
        // TODO: Can these be null?
        if (null == from) from = new ArrayList<WordListMetadata>();
        if (null == to) to = new ArrayList<WordListMetadata>();
        for (WordListMetadata wlData : from) wordListIds.add(wlData.mId);
        for (WordListMetadata wlData : to) wordListIds.add(wlData.mId);
        for (String id : wordListIds) {
            final WordListMetadata currentInfo = MetadataHandler.findWordListById(from, id);
            final WordListMetadata metadataInfo = MetadataHandler.findWordListById(to, id);
            // TODO: Remove the following unnecessary check, since we are now doing the filtering
            // inside findWordListById.
            final WordListMetadata newInfo = null == metadataInfo
                    || metadataInfo.mFormatVersion > MAXIMUM_SUPPORTED_FORMAT_VERSION
                            ? null : metadataInfo;
            Utils.l("Considering updating ", id, "currentInfo =", currentInfo);

            if (null == currentInfo && null == newInfo) {
                // This may happen if a new word list appeared that we can't handle.
                if (null == metadataInfo) {
                    // What happened? Bug in Set<>?
                    Log.e(TAG, "Got an id for a wordlist that is neither in from nor in to");
                } else {
                    // We may come here if there is a new word list that we can't handle.
                    Log.i(TAG, "Can't handle word list with id '" + id + "' because it has format"
                            + " version " + metadataInfo.mFormatVersion + " and the maximum version"
                            + "we can handle is " + MAXIMUM_SUPPORTED_FORMAT_VERSION);
                }
                continue;
            } else if (null == currentInfo) {
                // This is the case where a new list that we did not know of popped on the server.
                // Make it available.
                actions.add(new ActionBatch.MakeAvailableAction(clientId, newInfo));
            } else if (null == newInfo) {
                // This is the case where an old list we had is not in the server data any more.
                // Pass false to ForgetAction: this may be installed and we still want to apply
                // a forget-like action (remove the URL) if it is, so we want to turn off the
                // status == AVAILABLE check. If it's DELETING, this is the right thing to do,
                // as we want to leave the record as long as Android Keyboard has not deleted it ;
                // the record will be removed when the file is actually deleted.
                actions.add(new ActionBatch.ForgetAction(clientId, currentInfo, false));
            } else {
                final SQLiteDatabase db = MetadataDbHelper.getDb(context, clientId);
                if (newInfo.mVersion == currentInfo.mVersion) {
                    // If it's the same id/version, we update the DB with the new values.
                    // It doesn't matter too much if they didn't change.
                    actions.add(new ActionBatch.UpdateDataAction(clientId, newInfo));
                } else if (newInfo.mVersion > currentInfo.mVersion) {
                    // If it's a new version, it's a different entry in the database. Make it
                    // available, and if it's installed, also start the download.
                    final ContentValues values = MetadataDbHelper.getContentValuesByWordListId(db,
                            currentInfo.mId, currentInfo.mVersion);
                    final int status = values.getAsInteger(MetadataDbHelper.STATUS_COLUMN);
                    actions.add(new ActionBatch.MakeAvailableAction(clientId, newInfo));
                    if (status == MetadataDbHelper.STATUS_INSTALLED
                            || status == MetadataDbHelper.STATUS_DISABLED) {
                        actions.add(new ActionBatch.StartDownloadAction(clientId, newInfo, false));
                    } else {
                        // Pass true to ForgetAction: this is indeed an update to a non-installed
                        // word list, so activate status == AVAILABLE check
                        // In case the status is DELETING, this is the right thing to do. It will
                        // leave the entry as DELETING and remove its URL so that Android Keyboard
                        // can delete it the next time it starts up.
                        actions.add(new ActionBatch.ForgetAction(clientId, currentInfo, true));
                    }
                } else if (DEBUG) {
                    Log.i(TAG, "Not updating word list " + id
                            + " : current list timestamp is " + currentInfo.mLastUpdate
                                    + " ; new list timestamp is " + newInfo.mLastUpdate);
                }
            }
        }
        return actions;
    }

    /**
     * Computes an upgrade from the current state of the dictionaries to some desired state.
     * @param context the context for reading settings and files.
     * @param clientId the id of the client.
     * @param newMetadata the state we want to upgrade to.
     * @return the upgrade from the current state to the desired state, ready to be executed.
     */
    public static ActionBatch computeUpgradeTo(final Context context, final String clientId,
            final List<WordListMetadata> newMetadata) {
        final List<WordListMetadata> currentMetadata =
                MetadataHandler.getCurrentMetadata(context, clientId);
        return compareMetadataForUpgrade(context, clientId, currentMetadata, newMetadata);
    }

    /**
     * Shows the notification that informs the user a dictionary is available.
     *
     * When this notification is clicked, the dialog for downloading the dictionary
     * over a metered connection is shown.
     */
    private static void showDictionaryAvailableNotification(final Context context,
            final String clientId, final ContentValues installCandidate) {
        final String localeString = installCandidate.getAsString(MetadataDbHelper.LOCALE_COLUMN);
        final Intent intent = new Intent();
        intent.setClass(context, DownloadOverMeteredDialog.class);
        intent.putExtra(DownloadOverMeteredDialog.CLIENT_ID_KEY, clientId);
        intent.putExtra(DownloadOverMeteredDialog.WORDLIST_TO_DOWNLOAD_KEY,
                installCandidate.getAsString(MetadataDbHelper.WORDLISTID_COLUMN));
        intent.putExtra(DownloadOverMeteredDialog.SIZE_KEY,
                installCandidate.getAsInteger(MetadataDbHelper.FILESIZE_COLUMN));
        intent.putExtra(DownloadOverMeteredDialog.LOCALE_KEY, localeString);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
        final PendingIntent notificationIntent = PendingIntent.getActivity(context,
                0 /* requestCode */, intent,
                PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_ONE_SHOT);
        final NotificationManager notificationManager =
                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
        // None of those are expected to happen, but just in case...
        if (null == notificationIntent || null == notificationManager) return;

        final Locale locale = LocaleUtils.constructLocaleFromString(localeString);
        final String language = (null == locale ? "" : locale.getDisplayLanguage());
        final String titleFormat = context.getString(R.string.dict_available_notification_title);
        final String notificationTitle = String.format(titleFormat, language);
        final Notification notification = new Notification.Builder(context)
                .setAutoCancel(true)
                .setContentIntent(notificationIntent)
                .setContentTitle(notificationTitle)
                .setContentText(context.getString(R.string.dict_available_notification_description))
                .setTicker(notificationTitle)
                .setOngoing(false)
                .setOnlyAlertOnce(true)
                .setSmallIcon(R.drawable.ic_notify_dictionary)
                .getNotification();
        notificationManager.notify(DICT_AVAILABLE_NOTIFICATION_ID, notification);
    }

    /**
     * Installs a word list if it has never been requested.
     *
     * This is called when a word list is requested, and is available but not installed. It checks
     * the conditions for auto-installation: if the dictionary is a main dictionary for this
     * language, and it has never been opted out through the dictionary interface, then we start
     * installing it. For the user who enables a language and uses it for the first time, the
     * dictionary should magically start being used a short time after they start typing.
     * The mayPrompt argument indicates whether we should prompt the user for a decision to
     * download or not, in case we decide we are in the case where we should download - this
     * roughly happens when the current connectivity is 3G. See
     * DictionaryProvider#getDictionaryWordListsForContentUri for details.
     */
    // As opposed to many other methods, this method does not need the version of the word
    // list because it may only install the latest version we know about for this specific
    // word list ID / client ID combination.
    public static void installIfNeverRequested(final Context context, final String clientId,
            final String wordlistId, final boolean mayPrompt) {
        final String[] idArray = wordlistId.split(DictionaryProvider.ID_CATEGORY_SEPARATOR);
        // If we have a new-format dictionary id (category:manual_id), then use the
        // specified category. Otherwise, it is a main dictionary, so force the
        // MAIN category upon it.
        final String category = 2 == idArray.length ? idArray[0] : MAIN_DICTIONARY_CATEGORY;
        if (!MAIN_DICTIONARY_CATEGORY.equals(category)) {
            // Not a main dictionary. We only auto-install main dictionaries, so we can return now.
            return;
        }
        if (CommonPreferences.getCommonPreferences(context).contains(wordlistId)) {
            // If some kind of settings has been done in the past for this specific id, then
            // this is not a candidate for auto-install. Because it already is either true,
            // in which case it may be installed or downloading or whatever, and we don't
            // need to care about it because it's already handled or being handled, or it's false
            // in which case it means the user explicitely turned it off and don't want to have
            // it installed. So we quit right away.
            return;
        }

        final SQLiteDatabase db = MetadataDbHelper.getDb(context, clientId);
        final ContentValues installCandidate =
                MetadataDbHelper.getContentValuesOfLatestAvailableWordlistById(db, wordlistId);
        if (MetadataDbHelper.STATUS_AVAILABLE
                != installCandidate.getAsInteger(MetadataDbHelper.STATUS_COLUMN)) {
            // If it's not "AVAILABLE", we want to stop now. Because candidates for auto-install
            // are lists that we know are available, but we also know have never been installed.
            // It does obviously not concern already installed lists, or downloading lists,
            // or those that have been disabled, flagged as deleting... So anything else than
            // AVAILABLE means we don't auto-install.
            return;
        }

        if (mayPrompt
                && DOWNLOAD_OVER_METERED_SETTING_UNKNOWN
                        == getDownloadOverMeteredSetting(context)) {
            final ConnectivityManager cm =
                    (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
            if (ConnectivityManagerCompatUtils.isActiveNetworkMetered(cm)) {
                showDictionaryAvailableNotification(context, clientId, installCandidate);
                return;
            }
        }

        // We decided against prompting the user for a decision. This may be because we were
        // explicitly asked not to, or because we are currently on wi-fi anyway, or because we
        // already know the answer to the question. We'll enqueue a request ; StartDownloadAction
        // knows to use the correct type of network according to the current settings.

        // Also note that once it's auto-installed, a word list will be marked as INSTALLED. It will
        // thus receive automatic updates if there are any, which is what we want. If the user does
        // not want this word list, they will have to go to the settings and change them, which will
        // change the shared preferences. So there is no way for a word list that has been
        // auto-installed once to get auto-installed again, and that's what we want.
        final ActionBatch actions = new ActionBatch();
        actions.add(new ActionBatch.StartDownloadAction(clientId,
                WordListMetadata.createFromContentValues(installCandidate), false));
        final String localeString = installCandidate.getAsString(MetadataDbHelper.LOCALE_COLUMN);
        // We are in a content provider: we can't do any UI at all. We have to defer the displaying
        // itself to the service. Also, we only display this when the user does not have a
        // dictionary for this language already: we know that from the mayPrompt argument.
        if (mayPrompt) {
            final Intent intent = new Intent();
            intent.setClass(context, DictionaryService.class);
            intent.setAction(DictionaryService.SHOW_DOWNLOAD_TOAST_INTENT_ACTION);
            intent.putExtra(DictionaryService.LOCALE_INTENT_ARGUMENT, localeString);
            context.startService(intent);
        }
        actions.execute(context, new LogProblemReporter(TAG));
    }

    /**
     * Marks the word list with the passed id as used.
     *
     * This will download/install the list as required. The action will see that the destination
     * word list is a valid list, and take appropriate action - in this case, mark it as used.
     * @see ActionBatch.Action#execute
     *
     * @param context the context for using action batches.
     * @param clientId the id of the client.
     * @param wordlistId the id of the word list to mark as installed.
     * @param version the version of the word list to mark as installed.
     * @param status the current status of the word list.
     * @param allowDownloadOnMeteredData whether to download even on metered data connection
     */
    // The version argument is not used yet, because we don't need it to retrieve the information
    // we need. However, the pair (id, version) being the primary key to a word list in the database
    // it feels better for consistency to pass it, and some methods retrieving information about a
    // word list need it so we may need it in the future.
    public static void markAsUsed(final Context context, final String clientId,
            final String wordlistId, final int version,
            final int status, final boolean allowDownloadOnMeteredData) {
        final List<WordListMetadata> currentMetadata =
                MetadataHandler.getCurrentMetadata(context, clientId);
        WordListMetadata wordList = MetadataHandler.findWordListById(currentMetadata, wordlistId);
        if (null == wordList) return;
        final ActionBatch actions = new ActionBatch();
        if (MetadataDbHelper.STATUS_DISABLED == status
                || MetadataDbHelper.STATUS_DELETING == status) {
            actions.add(new ActionBatch.EnableAction(clientId, wordList));
        } else if (MetadataDbHelper.STATUS_AVAILABLE == status) {
            actions.add(new ActionBatch.StartDownloadAction(clientId, wordList,
                    allowDownloadOnMeteredData));
        } else {
            Log.e(TAG, "Unexpected state of the word list for markAsUsed : " + status);
        }
        actions.execute(context, new LogProblemReporter(TAG));
        signalNewDictionaryState(context);
    }

    /**
     * Marks the word list with the passed id as unused.
     *
     * This leaves the file on the disk for ulterior use. The action will see that the destination
     * word list is null, and take appropriate action - in this case, mark it as unused.
     * @see ActionBatch.Action#execute
     *
     * @param context the context for using action batches.
     * @param clientId the id of the client.
     * @param wordlistId the id of the word list to mark as installed.
     * @param version the version of the word list to mark as installed.
     * @param status the current status of the word list.
     */
    // The version and status arguments are not used yet, but this method matches its interface to
    // markAsUsed for consistency.
    public static void markAsUnused(final Context context, final String clientId,
            final String wordlistId, final int version, final int status) {
        final List<WordListMetadata> currentMetadata =
                MetadataHandler.getCurrentMetadata(context, clientId);
        final WordListMetadata wordList =
                MetadataHandler.findWordListById(currentMetadata, wordlistId);
        if (null == wordList) return;
        final ActionBatch actions = new ActionBatch();
        actions.add(new ActionBatch.DisableAction(clientId, wordList));
        actions.execute(context, new LogProblemReporter(TAG));
        signalNewDictionaryState(context);
    }

    /**
     * Marks the word list with the passed id as deleting.
     *
     * This basically means that on the next chance there is (right away if Android Keyboard
     * happens to be up, or the next time it gets up otherwise) the dictionary pack will
     * supply an empty dictionary to it that will replace whatever dictionary is installed.
     * This allows to release the space taken by a dictionary (except for the few bytes the
     * empty dictionary takes up), and override a built-in default dictionary so that we
     * can fake delete a built-in dictionary.
     *
     * @param context the context to open the database on.
     * @param clientId the id of the client.
     * @param wordlistId the id of the word list to mark as deleted.
     * @param version the version of the word list to mark as deleted.
     * @param status the current status of the word list.
     */
    public static void markAsDeleting(final Context context, final String clientId,
            final String wordlistId, final int version, final int status) {
        final List<WordListMetadata> currentMetadata =
                MetadataHandler.getCurrentMetadata(context, clientId);
        final WordListMetadata wordList =
                MetadataHandler.findWordListById(currentMetadata, wordlistId);
        if (null == wordList) return;
        final ActionBatch actions = new ActionBatch();
        actions.add(new ActionBatch.DisableAction(clientId, wordList));
        actions.add(new ActionBatch.StartDeleteAction(clientId, wordList));
        actions.execute(context, new LogProblemReporter(TAG));
        signalNewDictionaryState(context);
    }

    /**
     * Marks the word list with the passed id as actually deleted.
     *
     * This reverts to available status or deletes the row as appropriate.
     *
     * @param context the context to open the database on.
     * @param clientId the id of the client.
     * @param wordlistId the id of the word list to mark as deleted.
     * @param version the version of the word list to mark as deleted.
     * @param status the current status of the word list.
     */
    public static void markAsDeleted(final Context context, final String clientId,
            final String wordlistId, final int version, final int status) {
        final List<WordListMetadata> currentMetadata =
                MetadataHandler.getCurrentMetadata(context, clientId);
        final WordListMetadata wordList =
                MetadataHandler.findWordListById(currentMetadata, wordlistId);
        if (null == wordList) return;
        final ActionBatch actions = new ActionBatch();
        actions.add(new ActionBatch.FinishDeleteAction(clientId, wordList));
        actions.execute(context, new LogProblemReporter(TAG));
        signalNewDictionaryState(context);
    }

    /**
     * Marks the word list with the passed id as broken.
     *
     * This effectively deletes the entry from the metadata. It doesn't prevent the same
     * word list to be downloaded again at a later time if the same or a new version is
     * available the next time we download the metadata.
     *
     * @param context the context to open the database on.
     * @param clientId the id of the client.
     * @param wordlistId the id of the word list to mark as broken.
     * @param version the version of the word list to mark as deleted.
     */
    public static void markAsBroken(final Context context, final String clientId,
            final String wordlistId, final int version) {
        // TODO: do this on another thread to avoid blocking the UI.
        MetadataDbHelper.deleteEntry(MetadataDbHelper.getDb(context, clientId),
                wordlistId, version);
    }
}
