/**
 * 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.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.content.res.AssetFileDescriptor;
import android.database.AbstractCursor;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.text.TextUtils;
import android.util.Log;

import com.android.inputmethod.latin.R;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;

/**
 * Provider for dictionaries.
 *
 * This class is a ContentProvider exposing all available dictionary data as managed by
 * the dictionary pack.
 */
public final class DictionaryProvider extends ContentProvider {
    private static final String TAG = DictionaryProvider.class.getSimpleName();
    public static final boolean DEBUG = false;

    public static final Uri CONTENT_URI =
            Uri.parse(ContentResolver.SCHEME_CONTENT + "://" + DictionaryPackConstants.AUTHORITY);
    private static final String QUERY_PARAMETER_MAY_PROMPT_USER = "mayPrompt";
    private static final String QUERY_PARAMETER_TRUE = "true";
    private static final String QUERY_PARAMETER_DELETE_RESULT = "result";
    private static final String QUERY_PARAMETER_SUCCESS = "success";
    private static final String QUERY_PARAMETER_FAILURE = "failure";
    public static final String QUERY_PARAMETER_PROTOCOL_VERSION = "protocol";
    private static final int NO_MATCH = 0;
    private static final int DICTIONARY_V1_WHOLE_LIST = 1;
    private static final int DICTIONARY_V1_DICT_INFO = 2;
    private static final int DICTIONARY_V2_METADATA = 3;
    private static final int DICTIONARY_V2_WHOLE_LIST = 4;
    private static final int DICTIONARY_V2_DICT_INFO = 5;
    private static final int DICTIONARY_V2_DATAFILE = 6;
    private static final UriMatcher sUriMatcherV1 = new UriMatcher(NO_MATCH);
    private static final UriMatcher sUriMatcherV2 = new UriMatcher(NO_MATCH);
    static
    {
        sUriMatcherV1.addURI(DictionaryPackConstants.AUTHORITY, "list", DICTIONARY_V1_WHOLE_LIST);
        sUriMatcherV1.addURI(DictionaryPackConstants.AUTHORITY, "*", DICTIONARY_V1_DICT_INFO);
        sUriMatcherV2.addURI(DictionaryPackConstants.AUTHORITY, "*/metadata",
                DICTIONARY_V2_METADATA);
        sUriMatcherV2.addURI(DictionaryPackConstants.AUTHORITY, "*/list", DICTIONARY_V2_WHOLE_LIST);
        sUriMatcherV2.addURI(DictionaryPackConstants.AUTHORITY, "*/dict/*",
                DICTIONARY_V2_DICT_INFO);
        sUriMatcherV2.addURI(DictionaryPackConstants.AUTHORITY, "*/datafile/*",
                DICTIONARY_V2_DATAFILE);
    }

    // MIME types for dictionary and dictionary list, as required by ContentProvider contract.
    public static final String DICT_LIST_MIME_TYPE =
            "vnd.android.cursor.item/vnd.google.dictionarylist";
    public static final String DICT_DATAFILE_MIME_TYPE =
            "vnd.android.cursor.item/vnd.google.dictionary";

    public static final String ID_CATEGORY_SEPARATOR = ":";

    private static final class WordListInfo {
        public final String mId;
        public final String mLocale;
        public final int mMatchLevel;
        public WordListInfo(final String id, final String locale, final int matchLevel) {
            mId = id;
            mLocale = locale;
            mMatchLevel = matchLevel;
        }
    }

    /**
     * A cursor for returning a list of file ids from a List of strings.
     *
     * This simulates only the necessary methods. It has no error handling to speak of,
     * and does not support everything a database does, only a few select necessary methods.
     */
    private static final class ResourcePathCursor extends AbstractCursor {

        // Column names for the cursor returned by this content provider.
        static private final String[] columnNames = { "id", "locale" };

        // The list of word lists served by this provider that match the client request.
        final WordListInfo[] mWordLists;
        // Note : the cursor also uses mPos, which is defined in AbstractCursor.

        public ResourcePathCursor(final Collection<WordListInfo> wordLists) {
            // Allocating a 0-size WordListInfo here allows the toArray() method
            // to ensure we have a strongly-typed array. It's thrown out. That's
            // what the documentation of #toArray says to do in order to get a
            // new strongly typed array of the correct size.
            mWordLists = wordLists.toArray(new WordListInfo[0]);
            mPos = 0;
        }

        @Override
        public String[] getColumnNames() {
            return columnNames;
        }

        @Override
        public int getCount() {
            return mWordLists.length;
        }

        @Override public double getDouble(int column) { return 0; }
        @Override public float getFloat(int column) { return 0; }
        @Override public int getInt(int column) { return 0; }
        @Override public short getShort(int column) { return 0; }
        @Override public long getLong(int column) { return 0; }

        @Override public String getString(final int column) {
            switch (column) {
                case 0: return mWordLists[mPos].mId;
                case 1: return mWordLists[mPos].mLocale;
                default : return null;
            }
        }

        @Override
        public boolean isNull(final int column) {
            if (mPos >= mWordLists.length) return true;
            return column != 0;
        }
    }

    @Override
    public boolean onCreate() {
        return true;
    }

    private static int matchUri(final Uri uri) {
        int protocolVersion = 1;
        final String protocolVersionArg = uri.getQueryParameter(QUERY_PARAMETER_PROTOCOL_VERSION);
        if ("2".equals(protocolVersionArg)) protocolVersion = 2;
        switch (protocolVersion) {
            case 1: return sUriMatcherV1.match(uri);
            case 2: return sUriMatcherV2.match(uri);
            default: return NO_MATCH;
        }
    }

    private static String getClientId(final Uri uri) {
        int protocolVersion = 1;
        final String protocolVersionArg = uri.getQueryParameter(QUERY_PARAMETER_PROTOCOL_VERSION);
        if ("2".equals(protocolVersionArg)) protocolVersion = 2;
        switch (protocolVersion) {
            case 1: return null; // In protocol 1, the client ID is always null.
            case 2: return uri.getPathSegments().get(0);
            default: return null;
        }
    }

    /**
     * Returns the MIME type of the content associated with an Uri
     *
     * @see android.content.ContentProvider#getType(android.net.Uri)
     *
     * @param uri the URI of the content the type of which should be returned.
     * @return the MIME type, or null if the URL is not recognized.
     */
    @Override
    public String getType(final Uri uri) {
        PrivateLog.log("Asked for type of : " + uri);
        final int match = matchUri(uri);
        switch (match) {
            case NO_MATCH: return null;
            case DICTIONARY_V1_WHOLE_LIST:
            case DICTIONARY_V1_DICT_INFO:
            case DICTIONARY_V2_WHOLE_LIST:
            case DICTIONARY_V2_DICT_INFO: return DICT_LIST_MIME_TYPE;
            case DICTIONARY_V2_DATAFILE: return DICT_DATAFILE_MIME_TYPE;
            default: return null;
        }
    }

    /**
     * Query the provider for dictionary files.
     *
     * This version dispatches the query according to the protocol version found in the
     * ?protocol= query parameter. If absent or not well-formed, it defaults to 1.
     * @see android.content.ContentProvider#query(Uri, String[], String, String[], String)
     *
     * @param uri a content uri (see sUriMatcherV{1,2} at the top of this file for format)
     * @param projection ignored. All columns are always returned.
     * @param selection ignored.
     * @param selectionArgs ignored.
     * @param sortOrder ignored. The results are always returned in no particular order.
     * @return a cursor matching the uri, or null if the URI was not recognized.
     */
    @Override
    public Cursor query(final Uri uri, final String[] projection, final String selection,
            final String[] selectionArgs, final String sortOrder) {
        Utils.l("Uri =", uri);
        PrivateLog.log("Query : " + uri);
        final String clientId = getClientId(uri);
        final int match = matchUri(uri);
        switch (match) {
            case DICTIONARY_V1_WHOLE_LIST:
            case DICTIONARY_V2_WHOLE_LIST:
                final Cursor c = MetadataDbHelper.queryDictionaries(getContext(), clientId);
                Utils.l("List of dictionaries with count", c.getCount());
                PrivateLog.log("Returned a list of " + c.getCount() + " items");
                return c;
            case DICTIONARY_V2_DICT_INFO:
                // In protocol version 2, we return null if the client is unknown. Otherwise
                // we behave exactly like for protocol 1.
                if (!MetadataDbHelper.isClientKnown(getContext(), clientId)) return null;
                // Fall through
            case DICTIONARY_V1_DICT_INFO:
                final String locale = uri.getLastPathSegment();
                // If LatinIME does not have a dictionary for this locale at all, it will
                // send us true for this value. In this case, we may prompt the user for
                // a decision about downloading a dictionary even over a metered connection.
                final String mayPromptValue =
                        uri.getQueryParameter(QUERY_PARAMETER_MAY_PROMPT_USER);
                final boolean mayPrompt = QUERY_PARAMETER_TRUE.equals(mayPromptValue);
                final Collection<WordListInfo> dictFiles =
                        getDictionaryWordListsForLocale(clientId, locale, mayPrompt);
                // TODO: pass clientId to the following function
                DictionaryService.updateNowIfNotUpdatedInAVeryLongTime(getContext());
                if (null != dictFiles && dictFiles.size() > 0) {
                    PrivateLog.log("Returned " + dictFiles.size() + " files");
                    return new ResourcePathCursor(dictFiles);
                } else {
                    PrivateLog.log("No dictionary files for this URL");
                    return new ResourcePathCursor(Collections.<WordListInfo>emptyList());
                }
            // V2_METADATA and V2_DATAFILE are not supported for query()
            default:
                return null;
        }
    }

    /**
     * Helper method to get the wordlist metadata associated with a wordlist ID.
     *
     * @param clientId the ID of the client
     * @param wordlistId the ID of the wordlist for which to get the metadata.
     * @return the metadata for this wordlist ID, or null if none could be found.
     */
    private ContentValues getWordlistMetadataForWordlistId(final String clientId,
            final String wordlistId) {
        final Context context = getContext();
        if (TextUtils.isEmpty(wordlistId)) return null;
        final SQLiteDatabase db = MetadataDbHelper.getDb(context, clientId);
        return MetadataDbHelper.getInstalledOrDeletingWordListContentValuesByWordListId(
                db, wordlistId);
    }

    /**
     * Opens an asset file for an URI.
     *
     * Called by {@link android.content.ContentResolver#openAssetFileDescriptor(Uri, String)} or
     * {@link android.content.ContentResolver#openInputStream(Uri)} from a client requesting a
     * dictionary.
     * @see android.content.ContentProvider#openAssetFile(Uri, String)
     *
     * @param uri the URI the file is for.
     * @param mode the mode to read the file. MUST be "r" for readonly.
     * @return the descriptor, or null if the file is not found or if mode is not equals to "r".
     */
    @Override
    public AssetFileDescriptor openAssetFile(final Uri uri, final String mode) {
        if (null == mode || !"r".equals(mode)) return null;

        final int match = matchUri(uri);
        if (DICTIONARY_V1_DICT_INFO != match && DICTIONARY_V2_DATAFILE != match) {
            // Unsupported URI for openAssetFile
            Log.w(TAG, "Unsupported URI for openAssetFile : " + uri);
            return null;
        }
        final String wordlistId = uri.getLastPathSegment();
        final String clientId = getClientId(uri);
        final ContentValues wordList = getWordlistMetadataForWordlistId(clientId, wordlistId);

        if (null == wordList) return null;

        try {
            final int status = wordList.getAsInteger(MetadataDbHelper.STATUS_COLUMN);
            if (MetadataDbHelper.STATUS_DELETING == status) {
                // This will return an empty file (R.raw.empty points at an empty dictionary)
                // This is how we "delete" the files. It allows Android Keyboard to fake deleting
                // a default dictionary - which is actually in its assets and can't be really
                // deleted.
                final AssetFileDescriptor afd = getContext().getResources().openRawResourceFd(
                        R.raw.empty);
                return afd;
            } else {
                final String localFilename =
                        wordList.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN);
                final File f = getContext().getFileStreamPath(localFilename);
                final ParcelFileDescriptor pfd =
                        ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
                return new AssetFileDescriptor(pfd, 0, pfd.getStatSize());
            }
        } catch (FileNotFoundException e) {
            // No file : fall through and return null
        }
        return null;
    }

    /**
     * Reads the metadata and returns the collection of dictionaries for a given locale.
     *
     * Word list IDs are expected to be in the form category:manual_id. This method
     * will select only one word list for each category: the one with the most specific
     * locale matching the locale specified in the URI. The manual id serves only to
     * distinguish a word list from another for the purpose of updating, and is arbitrary
     * but may not contain a colon.
     *
     * @param clientId the ID of the client requesting the list
     * @param locale the locale for which we want the list, as a String
     * @param mayPrompt true if we are allowed to prompt the user for arbitration via notification
     * @return a collection of ids. It is guaranteed to be non-null, but may be empty.
     */
    private Collection<WordListInfo> getDictionaryWordListsForLocale(final String clientId,
            final String locale, final boolean mayPrompt) {
        final Context context = getContext();
        final Cursor results =
                MetadataDbHelper.queryInstalledOrDeletingOrAvailableDictionaryMetadata(context,
                        clientId);
        if (null == results) {
            return Collections.<WordListInfo>emptyList();
        } else {
            final HashMap<String, WordListInfo> dicts = new HashMap<String, WordListInfo>();
            final int idIndex = results.getColumnIndex(MetadataDbHelper.WORDLISTID_COLUMN);
            final int localeIndex = results.getColumnIndex(MetadataDbHelper.LOCALE_COLUMN);
            final int localFileNameIndex =
                    results.getColumnIndex(MetadataDbHelper.LOCAL_FILENAME_COLUMN);
            final int statusIndex = results.getColumnIndex(MetadataDbHelper.STATUS_COLUMN);
            if (results.moveToFirst()) {
                do {
                    final String wordListId = results.getString(idIndex);
                    if (TextUtils.isEmpty(wordListId)) continue;
                    final String[] wordListIdArray =
                            TextUtils.split(wordListId, ID_CATEGORY_SEPARATOR);
                    final String wordListCategory;
                    if (2 == wordListIdArray.length) {
                        // This is at the category:manual_id format.
                        wordListCategory = wordListIdArray[0];
                        // We don't need to read wordListIdArray[1] here, because it's irrelevant to
                        // word list selection - it's just a name we use to identify which data file
                        // is a newer version of which word list. We do however return the full id
                        // string for each selected word list, so in this sense we are 'using' it.
                    } else {
                        // This does not contain a colon, like the old format does. Old-format IDs
                        // always point to main dictionaries, so we force the main category upon it.
                        wordListCategory = UpdateHandler.MAIN_DICTIONARY_CATEGORY;
                    }
                    final String wordListLocale = results.getString(localeIndex);
                    final String wordListLocalFilename = results.getString(localFileNameIndex);
                    final int wordListStatus = results.getInt(statusIndex);
                    // Test the requested locale against this wordlist locale. The requested locale
                    // has to either match exactly or be more specific than the dictionary - a
                    // dictionary for "en" would match both a request for "en" or for "en_US", but a
                    // dictionary for "en_GB" would not match a request for "en_US". Thus if all
                    // three of "en" "en_US" and "en_GB" dictionaries are installed, a request for
                    // "en_US" would match "en" and "en_US", and a request for "en" only would only
                    // match the generic "en" dictionary. For more details, see the documentation
                    // for LocaleUtils#getMatchLevel.
                    final int matchLevel = LocaleUtils.getMatchLevel(wordListLocale, locale);
                    if (!LocaleUtils.isMatch(matchLevel)) {
                        // The locale of this wordlist does not match the required locale.
                        // Skip this wordlist and go to the next.
                        continue;
                    }
                    if (MetadataDbHelper.STATUS_INSTALLED == wordListStatus) {
                        // If the file does not exist, it has been deleted and the IME should
                        // already have it. Do not return it. However, this only applies if the
                        // word list is INSTALLED, for if it is DELETING we should return it always
                        // so that Android Keyboard can perform the actual deletion.
                        final File f = getContext().getFileStreamPath(wordListLocalFilename);
                        if (!f.isFile()) {
                            continue;
                        }
                    } else if (MetadataDbHelper.STATUS_AVAILABLE == wordListStatus) {
                        // The locale is the id for the main dictionary.
                        UpdateHandler.installIfNeverRequested(context, clientId, wordListId,
                                mayPrompt);
                        continue;
                    }
                    final WordListInfo currentBestMatch = dicts.get(wordListCategory);
                    if (null == currentBestMatch
                            || currentBestMatch.mMatchLevel < matchLevel) {
                        dicts.put(wordListCategory,
                                new WordListInfo(wordListId, wordListLocale, matchLevel));
                    }
                } while (results.moveToNext());
            }
            results.close();
            return Collections.unmodifiableCollection(dicts.values());
        }
    }

    /**
     * Deletes the file pointed by Uri, as returned by openAssetFile.
     *
     * @param uri the URI the file is for.
     * @param selection ignored
     * @param selectionArgs ignored
     * @return the number of files deleted (0 or 1 in the current implementation)
     * @see android.content.ContentProvider#delete(Uri, String, String[])
     */
    @Override
    public int delete(final Uri uri, final String selection, final String[] selectionArgs)
            throws UnsupportedOperationException {
        final int match = matchUri(uri);
        if (DICTIONARY_V1_DICT_INFO == match || DICTIONARY_V2_DATAFILE == match) {
            return deleteDataFile(uri);
        }
        if (DICTIONARY_V2_METADATA == match) {
            if (MetadataDbHelper.deleteClient(getContext(), getClientId(uri))) {
                return 1;
            }
            return 0;
        }
        // Unsupported URI for delete
        return 0;
    }

    private int deleteDataFile(final Uri uri) {
        final String wordlistId = uri.getLastPathSegment();
        final String clientId = getClientId(uri);
        final ContentValues wordList = getWordlistMetadataForWordlistId(clientId, wordlistId);
        if (null == wordList) return 0;
        final int status = wordList.getAsInteger(MetadataDbHelper.STATUS_COLUMN);
        final int version = wordList.getAsInteger(MetadataDbHelper.VERSION_COLUMN);
        if (MetadataDbHelper.STATUS_DELETING == status) {
            UpdateHandler.markAsDeleted(getContext(), clientId, wordlistId, version, status);
            return 1;
        } else if (MetadataDbHelper.STATUS_INSTALLED == status) {
            final String result = uri.getQueryParameter(QUERY_PARAMETER_DELETE_RESULT);
            if (QUERY_PARAMETER_FAILURE.equals(result)) {
                UpdateHandler.markAsBroken(getContext(), clientId, wordlistId, version);
            }
            final String localFilename =
                    wordList.getAsString(MetadataDbHelper.LOCAL_FILENAME_COLUMN);
            final File f = getContext().getFileStreamPath(localFilename);
            // f.delete() returns true if the file was successfully deleted, false otherwise
            if (f.delete()) {
                return 1;
            } else {
                return 0;
            }
        } else {
            Log.e(TAG, "Attempt to delete a file whose status is " + status);
            return 0;
        }
    }

    /**
     * Insert data into the provider. May be either a metadata source URL or some dictionary info.
     *
     * @param uri the designated content URI. See sUriMatcherV{1,2} for available URIs.
     * @param values the values to insert for this content uri
     * @return the URI for the newly inserted item. May be null if arguments don't allow for insert
     */
    @Override
    public Uri insert(final Uri uri, final ContentValues values)
            throws UnsupportedOperationException {
        if (null == uri || null == values) return null; // Should never happen but let's be safe
        PrivateLog.log("Insert, uri = " + uri.toString());
        final String clientId = getClientId(uri);
        switch (matchUri(uri)) {
            case DICTIONARY_V2_METADATA:
                // The values should contain a valid client ID and a valid URI for the metadata.
                // The client ID may not be null, nor may it be empty because the empty client ID
                // is reserved for internal use.
                // The metadata URI may not be null, but it may be empty if the client does not
                // want the dictionary pack to update the metadata automatically.
                MetadataDbHelper.updateClientInfo(getContext(), clientId, values);
                break;
            case DICTIONARY_V2_DICT_INFO:
                try {
                    final WordListMetadata newDictionaryMetadata =
                            WordListMetadata.createFromContentValues(
                                    MetadataDbHelper.completeWithDefaultValues(values));
                    new ActionBatch.MarkPreInstalledAction(clientId, newDictionaryMetadata)
                            .execute(getContext());
                } catch (final BadFormatException e) {
                    Log.w(TAG, "Not enough information to insert this dictionary " + values, e);
                }
                // We just received new information about the list of dictionary for this client.
                // For all intents and purposes, this is new metadata, so we should publish it
                // so that any listeners (like the Settings interface for example) can update
                // themselves.
                UpdateHandler.publishUpdateMetadataCompleted(getContext(), true);
                break;
            case DICTIONARY_V1_WHOLE_LIST:
            case DICTIONARY_V1_DICT_INFO:
                PrivateLog.log("Attempt to insert : " + uri);
                throw new UnsupportedOperationException(
                        "Insertion in the dictionary is not supported in this version");
        }
        return uri;
    }

    /**
     * Updating data is not supported, and will throw an exception.
     * @see android.content.ContentProvider#update(Uri, ContentValues, String, String[])
     * @see android.content.ContentProvider#insert(Uri, ContentValues)
     */
    @Override
    public int update(final Uri uri, final ContentValues values, final String selection,
            final String[] selectionArgs) throws UnsupportedOperationException {
        PrivateLog.log("Attempt to update : " + uri);
        throw new UnsupportedOperationException("Updating dictionary words is not supported");
    }
}
