/*
 * Copyright (C) 2010 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.settings.inputmethod;

import com.android.settings.R;
import com.android.settings.SettingsPreferenceFragment;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceScreen;
import android.text.TextUtils;
import android.util.Log;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

public class InputMethodAndSubtypeEnabler extends SettingsPreferenceFragment {
    private static final String TAG =InputMethodAndSubtypeEnabler.class.getSimpleName();
    private AlertDialog mDialog = null;
    private boolean mHaveHardKeyboard;
    final private HashMap<String, List<Preference>> mInputMethodAndSubtypePrefsMap =
            new HashMap<String, List<Preference>>();
    final private HashMap<String, CheckBoxPreference> mSubtypeAutoSelectionCBMap =
            new HashMap<String, CheckBoxPreference>();
    private InputMethodManager mImm;
    private List<InputMethodInfo> mInputMethodProperties;
    private String mInputMethodId;
    private String mTitle;
    private String mSystemLocale = "";

    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        mImm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        final Configuration config = getResources().getConfiguration();
        mHaveHardKeyboard = (config.keyboard == Configuration.KEYBOARD_QWERTY);

        final Bundle arguments = getArguments();
        // Input method id should be available from an Intent when this preference is launched as a
        // single Activity (see InputMethodAndSubtypeEnablerActivity). It should be available
        // from a preference argument when the preference is launched as a part of the other
        // Activity (like a right pane of 2-pane Settings app)
        mInputMethodId = getActivity().getIntent().getStringExtra(
                android.provider.Settings.EXTRA_INPUT_METHOD_ID);
        if (mInputMethodId == null && (arguments != null)) {
            final String inputMethodId =
                    arguments.getString(android.provider.Settings.EXTRA_INPUT_METHOD_ID);
            if (inputMethodId != null) {
                mInputMethodId = inputMethodId;
            }
        }
        mTitle = getActivity().getIntent().getStringExtra(Intent.EXTRA_TITLE);
        if (mTitle == null && (arguments != null)) {
            final String title = arguments.getString(Intent.EXTRA_TITLE);
            if (title != null) {
                mTitle = title;
            }
        }

        mSystemLocale = config.locale.toString();
        onCreateIMM();
        setPreferenceScreen(createPreferenceHierarchy());
    }

    @Override
    public void onActivityCreated(Bundle icicle) {
        super.onActivityCreated(icicle);
        if (!TextUtils.isEmpty(mTitle)) {
            getActivity().setTitle(mTitle);
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        InputMethodAndSubtypeUtil.loadInputMethodSubtypeList(
                this, getContentResolver(), mInputMethodProperties, mInputMethodAndSubtypePrefsMap);
        updateAutoSelectionCB();
    }

    @Override
    public void onPause() {
        super.onPause();
        // Clear all subtypes of all IMEs to make sure
        clearImplicitlyEnabledSubtypes(null);
        InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(this, getContentResolver(),
                mInputMethodProperties, mHaveHardKeyboard);
    }

    @Override
    public boolean onPreferenceTreeClick(
            PreferenceScreen preferenceScreen, Preference preference) {

        if (preference instanceof CheckBoxPreference) {
            final CheckBoxPreference chkPref = (CheckBoxPreference) preference;

            for (String imiId: mSubtypeAutoSelectionCBMap.keySet()) {
                if (mSubtypeAutoSelectionCBMap.get(imiId) == chkPref) {
                    // We look for the first preference item in subtype enabler.
                    // The first item is used for turning on/off subtype auto selection.
                    // We are in the subtype enabler and trying selecting subtypes automatically.
                    setSubtypeAutoSelectionEnabled(imiId, chkPref.isChecked());
                    return super.onPreferenceTreeClick(preferenceScreen, preference);
                }
            }

            final String id = chkPref.getKey();
            if (chkPref.isChecked()) {
                InputMethodInfo selImi = null;
                final int N = mInputMethodProperties.size();
                for (int i = 0; i < N; i++) {
                    InputMethodInfo imi = mInputMethodProperties.get(i);
                    if (id.equals(imi.getId())) {
                        selImi = imi;
                        if (InputMethodAndSubtypeUtil.isSystemIme(imi)) {
                            InputMethodAndSubtypeUtil.setSubtypesPreferenceEnabled(
                                    this, mInputMethodProperties, id, true);
                            // This is a built-in IME, so no need to warn.
                            return super.onPreferenceTreeClick(preferenceScreen, preference);
                        }
                        break;
                    }
                }
                if (selImi == null) {
                    return super.onPreferenceTreeClick(preferenceScreen, preference);
                }
                chkPref.setChecked(false);
                if (mDialog == null) {
                    mDialog = (new AlertDialog.Builder(getActivity()))
                            .setTitle(android.R.string.dialog_alert_title)
                            .setIcon(android.R.drawable.ic_dialog_alert)
                            .setCancelable(true)
                            .setPositiveButton(android.R.string.ok,
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                            chkPref.setChecked(true);
                                            InputMethodAndSubtypeUtil.setSubtypesPreferenceEnabled(
                                                    InputMethodAndSubtypeEnabler.this,
                                                    mInputMethodProperties, id, true);
                                        }

                            })
                            .setNegativeButton(android.R.string.cancel,
                                    new DialogInterface.OnClickListener() {
                                        @Override
                                        public void onClick(DialogInterface dialog, int which) {
                                        }

                            })
                            .create();
                } else {
                    if (mDialog.isShowing()) {
                        mDialog.dismiss();
                    }
                }
                mDialog.setMessage(getResources().getString(
                        R.string.ime_security_warning,
                        selImi.getServiceInfo().applicationInfo.loadLabel(getPackageManager())));
                mDialog.show();
            } else {
                InputMethodAndSubtypeUtil.setSubtypesPreferenceEnabled(
                        this, mInputMethodProperties, id, false);
                updateAutoSelectionCB();
            }
        }
        return super.onPreferenceTreeClick(preferenceScreen, preference);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mDialog != null) {
            mDialog.dismiss();
            mDialog = null;
        }
    }

    private void onCreateIMM() {
        InputMethodManager imm = (InputMethodManager) getSystemService(
                Context.INPUT_METHOD_SERVICE);

        // TODO: Change mInputMethodProperties to Map
        mInputMethodProperties = imm.getInputMethodList();
    }

    private PreferenceScreen createPreferenceHierarchy() {
        // Root
        final PreferenceScreen root = getPreferenceManager().createPreferenceScreen(getActivity());
        final Context context = getActivity();

        int N = (mInputMethodProperties == null ? 0 : mInputMethodProperties.size());

        for (int i = 0; i < N; ++i) {
            final InputMethodInfo imi = mInputMethodProperties.get(i);
            final int subtypeCount = imi.getSubtypeCount();
            if (subtypeCount <= 1) continue;
            final String imiId = imi.getId();
            // Add this subtype to the list when no IME is specified or when the IME of this
            // subtype is the specified IME.
            if (!TextUtils.isEmpty(mInputMethodId) && !mInputMethodId.equals(imiId)) {
                continue;
            }
            final PreferenceCategory keyboardSettingsCategory = new PreferenceCategory(context);
            root.addPreference(keyboardSettingsCategory);
            final PackageManager pm = getPackageManager();
            final CharSequence label = imi.loadLabel(pm);

            keyboardSettingsCategory.setTitle(label);
            keyboardSettingsCategory.setKey(imiId);
            // TODO: Use toggle Preference if images are ready.
            final CheckBoxPreference autoCB = new CheckBoxPreference(context);
            mSubtypeAutoSelectionCBMap.put(imiId, autoCB);
            keyboardSettingsCategory.addPreference(autoCB);

            final PreferenceCategory activeInputMethodsCategory = new PreferenceCategory(context);
            activeInputMethodsCategory.setTitle(R.string.active_input_method_subtypes);
            root.addPreference(activeInputMethodsCategory);

            boolean isAutoSubtype = false;
            CharSequence autoSubtypeLabel = null;
            final ArrayList<Preference> subtypePreferences = new ArrayList<Preference>();
            if (subtypeCount > 0) {
                for (int j = 0; j < subtypeCount; ++j) {
                    final InputMethodSubtype subtype = imi.getSubtypeAt(j);
                    final CharSequence subtypeLabel = subtype.getDisplayName(context,
                            imi.getPackageName(), imi.getServiceInfo().applicationInfo);
                    if (subtype.overridesImplicitlyEnabledSubtype()) {
                        if (!isAutoSubtype) {
                            isAutoSubtype = true;
                            autoSubtypeLabel = subtypeLabel;
                        }
                    } else {
                        final CheckBoxPreference chkbxPref = new SubtypeCheckBoxPreference(
                                context, subtype.getLocale(), mSystemLocale);
                        chkbxPref.setKey(imiId + subtype.hashCode());
                        chkbxPref.setTitle(subtypeLabel);
                        subtypePreferences.add(chkbxPref);
                    }
                }
                Collections.sort(subtypePreferences);
                for (int j = 0; j < subtypePreferences.size(); ++j) {
                    activeInputMethodsCategory.addPreference(subtypePreferences.get(j));
                }
                mInputMethodAndSubtypePrefsMap.put(imiId, subtypePreferences);
            }
            if (isAutoSubtype) {
                if (TextUtils.isEmpty(autoSubtypeLabel)) {
                    Log.w(TAG, "Title for auto subtype is empty.");
                    autoCB.setTitle("---");
                } else {
                    autoCB.setTitle(autoSubtypeLabel);
                }
            } else {
                autoCB.setTitle(R.string.use_system_language_to_select_input_method_subtypes);
            }
        }
        return root;
    }

    private boolean isNoSubtypesExplicitlySelected(String imiId) {
        boolean allSubtypesOff = true;
        final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
        for (Preference subtypePref: subtypePrefs) {
            if (subtypePref instanceof CheckBoxPreference
                    && ((CheckBoxPreference)subtypePref).isChecked()) {
                allSubtypesOff = false;
                break;
            }
        }
        return allSubtypesOff;
    }

    private void setSubtypeAutoSelectionEnabled(String imiId, boolean autoSelectionEnabled) {
        CheckBoxPreference autoSelectionCB = mSubtypeAutoSelectionCBMap.get(imiId);
        if (autoSelectionCB == null) return;
        autoSelectionCB.setChecked(autoSelectionEnabled);
        final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
        for (Preference subtypePref: subtypePrefs) {
            if (subtypePref instanceof CheckBoxPreference) {
                // When autoSelectionEnabled is true, all subtype prefs need to be disabled with
                // implicitly checked subtypes. In case of false, all subtype prefs need to be
                // enabled.
                subtypePref.setEnabled(!autoSelectionEnabled);
                if (autoSelectionEnabled) {
                    ((CheckBoxPreference)subtypePref).setChecked(false);
                }
            }
        }
        if (autoSelectionEnabled) {
            InputMethodAndSubtypeUtil.saveInputMethodSubtypeList(this, getContentResolver(),
                    mInputMethodProperties, mHaveHardKeyboard);
            setCheckedImplicitlyEnabledSubtypes(imiId);
        }
    }

    private void setCheckedImplicitlyEnabledSubtypes(String targetImiId) {
        updateImplicitlyEnabledSubtypes(targetImiId, true);
    }

    private void clearImplicitlyEnabledSubtypes(String targetImiId) {
        updateImplicitlyEnabledSubtypes(targetImiId, false);
    }

    private void updateImplicitlyEnabledSubtypes(String targetImiId, boolean check) {
        // When targetImiId is null, apply to all subtypes of all IMEs
        for (InputMethodInfo imi: mInputMethodProperties) {
            String imiId = imi.getId();
            if (targetImiId != null && !targetImiId.equals(imiId)) continue;
            final CheckBoxPreference autoCB = mSubtypeAutoSelectionCBMap.get(imiId);
            // No need to update implicitly enabled subtypes when the user has unchecked the
            // "subtype auto selection".
            if (autoCB == null || !autoCB.isChecked()) continue;
            final List<Preference> subtypePrefs = mInputMethodAndSubtypePrefsMap.get(imiId);
            final List<InputMethodSubtype> implicitlyEnabledSubtypes =
                    mImm.getEnabledInputMethodSubtypeList(imi, true);
            if (subtypePrefs == null || implicitlyEnabledSubtypes == null) continue;
            for (Preference subtypePref: subtypePrefs) {
                if (subtypePref instanceof CheckBoxPreference) {
                    CheckBoxPreference cb = (CheckBoxPreference)subtypePref;
                    cb.setChecked(false);
                    if (check) {
                        for (InputMethodSubtype subtype: implicitlyEnabledSubtypes) {
                            String implicitlyEnabledSubtypePrefKey = imiId + subtype.hashCode();
                            if (cb.getKey().equals(implicitlyEnabledSubtypePrefKey)) {
                                cb.setChecked(true);
                                break;
                            }
                        }
                    }
                }
            }
        }
    }

    private void updateAutoSelectionCB() {
        for (String imiId: mInputMethodAndSubtypePrefsMap.keySet()) {
            setSubtypeAutoSelectionEnabled(imiId, isNoSubtypesExplicitlySelected(imiId));
        }
        setCheckedImplicitlyEnabledSubtypes(null);
    }

    private static class SubtypeCheckBoxPreference extends CheckBoxPreference {
        private final boolean mIsSystemLocale;
        private final boolean mIsSystemLanguage;

        public SubtypeCheckBoxPreference(
                Context context, String subtypeLocale, String systemLocale) {
            super(context);
            if (TextUtils.isEmpty(subtypeLocale)) {
                mIsSystemLocale = false;
                mIsSystemLanguage = false;
            } else {
                mIsSystemLocale = subtypeLocale.equals(systemLocale);
                mIsSystemLanguage = mIsSystemLocale
                        || subtypeLocale.startsWith(systemLocale.substring(0, 2));
            }
        }

        @Override
        public int compareTo(Preference p) {
            if (p instanceof SubtypeCheckBoxPreference) {
                final SubtypeCheckBoxPreference pref = ((SubtypeCheckBoxPreference)p);
                final CharSequence t0 = getTitle();
                final CharSequence t1 = pref.getTitle();
                if (TextUtils.equals(t0, t1)) {
                    return 0;
                }
                if (mIsSystemLocale) {
                    return -1;
                }
                if (pref.mIsSystemLocale) {
                    return 1;
                }
                if (mIsSystemLanguage) {
                    return -1;
                }
                if (pref.mIsSystemLanguage) {
                    return 1;
                }
                if (TextUtils.isEmpty(t0)) {
                    return 1;
                }
                if (TextUtils.isEmpty(t1)) {
                    return -1;
                }
                return t0.toString().compareTo(t1.toString());
            } else {
                Log.w(TAG, "Illegal preference type.");
                return -1;
            }
        }
    }
}
