// Copyright 2010-2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package org.mozc.android.inputmethod.japanese.preference;

import org.mozc.android.inputmethod.japanese.MozcLog;
import org.mozc.android.inputmethod.japanese.MozcUtil;
import org.mozc.android.inputmethod.japanese.preference.ClientSidePreference.KeyboardLayout;
import org.mozc.android.inputmethod.japanese.resources.R;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.PreferenceGroup;
import android.preference.PreferenceManager;
import android.util.DisplayMetrics;

import java.util.HashSet;
import java.util.Set;

/**
 * Utilities for Mozc preferences.
 *
 */
public class PreferenceUtil {

  /** Simple {@code PreferenceManager} wrapper for testing purpose. */
  interface PreferenceManagerInterface {
    public Preference findPreference(CharSequence key);
  }

  /** Simple {@code PreferenceManager} wrapper for testing purpose.
   *  This interface wraps static method so no constructor is required.
   */
  public interface PreferenceManagerStaticInterface {
    public void setDefaultValues(Context context, int id, boolean readAgain);
  }

  static class PreferenceManagerInterfaceImpl implements PreferenceManagerInterface {
    private final PreferenceManager preferenceManager;

    PreferenceManagerInterfaceImpl(PreferenceManager preferenceManager) {
      this.preferenceManager = preferenceManager;
    }

    @Override
    public Preference findPreference(CharSequence key) {
      return preferenceManager.findPreference(key);
    }
  }

  private static Optional<PreferenceManagerStaticInterface> defaultPreferenceManagerStatic =
      Optional.absent();

  public static PreferenceManagerStaticInterface getDefaultPreferenceManagerStatic() {
    // As construction cost of defaultPrereferenceManagerStatic is cheap and it is invariant,
    // no lock mechanism is employed here.
    if (!defaultPreferenceManagerStatic.isPresent()) {
      defaultPreferenceManagerStatic = Optional.<PreferenceManagerStaticInterface>of(
          new PreferenceManagerStaticInterface() {
            @Override
            public void setDefaultValues(Context context, int id, boolean readAgain) {
              PreferenceManager.setDefaultValues(context, id, readAgain);
            }
          });
    }
    return defaultPreferenceManagerStatic.get();
  }

  static class CurrentKeyboardLayoutPreferenceChangeListener implements OnPreferenceChangeListener {
    @Override
    public boolean onPreferenceChange(Preference preference, Object newValue) {
      if (!(newValue instanceof KeyboardLayout)) {
        return false;
      }

      // Write back to with the appropriate preference key.
      SharedPreferences sharedPreferences = preference.getSharedPreferences();
      boolean isLandscapeKeyboardSettingActive = isLandscapeKeyboardSettingActive(
          sharedPreferences, preference.getContext().getResources().getConfiguration().orientation);
      sharedPreferences.edit()
          .putString(
              isLandscapeKeyboardSettingActive
                  ? PREF_LANDSCAPE_KEYBOARD_LAYOUT_KEY
                  : PREF_PORTRAIT_KEYBOARD_LAYOUT_KEY,
              KeyboardLayout.class.cast(newValue).name())
          .commit();
      return true;
    }
  }

  // Keys for Keyboard Layout.
  public static final String PREF_CURRENT_KEYBOARD_LAYOUT_KEY =
      "pref_current_keyboard_layout_key";

  public static final String PREF_SOFTWARE_KEYBOARD_ADVANED_PORTRAIT_KEY =
      "pref_software_keyboard_advanced_portrait_key";
  public static final String PREF_PORTRAIT_KEYBOARD_LAYOUT_KEY =
      "pref_portrait_keyboard_layout_key";
  public static final String PREF_PORTRAIT_INPUT_STYLE_KEY =
      "pref_portrait_input_style_key";
  public static final String PREF_PORTRAIT_QWERTY_LAYOUT_FOR_ALPHABET_KEY =
      "pref_portrait_qwerty_layout_for_alphabet_key";
  public static final String PREF_PORTRAIT_FLICK_SENSITIVITY_KEY =
      "pref_portrait_flick_sensitivity_key";
  public static final String PREF_PORTRAIT_LAYOUT_ADJUSTMENT_KEY =
      "pref_portrait_layout_adjustment_key";
  public static final String PREF_PORTRAIT_KEYBOARD_HEIGHT_RATIO_KEY =
      "pref_portrait_keyboard_height_ratio_key";

  public static final String PREF_SOFTWARE_KEYBOARD_ADVANED_LANDSCAPE_KEY =
      "pref_software_keyboard_advanced_landscape_key";
  public static final String PREF_LANDSCAPE_KEYBOARD_LAYOUT_KEY =
      "pref_landscape_keyboard_layout_key";
  public static final String PREF_LANDSCAPE_INPUT_STYLE_KEY =
      "pref_landscape_input_style_key";
  public static final String PREF_LANDSCAPE_QWERTY_LAYOUT_FOR_ALPHABET_KEY =
      "pref_landscape_qwerty_layout_for_alphabet_key";
  public static final String PREF_LANDSCAPE_FLICK_SENSITIVITY_KEY =
      "pref_landscape_flick_sensitivity_key";
  public static final String PREF_LANDSCAPE_LAYOUT_ADJUSTMENT_KEY =
      "pref_landscape_layout_adjustment_key";
  public static final String PREF_LANDSCAPE_KEYBOARD_HEIGHT_RATIO_KEY =
      "pref_landscape_keyboard_height_ratio_key";

  public static final String PREF_USE_PORTRAIT_KEYBOARD_SETTINGS_FOR_LANDSCAPE_KEY =
      "pref_use_portrait_keyboard_settings_for_landscape_key";

  // Full screen keys.
  public static final String PREF_PORTRAIT_FULLSCREEN_KEY =
      "pref_portrait_fullscreen_key";
  public static final String PREF_LANDSCAPE_FULLSCREEN_KEY =
      "pref_landscape_fullscreen_key";

  // Keys for generic preferences.
  public static final String PREF_HARDWARE_KEYMAP = "pref_hardware_keymap";
  public static final String PREF_VOICE_INPUT_KEY = "pref_voice_input_key";
  public static final String PREF_HAPTIC_FEEDBACK_KEY = "pref_haptic_feedback_key";
  public static final String PREF_HAPTIC_FEEDBACK_DURATION_KEY =
      "pref_haptic_feedback_duration_key";
  public static final String PREF_SOUND_FEEDBACK_KEY = "pref_sound_feedback_key";
  public static final String PREF_SOUND_FEEDBACK_VOLUME_KEY =
      "pref_sound_feedback_volume_key";
  public static final String PREF_POPUP_FEEDBACK_KEY = "pref_popup_feedback_key";
  public static final String PREF_SPACE_CHARACTER_FORM_KEY =
      "pref_space_character_form_key";
  public static final String PREF_KANA_MODIFIER_INSENSITIVE_CONVERSION_KEY =
      "pref_kana_modifier_insensitive_conversion";
  public static final String PREF_TYPING_CORRECTION_KEY =
      "pref_typing_correction";
  public static final String PREF_EMOJI_PROVIDER_TYPE =
      "pref_emoji_provider_type";
  public static final String PREF_DICTIONARY_PERSONALIZATION_KEY =
      "pref_dictionary_personalization_key";
  public static final String PREF_DICTIONARY_USER_DICTIONARY_TOOL_KEY =
      "pref_dictionary_user_dictionary_tool_key";
  public static final String PREF_OTHER_INCOGNITO_MODE_KEY = "pref_other_anonimous_mode_key";
  public static final String PREF_OTHER_USAGE_STATS_KEY = "pref_other_usage_stats_key";
  public static final String PREF_ABOUT_VERSION = "pref_about_version";
  public static final String PREF_LAUNCHER_ICON_VISIBILITY_KEY = "pref_launcher_icon_visibility";
  // Application lifecycle
  public static final String PREF_LAST_LAUNCH_ABI_INDEPENDENT_VERSION_CODE =
      "pref_last_launch_abi_independent_version_code";

  private static final OnPreferenceChangeListener
      CURRENT_KEYBOARD_LAYOUT_PREFERENCE_CHANGE_LISTENER =
          new CurrentKeyboardLayoutPreferenceChangeListener();

  // Disallow instantiation.
  private PreferenceUtil() {
  }

  public static boolean isLandscapeKeyboardSettingActive(
      SharedPreferences sharedPreferences, int deviceOrientation) {
    Preconditions.checkNotNull(sharedPreferences);
    if (sharedPreferences.getBoolean(PREF_USE_PORTRAIT_KEYBOARD_SETTINGS_FOR_LANDSCAPE_KEY, true)) {
      // Always use portrait configuration.
      return false;
    }

    return deviceOrientation == Configuration.ORIENTATION_LANDSCAPE;
  }

  /**
   * Initializes some preferences which need special initialization.
   */
  static void initializeSpecialPreferences(PreferenceManager preferenceManager) {
    if (preferenceManager == null) {
      return;
    }

    initializeSpecialPreferencesInternal(new PreferenceManagerInterfaceImpl(preferenceManager));
  }

  static void initializeSpecialPreferencesInternal(PreferenceManagerInterface preferenceManager) {
    initializeCurrentKeyboardLayoutPreference(
        preferenceManager.findPreference(PREF_CURRENT_KEYBOARD_LAYOUT_KEY));
    initializeUsageStatsPreference(preferenceManager.findPreference(PREF_OTHER_USAGE_STATS_KEY));
    initializeVersionPreference(preferenceManager.findPreference(PREF_ABOUT_VERSION));
    initializeLayoutAdjustmentPreference(preferenceManager);

  }

  private static void initializeCurrentKeyboardLayoutPreference(Preference preference) {
    if (!(preference instanceof KeyboardLayoutPreference)) {
      return;
    }

    // Initialize the value based on the current orientation.
    SharedPreferences sharedPreferences = preference.getSharedPreferences();
    boolean isLandscapeKeyboardSettingActive = isLandscapeKeyboardSettingActive(
        sharedPreferences, preference.getContext().getResources().getConfiguration().orientation);
    KeyboardLayoutPreference.class.cast(preference).setValue(
        getKeyboardLayout(sharedPreferences,
                          isLandscapeKeyboardSettingActive
                              ? PREF_LANDSCAPE_KEYBOARD_LAYOUT_KEY
                              : PREF_PORTRAIT_KEYBOARD_LAYOUT_KEY));
    preference.setOnPreferenceChangeListener(CURRENT_KEYBOARD_LAYOUT_PREFERENCE_CHANGE_LISTENER);
  }

  /**
   * Returns parsed {@link KeyboardLayout} instance, or TWELVE_KEYS if any error is found.
   */
  private static KeyboardLayout getKeyboardLayout(SharedPreferences sharedPreferences, String key) {
    if (sharedPreferences == null || key == null) {
      return KeyboardLayout.TWELVE_KEYS;
    }

    String value = sharedPreferences.getString(key, null);
    if (value == null) {
      return KeyboardLayout.TWELVE_KEYS;
    }

    try {
      return KeyboardLayout.valueOf(value);
    } catch (IllegalArgumentException e) {
      MozcLog.e("Invalid KeyboardLayout: " + value);
    }

    return KeyboardLayout.TWELVE_KEYS;
  }

  private static void initializeUsageStatsPreference(Preference preference) {
    if (preference == null) {
      return;
    }

    Context context = preference.getContext();
    Resources resources = context.getResources();
    preference.setSummary(
        resources.getString(R.string.pref_other_usage_stats_description,
                            resources.getString(R.string.developer_organization)));
    // Disable (always on to send usage stats) for dev-channel build.
    preference.setEnabled(!MozcUtil.isDevChannel(context));
  }

  private static void initializeVersionPreference(Preference preference) {
    if (preference == null) {
      return;
    }
    preference.setSummary(MozcUtil.getVersionName(preference.getContext()));
  }

  static boolean shouldRemoveLayoutAdjustmentPreferences(
      PreferenceManagerInterface preferenceManager) {
    Preference preference = preferenceManager.findPreference(
        PREF_SOFTWARE_KEYBOARD_ADVANED_PORTRAIT_KEY);
    if (preference == null) {
      return false;
    }

    Resources resouces = preference.getContext().getResources();
    int smallestWidth = resouces.getDimensionPixelSize(R.dimen.ime_window_partial_width)
        + resouces.getDimensionPixelSize(R.dimen.side_frame_width);
    DisplayMetrics displayMetrics = resouces.getDisplayMetrics();
    return displayMetrics.widthPixels < smallestWidth
        || displayMetrics.heightPixels < smallestWidth;
  }

  static void removePreference(PreferenceManagerInterface preferenceManager, CharSequence key) {
    CharSequence parentKey;
    if (key == PREF_PORTRAIT_LAYOUT_ADJUSTMENT_KEY) {
      parentKey = PREF_SOFTWARE_KEYBOARD_ADVANED_PORTRAIT_KEY;
    } else if (key == PREF_LANDSCAPE_LAYOUT_ADJUSTMENT_KEY) {
      parentKey = PREF_SOFTWARE_KEYBOARD_ADVANED_LANDSCAPE_KEY;
    } else {
      return;
    }

    Preference preference = preferenceManager.findPreference(key);
    PreferenceGroup parentPreference = PreferenceGroup.class.cast(preferenceManager
        .findPreference(parentKey));
    if (preference == null || parentPreference == null) {
      return;
    }
    parentPreference.removePreference(preference);
  }

  static void initializeLayoutAdjustmentPreference(PreferenceManagerInterface preferenceManager) {
    if (shouldRemoveLayoutAdjustmentPreferences(preferenceManager)) {
      removePreference(preferenceManager, PREF_PORTRAIT_LAYOUT_ADJUSTMENT_KEY);
      removePreference(preferenceManager, PREF_LANDSCAPE_LAYOUT_ADJUSTMENT_KEY);
    }
  }

  /**
   * Gets an enum value in the SharedPreference.
   *
   * @param sharedPreference a {@link SharedPreferences} to be loaded.
   * @param key a key name
   * @param type a class of enum value
   * @param defaultValue default value if the {@link SharedPreferences} doesn't have corresponding
   *        entry.
   * @param conversionRecoveryValue default value if unknown value is stored.
   *        For example, if the value is "ALPHA" and {@code type} doesn't have "ALPHA" entry,
   *        this argument is returned.
   */
  public static <T extends Enum<T>> T getEnum(
      SharedPreferences sharedPreference, String key, Class<T> type,
      T defaultValue, T conversionRecoveryValue) {
    if (sharedPreference == null) {
      return defaultValue;
    }
    String name = sharedPreference.getString(key, null);
    if (name != null) {
      try {
        return Enum.valueOf(type, name);
      } catch (IllegalArgumentException e) {
        return conversionRecoveryValue;
      }
    }
    return defaultValue;
  }

  /**
   * Same as {@link getEnum}.
   *
   * {@code defaultValue} is used as {@code conversionRecoveryValue}
   */
  @SuppressWarnings("javadoc")
  public static <T extends Enum<T>> T getEnum(
      SharedPreferences sharedPreference, String key, Class<T> type, T defaultValue) {
    return getEnum(sharedPreference, key, type, defaultValue, defaultValue);
  }

  public static void setDefaultValues(PreferenceManagerStaticInterface preferenceManager,
                                      Context context, boolean isDebug, boolean useUsageStats) {
    Preconditions.checkNotNull(preferenceManager);
    Preconditions.checkNotNull(context);
    Set<Integer> preferenceResources = new HashSet<Integer>();
    // Collect all the preferences resource ids from possible preference pages,
    // removing duplication.
    for (PreferencePage page : PreferencePage.values()) {
      for (int id : PreferencePage.getResourceIdList(page, isDebug, useUsageStats)) {
        preferenceResources.add(id);
      }
    }
    for (int id : preferenceResources) {
      // 'true' here means the preferences which have not set yet are *always* set here.
      // This doesn't mean *Reset all the preferences*.
      // (if 'false' the process will be done once on the first launch
      //  so even if new preferences are added their default values will not be set here)
      preferenceManager.setDefaultValues(context, id, true);
    }
  }
}
