/**
 * 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.Context;
import android.content.SharedPreferences;
import android.preference.Preference;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.android.inputmethod.latin.R;

import java.util.Locale;

/**
 * A preference for one word list.
 *
 * This preference refers to a single word list, as available in the dictionary
 * pack. Upon being pressed, it displays a menu to allow the user to install, disable,
 * enable or delete it as appropriate for the current state of the word list.
 */
public final class WordListPreference extends Preference {
    static final private String TAG = WordListPreference.class.getSimpleName();

    // What to display in the "status" field when we receive unknown data as a status from
    // the content provider. Empty string sounds sensible.
    static final private String NO_STATUS_MESSAGE = "";

    /// Actions
    static final private int ACTION_UNKNOWN = 0;
    static final private int ACTION_ENABLE_DICT = 1;
    static final private int ACTION_DISABLE_DICT = 2;
    static final private int ACTION_DELETE_DICT = 3;

    // Members
    // The context to get resources
    final Context mContext;
    // The id of the client for which this preference is.
    final String mClientId;
    // The metadata word list id and version of this word list.
    public final String mWordlistId;
    public final int mVersion;
    // The status
    public int mStatus;
    // The size of the dictionary file
    private final int mFilesize;

    private final DictionaryListInterfaceState mInterfaceState;
    private final OnWordListPreferenceClick mPreferenceClickHandler =
            new OnWordListPreferenceClick();
    private final OnActionButtonClick mActionButtonClickHandler =
            new OnActionButtonClick();

    public WordListPreference(final Context context,
            final DictionaryListInterfaceState dictionaryListInterfaceState, final String clientId,
            final String wordlistId, final int version, final Locale locale,
            final String description, final int status, final int filesize) {
        super(context, null);
        mContext = context;
        mInterfaceState = dictionaryListInterfaceState;
        mClientId = clientId;
        mVersion = version;
        mWordlistId = wordlistId;
        mFilesize = filesize;

        setLayoutResource(R.layout.dictionary_line);

        setTitle(description);
        setStatus(status);
        setKey(wordlistId);
    }

    private void setStatus(final int status) {
        if (status == mStatus) return;
        mStatus = status;
        setSummary(getSummary(status));
    }

    private String getSummary(final int status) {
        switch (status) {
            // If we are deleting the word list, for the user it's like it's already deleted.
            // It should be reinstallable. Exposing to the user the whole complexity of
            // the delayed deletion process between the dictionary pack and Android Keyboard
            // would only be confusing.
            case MetadataDbHelper.STATUS_DELETING:
            case MetadataDbHelper.STATUS_AVAILABLE:
                return mContext.getString(R.string.dictionary_available);
            case MetadataDbHelper.STATUS_DOWNLOADING:
                return mContext.getString(R.string.dictionary_downloading);
            case MetadataDbHelper.STATUS_INSTALLED:
                return mContext.getString(R.string.dictionary_installed);
            case MetadataDbHelper.STATUS_DISABLED:
                return mContext.getString(R.string.dictionary_disabled);
            default:
                return NO_STATUS_MESSAGE;
        }
    }

    // The table below needs to be kept in sync with MetadataDbHelper.STATUS_* since it uses
    // the values as indices.
    private static final int sStatusActionList[][] = {
        // MetadataDbHelper.STATUS_UNKNOWN
        {},
        // MetadataDbHelper.STATUS_AVAILABLE
        { ButtonSwitcher.STATUS_INSTALL, ACTION_ENABLE_DICT },
        // MetadataDbHelper.STATUS_DOWNLOADING
        { ButtonSwitcher.STATUS_CANCEL, ACTION_DISABLE_DICT },
        // MetadataDbHelper.STATUS_INSTALLED
        { ButtonSwitcher.STATUS_DELETE, ACTION_DELETE_DICT },
        // MetadataDbHelper.STATUS_DISABLED
        { ButtonSwitcher.STATUS_DELETE, ACTION_DELETE_DICT },
        // MetadataDbHelper.STATUS_DELETING
        // We show 'install' because the file is supposed to be deleted.
        // The user may reinstall it.
        { ButtonSwitcher.STATUS_INSTALL, ACTION_ENABLE_DICT }
    };

    private int getButtonSwitcherStatus(final int status) {
        if (status >= sStatusActionList.length) {
            Log.e(TAG, "Unknown status " + status);
            return ButtonSwitcher.STATUS_NO_BUTTON;
        }
        return sStatusActionList[status][0];
    }

    private static int getActionIdFromStatusAndMenuEntry(final int status) {
        if (status >= sStatusActionList.length) {
            Log.e(TAG, "Unknown status " + status);
            return ACTION_UNKNOWN;
        }
        return sStatusActionList[status][1];
    }

    private void disableDict() {
        SharedPreferences prefs = CommonPreferences.getCommonPreferences(mContext);
        CommonPreferences.disable(prefs, mWordlistId);
        UpdateHandler.markAsUnused(mContext, mClientId, mWordlistId, mVersion, mStatus);
        if (MetadataDbHelper.STATUS_DOWNLOADING == mStatus) {
            setStatus(MetadataDbHelper.STATUS_AVAILABLE);
        } else if (MetadataDbHelper.STATUS_INSTALLED == mStatus) {
            // Interface-wise, we should no longer be able to come here. However, this is still
            // the right thing to do if we do come here.
            setStatus(MetadataDbHelper.STATUS_DISABLED);
        } else {
            Log.e(TAG, "Unexpected state of the word list for disabling " + mStatus);
        }
    }
    private void enableDict() {
        SharedPreferences prefs = CommonPreferences.getCommonPreferences(mContext);
        CommonPreferences.enable(prefs, mWordlistId);
        // Explicit enabling by the user : allow downloading on metered data connection.
        UpdateHandler.markAsUsed(mContext, mClientId, mWordlistId, mVersion, mStatus, true);
        if (MetadataDbHelper.STATUS_AVAILABLE == mStatus) {
            setStatus(MetadataDbHelper.STATUS_DOWNLOADING);
        } else if (MetadataDbHelper.STATUS_DISABLED == mStatus
                || MetadataDbHelper.STATUS_DELETING == mStatus) {
            // If the status is DELETING, it means Android Keyboard
            // has not deleted the word list yet, so we can safely
            // turn it to 'installed'. The status DISABLED is still supported internally to
            // avoid breaking older installations and all but there should not be a way to
            // disable a word list through the interface any more.
            setStatus(MetadataDbHelper.STATUS_INSTALLED);
        } else {
            Log.e(TAG, "Unexpected state of the word list for enabling " + mStatus);
        }
    }
    private void deleteDict() {
        SharedPreferences prefs = CommonPreferences.getCommonPreferences(mContext);
        CommonPreferences.disable(prefs, mWordlistId);
        setStatus(MetadataDbHelper.STATUS_DELETING);
        UpdateHandler.markAsDeleting(mContext, mClientId, mWordlistId, mVersion, mStatus);
    }

    @Override
    protected void onBindView(final View view) {
        super.onBindView(view);
        ((ViewGroup)view).setLayoutTransition(null);

        final ProgressBar progressBar =
                (ProgressBar)view.findViewById(R.id.dictionary_line_progress_bar);
        final TextView status = (TextView)view.findViewById(android.R.id.summary);
        progressBar.setMax(mFilesize);
        final boolean showProgressBar = (MetadataDbHelper.STATUS_DOWNLOADING == mStatus);
        status.setVisibility(showProgressBar ? View.INVISIBLE : View.VISIBLE);
        progressBar.setVisibility(showProgressBar ? View.VISIBLE : View.INVISIBLE);

        final ButtonSwitcher buttonSwitcher =
                (ButtonSwitcher)view.findViewById(R.id.wordlist_button_switcher);
        if (mInterfaceState.isOpen(mWordlistId)) {
            // The button is open.
            final int previousStatus = mInterfaceState.getStatus(mWordlistId);
            buttonSwitcher.setStatusAndUpdateVisuals(getButtonSwitcherStatus(previousStatus));
            if (previousStatus != mStatus) {
                // We come here if the status has changed since last time. We need to animate
                // the transition.
                buttonSwitcher.setStatusAndUpdateVisuals(getButtonSwitcherStatus(mStatus));
                mInterfaceState.setOpen(mWordlistId, mStatus);
            }
        } else {
            // The button is closed.
            buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON);
        }
        buttonSwitcher.setInternalOnClickListener(mActionButtonClickHandler);
        view.setOnClickListener(mPreferenceClickHandler);
    }

    private class OnWordListPreferenceClick implements View.OnClickListener {
        @Override
        public void onClick(final View v) {
            // Note : v is the preference view
            final ViewParent parent = v.getParent();
            // Just in case something changed in the framework, test for the concrete class
            if (!(parent instanceof ListView)) return;
            final ListView listView = (ListView)parent;
            final int indexToOpen;
            // Close all first, we'll open back any item that needs to be open.
            final boolean wasOpen = mInterfaceState.isOpen(mWordlistId);
            mInterfaceState.closeAll();
            if (wasOpen) {
                // This button being shown. Take note that we don't want to open any button in the
                // loop below.
                indexToOpen = -1;
            } else {
                // This button was not being shown. Open it, and remember the index of this
                // child as the one to open in the following loop.
                mInterfaceState.setOpen(mWordlistId, mStatus);
                indexToOpen = listView.indexOfChild(v);
            }
            final int lastDisplayedIndex =
                    listView.getLastVisiblePosition() - listView.getFirstVisiblePosition();
            // The "lastDisplayedIndex" is actually displayed, hence the <=
            for (int i = 0; i <= lastDisplayedIndex; ++i) {
                final ButtonSwitcher buttonSwitcher = (ButtonSwitcher)listView.getChildAt(i)
                        .findViewById(R.id.wordlist_button_switcher);
                if (i == indexToOpen) {
                    buttonSwitcher.setStatusAndUpdateVisuals(getButtonSwitcherStatus(mStatus));
                } else {
                    buttonSwitcher.setStatusAndUpdateVisuals(ButtonSwitcher.STATUS_NO_BUTTON);
                }
            }
        }
    }

    private class OnActionButtonClick implements View.OnClickListener {
        @Override
        public void onClick(final View v) {
            switch (getActionIdFromStatusAndMenuEntry(mStatus)) {
            case ACTION_ENABLE_DICT:
                enableDict();
                break;
            case ACTION_DISABLE_DICT:
                disableDict();
                break;
            case ACTION_DELETE_DICT:
                deleteDict();
                break;
            default:
                Log.e(TAG, "Unknown menu item pressed");
            }
        }
    }
}
