/*
 * 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.latin;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.util.Log;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodSubtype;

import com.android.inputmethod.keyboard.internal.KeySpecParser;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;

/**
 * When you call the constructor of this class, you may want to change the current system locale by
 * using {@link LocaleUtils.RunInLocale}.
 */
public final class SettingsValues {
    private static final String TAG = SettingsValues.class.getSimpleName();

    private static final int SUGGESTION_VISIBILITY_SHOW_VALUE
            = R.string.prefs_suggestion_visibility_show_value;
    private static final int SUGGESTION_VISIBILITY_SHOW_ONLY_PORTRAIT_VALUE
            = R.string.prefs_suggestion_visibility_show_only_portrait_value;
    private static final int SUGGESTION_VISIBILITY_HIDE_VALUE
            = R.string.prefs_suggestion_visibility_hide_value;

    private static final int[] SUGGESTION_VISIBILITY_VALUE_ARRAY = new int[] {
        SUGGESTION_VISIBILITY_SHOW_VALUE,
        SUGGESTION_VISIBILITY_SHOW_ONLY_PORTRAIT_VALUE,
        SUGGESTION_VISIBILITY_HIDE_VALUE
    };

    // From resources:
    public final int mDelayUpdateOldSuggestions;
    public final String mWeakSpaceStrippers;
    public final String mWeakSpaceSwappers;
    private final String mPhantomSpacePromotingSymbols;
    public final SuggestedWords mSuggestPuncList;
    private final String mSymbolsExcludedFromWordSeparators;
    public final String mWordSeparators;
    public final CharSequence mHintToSaveText;

    // From preferences, in the same order as xml/prefs.xml:
    public final boolean mAutoCap;
    public final boolean mVibrateOn;
    public final boolean mSoundOn;
    public final boolean mKeyPreviewPopupOn;
    private final String mVoiceMode;
    private final String mAutoCorrectionThresholdRawValue;
    public final String mShowSuggestionsSetting;
    @SuppressWarnings("unused") // TODO: Use this
    private final boolean mUsabilityStudyMode;
    public final boolean mIncludesOtherImesInLanguageSwitchList;
    public final boolean mShowsLanguageSwitchKey;
    @SuppressWarnings("unused") // TODO: Use this
    private final String mKeyPreviewPopupDismissDelayRawValue;
    public final boolean mUseContactsDict;
    // Use bigrams to predict the next word when there is no input for it yet
    public final boolean mBigramPredictionEnabled;
    @SuppressWarnings("unused") // TODO: Use this
    private final int mVibrationDurationSettingsRawValue;
    @SuppressWarnings("unused") // TODO: Use this
    private final float mKeypressSoundVolumeRawValue;
    private final InputMethodSubtype[] mAdditionalSubtypes;
    public final boolean mGestureInputEnabled;
    public final boolean mGesturePreviewTrailEnabled;
    public final boolean mGestureFloatingPreviewTextEnabled;

    // From the input box
    private final InputAttributes mInputAttributes;

    // Deduced settings
    public final int mKeypressVibrationDuration;
    public final float mFxVolume;
    public final int mKeyPreviewPopupDismissDelay;
    private final boolean mAutoCorrectEnabled;
    public final float mAutoCorrectionThreshold;
    public final boolean mCorrectionEnabled;
    public final int mSuggestionVisibility;
    private final boolean mVoiceKeyEnabled;
    private final boolean mVoiceKeyOnMain;

    public SettingsValues(final SharedPreferences prefs, final InputAttributes inputAttributes,
            final Context context) {
        final Resources res = context.getResources();

        // Get the resources
        mDelayUpdateOldSuggestions = res.getInteger(R.integer.config_delay_update_old_suggestions);
        mWeakSpaceStrippers = res.getString(R.string.weak_space_stripping_symbols);
        mWeakSpaceSwappers = res.getString(R.string.weak_space_swapping_symbols);
        mPhantomSpacePromotingSymbols = res.getString(R.string.phantom_space_promoting_symbols);
        if (LatinImeLogger.sDBG) {
            final int length = mWeakSpaceStrippers.length();
            for (int i = 0; i < length; i = mWeakSpaceStrippers.offsetByCodePoints(i, 1)) {
                if (isWeakSpaceSwapper(mWeakSpaceStrippers.codePointAt(i))) {
                    throw new RuntimeException("Char code " + mWeakSpaceStrippers.codePointAt(i)
                            + " is both a weak space swapper and stripper.");
                }
            }
        }
        final String[] suggestPuncsSpec = KeySpecParser.parseCsvString(
                res.getString(R.string.suggested_punctuations), null);
        mSuggestPuncList = createSuggestPuncList(suggestPuncsSpec);
        mSymbolsExcludedFromWordSeparators =
                res.getString(R.string.symbols_excluded_from_word_separators);
        mWordSeparators = createWordSeparators(mWeakSpaceStrippers, mWeakSpaceSwappers,
                mSymbolsExcludedFromWordSeparators, res);
        mHintToSaveText = context.getText(R.string.hint_add_to_dictionary);

        // Store the input attributes
        if (null == inputAttributes) {
            mInputAttributes = new InputAttributes(null, false /* isFullscreenMode */);
        } else {
            mInputAttributes = inputAttributes;
        }

        // Get the settings preferences
        mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true);
        mVibrateOn = isVibrateOn(context, prefs, res);
        mSoundOn = prefs.getBoolean(Settings.PREF_SOUND_ON,
                res.getBoolean(R.bool.config_default_sound_enabled));
        mKeyPreviewPopupOn = isKeyPreviewPopupEnabled(prefs, res);
        final String voiceModeMain = res.getString(R.string.voice_mode_main);
        final String voiceModeOff = res.getString(R.string.voice_mode_off);
        mVoiceMode = prefs.getString(Settings.PREF_VOICE_MODE, voiceModeMain);
        mAutoCorrectionThresholdRawValue = prefs.getString(Settings.PREF_AUTO_CORRECTION_THRESHOLD,
                res.getString(R.string.auto_correction_threshold_mode_index_modest));
        mShowSuggestionsSetting = prefs.getString(Settings.PREF_SHOW_SUGGESTIONS_SETTING,
                res.getString(R.string.prefs_suggestion_visibility_default_value));
        mUsabilityStudyMode = getUsabilityStudyMode(prefs);
        mIncludesOtherImesInLanguageSwitchList = prefs.getBoolean(
                Settings.PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST, false);
        mShowsLanguageSwitchKey = showsLanguageSwitchKey(prefs);
        mKeyPreviewPopupDismissDelayRawValue = prefs.getString(
                Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
                Integer.toString(res.getInteger(R.integer.config_key_preview_linger_timeout)));
        mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true);
        mAutoCorrectEnabled = isAutoCorrectEnabled(res, mAutoCorrectionThresholdRawValue);
        mBigramPredictionEnabled = isBigramPredictionEnabled(prefs, res);
        mVibrationDurationSettingsRawValue =
                prefs.getInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, -1);
        mKeypressSoundVolumeRawValue = prefs.getFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, -1.0f);

        // Compute other readable settings
        mKeypressVibrationDuration = getCurrentVibrationDuration(prefs, res);
        mFxVolume = getCurrentKeypressSoundVolume(prefs, res);
        mKeyPreviewPopupDismissDelay = getKeyPreviewPopupDismissDelay(prefs, res);
        mAutoCorrectionThreshold = getAutoCorrectionThreshold(res,
                mAutoCorrectionThresholdRawValue);
        mVoiceKeyEnabled = mVoiceMode != null && !mVoiceMode.equals(voiceModeOff);
        mVoiceKeyOnMain = mVoiceMode != null && mVoiceMode.equals(voiceModeMain);
        mAdditionalSubtypes = AdditionalSubtype.createAdditionalSubtypesArray(
                getPrefAdditionalSubtypes(prefs, res));
        final boolean gestureInputEnabledByBuildConfig = res.getBoolean(
                R.bool.config_gesture_input_enabled_by_build_config);
        mGestureInputEnabled = gestureInputEnabledByBuildConfig
                && prefs.getBoolean(Settings.PREF_GESTURE_INPUT, true);
        mGesturePreviewTrailEnabled = prefs.getBoolean(Settings.PREF_GESTURE_PREVIEW_TRAIL, true);
        mGestureFloatingPreviewTextEnabled = prefs.getBoolean(
                Settings.PREF_GESTURE_FLOATING_PREVIEW_TEXT, true);
        mCorrectionEnabled = mAutoCorrectEnabled && !mInputAttributes.mInputTypeNoAutoCorrect;
        mSuggestionVisibility = createSuggestionVisibility(res);
    }

    // Helper functions to create member values.
    private static SuggestedWords createSuggestPuncList(final String[] puncs) {
        final ArrayList<SuggestedWordInfo> puncList = CollectionUtils.newArrayList();
        if (puncs != null) {
            for (final String puncSpec : puncs) {
                puncList.add(new SuggestedWordInfo(KeySpecParser.getLabel(puncSpec),
                        SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_HARDCODED,
                        Dictionary.TYPE_HARDCODED));
            }
        }
        return new SuggestedWords(puncList,
                false /* typedWordValid */,
                false /* hasAutoCorrectionCandidate */,
                true /* isPunctuationSuggestions */,
                false /* isObsoleteSuggestions */,
                false /* isPrediction */);
    }

    private static String createWordSeparators(final String weakSpaceStrippers,
            final String weakSpaceSwappers, final String symbolsExcludedFromWordSeparators,
            final Resources res) {
        String wordSeparators = weakSpaceStrippers + weakSpaceSwappers
                + res.getString(R.string.phantom_space_promoting_symbols);
        for (int i = symbolsExcludedFromWordSeparators.length() - 1; i >= 0; --i) {
            wordSeparators = wordSeparators.replace(
                    symbolsExcludedFromWordSeparators.substring(i, i + 1), "");
        }
        return wordSeparators;
    }

    private int createSuggestionVisibility(final Resources res) {
        final String suggestionVisiblityStr = mShowSuggestionsSetting;
        for (int visibility : SUGGESTION_VISIBILITY_VALUE_ARRAY) {
            if (suggestionVisiblityStr.equals(res.getString(visibility))) {
                return visibility;
            }
        }
        throw new RuntimeException("Bug: visibility string is not configured correctly");
    }

    private static boolean isVibrateOn(final Context context, final SharedPreferences prefs,
            final Resources res) {
        final boolean hasVibrator = VibratorUtils.getInstance(context).hasVibrator();
        return hasVibrator && prefs.getBoolean(Settings.PREF_VIBRATE_ON,
                res.getBoolean(R.bool.config_default_vibration_enabled));
    }

    public boolean isApplicationSpecifiedCompletionsOn() {
        return mInputAttributes.mApplicationSpecifiedCompletionOn;
    }

    public boolean isSuggestionsRequested(final int displayOrientation) {
        return mInputAttributes.mIsSettingsSuggestionStripOn
                && (mCorrectionEnabled
                        || isSuggestionStripVisibleInOrientation(displayOrientation));
    }

    public boolean isSuggestionStripVisibleInOrientation(final int orientation) {
        return (mSuggestionVisibility == SUGGESTION_VISIBILITY_SHOW_VALUE)
                || (mSuggestionVisibility == SUGGESTION_VISIBILITY_SHOW_ONLY_PORTRAIT_VALUE
                        && orientation == Configuration.ORIENTATION_PORTRAIT);
    }

    public boolean isWordSeparator(final int code) {
        return mWordSeparators.contains(String.valueOf((char)code));
    }

    public boolean isSymbolExcludedFromWordSeparators(final int code) {
        return mSymbolsExcludedFromWordSeparators.contains(String.valueOf((char)code));
    }

    // TODO: use "Phantom" instead of "Weak" in this method name
    public boolean isWeakSpaceStripper(final int code) {
        // TODO: this does not work if the code does not fit in a char
        return mWeakSpaceStrippers.contains(String.valueOf((char)code));
    }

    // TODO: use "Phantom" instead of "Weak" in this method name
    public boolean isWeakSpaceSwapper(final int code) {
        // TODO: this does not work if the code does not fit in a char
        return mWeakSpaceSwappers.contains(String.valueOf((char)code));
    }

    public boolean isPhantomSpacePromotingSymbol(final int code) {
        // TODO: this does not work if the code does not fit in a char
        return mPhantomSpacePromotingSymbols.contains(String.valueOf((char)code));
    }

    public boolean shouldInsertSpacesAutomatically() {
        return mInputAttributes.shouldInsertSpacesAutomatically();
    }

    private static boolean isAutoCorrectEnabled(final Resources res,
            final String currentAutoCorrectionSetting) {
        final String autoCorrectionOff = res.getString(
                R.string.auto_correction_threshold_mode_index_off);
        return !currentAutoCorrectionSetting.equals(autoCorrectionOff);
    }

    // Public to access from KeyboardSwitcher. Should it have access to some
    // process-global instance instead?
    public static boolean isKeyPreviewPopupEnabled(final SharedPreferences prefs,
            final Resources res) {
        final boolean showPopupOption = res.getBoolean(
                R.bool.config_enable_show_popup_on_keypress_option);
        if (!showPopupOption) return res.getBoolean(R.bool.config_default_popup_preview);
        return prefs.getBoolean(Settings.PREF_POPUP_ON,
                res.getBoolean(R.bool.config_default_popup_preview));
    }

    // Likewise
    public static int getKeyPreviewPopupDismissDelay(final SharedPreferences prefs,
            final Resources res) {
        // TODO: use mKeyPreviewPopupDismissDelayRawValue instead of reading it again here.
        return Integer.parseInt(prefs.getString(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
                Integer.toString(res.getInteger(
                        R.integer.config_key_preview_linger_timeout))));
    }

    private static boolean isBigramPredictionEnabled(final SharedPreferences prefs,
            final Resources res) {
        return prefs.getBoolean(Settings.PREF_BIGRAM_PREDICTIONS, res.getBoolean(
                R.bool.config_default_next_word_prediction));
    }

    private static float getAutoCorrectionThreshold(final Resources res,
            final String currentAutoCorrectionSetting) {
        final String[] autoCorrectionThresholdValues = res.getStringArray(
                R.array.auto_correction_threshold_values);
        // When autoCorrectionThreshold is greater than 1.0, it's like auto correction is off.
        float autoCorrectionThreshold = Float.MAX_VALUE;
        try {
            final int arrayIndex = Integer.valueOf(currentAutoCorrectionSetting);
            if (arrayIndex >= 0 && arrayIndex < autoCorrectionThresholdValues.length) {
                autoCorrectionThreshold = Float.parseFloat(
                        autoCorrectionThresholdValues[arrayIndex]);
            }
        } catch (NumberFormatException e) {
            // Whenever the threshold settings are correct, never come here.
            autoCorrectionThreshold = Float.MAX_VALUE;
            Log.w(TAG, "Cannot load auto correction threshold setting."
                    + " currentAutoCorrectionSetting: " + currentAutoCorrectionSetting
                    + ", autoCorrectionThresholdValues: "
                    + Arrays.toString(autoCorrectionThresholdValues));
        }
        return autoCorrectionThreshold;
    }

    public boolean isVoiceKeyEnabled(final EditorInfo editorInfo) {
        final boolean shortcutImeEnabled = SubtypeSwitcher.getInstance().isShortcutImeEnabled();
        final int inputType = (editorInfo != null) ? editorInfo.inputType : 0;
        return shortcutImeEnabled && mVoiceKeyEnabled
                && !InputTypeUtils.isPasswordInputType(inputType);
    }

    public boolean isVoiceKeyOnMain() {
        return mVoiceKeyOnMain;
    }

    // This preference key is deprecated. Use {@link #PREF_SHOW_LANGUAGE_SWITCH_KEY} instead.
    // This is being used only for the backward compatibility.
    private static final String PREF_SUPPRESS_LANGUAGE_SWITCH_KEY =
            "pref_suppress_language_switch_key";

    public static boolean showsLanguageSwitchKey(final SharedPreferences prefs) {
        if (prefs.contains(PREF_SUPPRESS_LANGUAGE_SWITCH_KEY)) {
            final boolean suppressLanguageSwitchKey = prefs.getBoolean(
                    PREF_SUPPRESS_LANGUAGE_SWITCH_KEY, false);
            final SharedPreferences.Editor editor = prefs.edit();
            editor.remove(PREF_SUPPRESS_LANGUAGE_SWITCH_KEY);
            editor.putBoolean(Settings.PREF_SHOW_LANGUAGE_SWITCH_KEY, !suppressLanguageSwitchKey);
            editor.apply();
        }
        return prefs.getBoolean(Settings.PREF_SHOW_LANGUAGE_SWITCH_KEY, true);
    }

    public boolean isLanguageSwitchKeyEnabled(final Context context) {
        if (!mShowsLanguageSwitchKey) {
            return false;
        }
        if (mIncludesOtherImesInLanguageSwitchList) {
            return ImfUtils.hasMultipleEnabledIMEsOrSubtypes(
                    context, /* include aux subtypes */false);
        } else {
            return ImfUtils.hasMultipleEnabledSubtypesInThisIme(
                    context, /* include aux subtypes */false);
        }
    }

    public static boolean isFullscreenModeAllowed(final Resources res) {
        return res.getBoolean(R.bool.config_use_fullscreen_mode);
    }

    public InputMethodSubtype[] getAdditionalSubtypes() {
        return mAdditionalSubtypes;
    }

    public static String getPrefAdditionalSubtypes(final SharedPreferences prefs,
            final Resources res) {
        final String predefinedPrefSubtypes = AdditionalSubtype.createPrefSubtypes(
                res.getStringArray(R.array.predefined_subtypes));
        return prefs.getString(Settings.PREF_CUSTOM_INPUT_STYLES, predefinedPrefSubtypes);
    }

    // Accessed from the settings interface, hence public
    public static float getCurrentKeypressSoundVolume(final SharedPreferences prefs,
            final Resources res) {
        // TODO: use mVibrationDurationSettingsRawValue instead of reading it again here
        final float volume = prefs.getFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, -1.0f);
        if (volume >= 0) {
            return volume;
        }

        return Float.parseFloat(ResourceUtils.getDeviceOverrideValue(
                res, R.array.keypress_volumes, "-1.0f"));
    }

    // Likewise
    public static int getCurrentVibrationDuration(final SharedPreferences prefs,
            final Resources res) {
        // TODO: use mKeypressVibrationDuration instead of reading it again here
        final int ms = prefs.getInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, -1);
        if (ms >= 0) {
            return ms;
        }

        return Integer.parseInt(ResourceUtils.getDeviceOverrideValue(
                res, R.array.keypress_vibration_durations, "-1"));
    }

    // Likewise
    public static boolean getUsabilityStudyMode(final SharedPreferences prefs) {
        // TODO: use mUsabilityStudyMode instead of reading it again here
        return prefs.getBoolean(DebugSettings.PREF_USABILITY_STUDY_MODE, true);
    }

    public static long getLastUserHistoryWriteTime(final SharedPreferences prefs,
            final String locale) {
        final String str = prefs.getString(Settings.PREF_LAST_USER_DICTIONARY_WRITE_TIME, "");
        final HashMap<String, Long> map = LocaleUtils.localeAndTimeStrToHashMap(str);
        if (map.containsKey(locale)) {
            return map.get(locale);
        }
        return 0;
    }

    public static void setLastUserHistoryWriteTime(final SharedPreferences prefs,
            final String locale) {
        final String oldStr = prefs.getString(Settings.PREF_LAST_USER_DICTIONARY_WRITE_TIME, "");
        final HashMap<String, Long> map = LocaleUtils.localeAndTimeStrToHashMap(oldStr);
        map.put(locale, System.currentTimeMillis());
        final String newStr = LocaleUtils.localeAndTimeHashMapToStr(map);
        prefs.edit().putString(Settings.PREF_LAST_USER_DICTIONARY_WRITE_TIME, newStr).apply();
    }

    public boolean isSameInputType(final EditorInfo editorInfo) {
        return mInputAttributes.isSameInputType(editorInfo);
    }

    // For debug.
    public String getInputAttributesDebugString() {
        return mInputAttributes.toString();
    }
}
