// Copyright 2010-2014, 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;

import org.mozc.android.inputmethod.japanese.keyboard.Keyboard.KeyboardSpecification;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.Request;
import org.mozc.android.inputmethod.japanese.util.ResourcesWrapper;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.protobuf.ByteString;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Dialog;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.StrictMode;
import android.os.SystemClock;
import android.provider.Settings;
import android.telephony.TelephonyManager;
import android.text.InputType;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;

import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.zip.ZipFile;

/**
 * Utility class
 *
 */
public final class MozcUtil {

  private static class OutOfMemoryRetryingResources extends ResourcesWrapper {

    private final int retryCount;
    public OutOfMemoryRetryingResources(Resources base, int retryCount) {
      super(Preconditions.checkNotNull(base));
      this.retryCount = retryCount;
    }

    @Override
    public Drawable getDrawable(int id) throws NotFoundException {
      Resources base = getBase();
      for (int i = 0; i < retryCount; ++i) {
        try {
          return base.getDrawable(id);
        } catch (OutOfMemoryError e) {
          // Retry with running gc.
          System.gc();
        }
      }

      // Final trial.
      return base.getDrawable(id);
    }

    @TargetApi(15)
    @Override
    public Drawable getDrawableForDensity(int id, int density) throws NotFoundException {
      Resources base = getBase();
      for (int i = 0; i < retryCount; ++i) {
        try {
          return base.getDrawableForDensity(id, density);
        } catch (OutOfMemoryError e) {
          // Retry with running gc.
          System.gc();
        }
      }

      // Final trial.
      return base.getDrawableForDensity(id, density);
    }
  }

  /**
   * Simple interface to use mock of TelephonyManager for testing purpose.
   */
  public interface TelephonyManagerInterface {
    public String getNetworkOperator();
  }

  /**
   * Real implementation of TelephonyManagerInterface.
   */
  private static class TelephonyManagerImpl implements TelephonyManagerInterface {

    private final TelephonyManager telephonyManager;
    TelephonyManagerImpl(TelephonyManager telephonyManager) {
      this.telephonyManager = Preconditions.checkNotNull(telephonyManager);
    }

    @Override
    public String getNetworkOperator() {
      return telephonyManager.getNetworkOperator();
    }
  }

  static class InputMethodPickerShowingCallback implements Handler.Callback {

    @Override
    public boolean handleMessage(Message msg) {
      Context context = Context.class.cast(Preconditions.checkNotNull(msg).obj);
      InputMethodManager.class.cast(
          context.getSystemService(Context.INPUT_METHOD_SERVICE)).showInputMethodPicker();
      return false;
    }
  }

  // Cursor position values.
  // According to the restriction of IMF,
  // the cursor position must be at the head or tail of precomposition.
  public static final int CURSOR_POSITION_HEAD = 0;
  public static final int CURSOR_POSITION_TAIL = 1;

  // Tag for logging.
  // This constant value affects only the logs printed by Java layer.
  // If you want to change the tag name, see also kProductPrefix in base/const.h.
  public static final String LOGTAG = "Mozc";

  private static final int OUT_OF_MEMORY_RETRY_COUNT = 5;

  private static Optional<Boolean> isDebug = Optional.<Boolean>absent();
  private static Optional<Boolean> isDevChannel = Optional.<Boolean>absent();
  private static Optional<Boolean> isMozcEnabled = Optional.<Boolean>absent();
  private static Optional<Boolean> isMozcDefaultIme = Optional.<Boolean>absent();
  private static Optional<Boolean> isSystemApplication = Optional.<Boolean>absent();
  private static Optional<Boolean> isTouchUI = Optional.<Boolean>absent();
  private static Optional<Boolean> isUpdatedSystemApplication = Optional.<Boolean>absent();
  private static Optional<Integer> versionCode = Optional.<Integer>absent();
  private static Optional<Long> uptimeMillis = Optional.<Long>absent();

  private static final int SHOW_INPUT_METHOD_PICKER_WHAT = 0;
  private static Optional<Handler> showInputMethodPickerHandler = Optional.absent();

  public static final String IME_OPTION_NO_MICROPHONE_COMPAT = "nm";
  public static final String IME_OPTION_NO_MICROPHONE =
      "com.google.android.inputmethod.latin.noMicrophoneKey";

  private static final String USER_DICTIONARY_EXPORT_DIR = "user_dictionary_export";

  /**
   * Lazy creation of a handler.
   *
   * Creating a handler must be done in threads which has a Looper.
   * This lazy creation enables worker threads (which don't have a Looper) to access this class.
   */
  private static Handler getShowInputMethodPickerHandler() {
    if (!showInputMethodPickerHandler.isPresent()) {
      showInputMethodPickerHandler =
        Optional.of(new Handler(new InputMethodPickerShowingCallback()));
    }
    return showInputMethodPickerHandler.get();
  }

  // Disallow instantiation.
  private MozcUtil() {
  }

  private static final boolean checkApplicationFlag(Context context, int flag) {
    Preconditions.checkNotNull(context);
    PackageManager manager = context.getPackageManager();
    try {
      ApplicationInfo appInfo =
          manager.getApplicationInfo(context.getPackageName(), 0);
      return (appInfo.flags & flag) != 0;
    } catch (NameNotFoundException e) {
      MozcLog.w("PackageManager#getApplicationInfo cannot find this application.");
      return false;
    }
  }

  public static final boolean isDebug(Context context) {
    Preconditions.checkNotNull(context);
    if (isDebug.isPresent()) {
      return isDebug.get();
    }
    return checkApplicationFlag(context, ApplicationInfo.FLAG_DEBUGGABLE);
  }

  /**
   * For testing purpose.
   *
   * @param isDebug Optional.absent() if default behavior is preferable
   */
  public static final void setDebug(Optional<Boolean> isDebug) {
    MozcUtil.isDebug = Preconditions.checkNotNull(isDebug);
  }

  public static final boolean isDevChannel(Context context) {
    Preconditions.checkNotNull(context);
    if (isDevChannel.isPresent()) {
      return isDevChannel.get();
    }
    return isDevChannelVersionName(getVersionName(context));
  }

  public static final boolean isSystemApplication(Context context) {
    Preconditions.checkNotNull(context);
    if (isSystemApplication.isPresent()) {
      return isSystemApplication.get();
    }
    return checkApplicationFlag(context, ApplicationInfo.FLAG_SYSTEM);
  }

  /**
   * For testing purpose.
   * @param isSystemApplication Optional.absent() if default behavior is preferable
   */
  public static final void setSystemApplication(Optional<Boolean> isSystemApplication) {
    MozcUtil.isSystemApplication = Preconditions.checkNotNull(isSystemApplication);
  }

  public static final boolean isUpdatedSystemApplication(Context context) {
    Preconditions.checkNotNull(context);
    if (isUpdatedSystemApplication.isPresent()) {
      return isUpdatedSystemApplication.get();
    }
    return checkApplicationFlag(context, ApplicationInfo.FLAG_UPDATED_SYSTEM_APP);
  }

  /**
   * For testing purpose.
   * @param isUpdatedSystemApplication Optional.absent() if default behavior is preferable
   */
  public static final void setUpdatedSystemApplication(
      Optional<Boolean> isUpdatedSystemApplication) {
    MozcUtil.isUpdatedSystemApplication = Preconditions.checkNotNull(isUpdatedSystemApplication);
  }

  /**
   * Gets version name.
   *
   * @return version name string or empty. Non-null is guaranteed.
   */
  public static String getVersionName(Context context) {
    Preconditions.checkNotNull(context);

    PackageManager manager = context.getPackageManager();
    try {
      PackageInfo packageInfo = manager.getPackageInfo(context.getPackageName(), 0);
      return Strings.nullToEmpty(packageInfo.versionName);
    } catch (NameNotFoundException e) {
      MozcLog.e("Package info error", e);
    }
    return "";
  }

  /**
   * For testing purpose.
   */
  public static void setVersionCode(Optional<Integer> versionCode) {
    MozcUtil.versionCode = Preconditions.checkNotNull(versionCode);
  }

  /**
   * Gets raw (ABI dependent) version code.
   *
   * @return version code. Note that this version code contains ABI specific mask.
   */
  public static int getVersionCode(Context context) {
    Preconditions.checkNotNull(context);

    if (MozcUtil.versionCode.isPresent()) {
      return MozcUtil.versionCode.get();
    }

    PackageManager manager = context.getPackageManager();
    try {
      PackageInfo packageInfo = manager.getPackageInfo(context.getPackageName(), 0);
      return packageInfo.versionCode;
    } catch (NameNotFoundException e) {
      MozcLog.e("Package info error", e);
    }
    return 0;
  }

  /**
   * Gets ABI independent version code.
   *
   * ABI independent version code is equivalent to "Build number" of Mozc project.
   *
   * <p>Must be consistent with mozc_version.py
   */
  public static int getAbiIndependentVersionCode(Context context) {
    // Version code format:
    // 00000BBBBB or
    // 0005BBBBBA
    // A: ABI (0: Fat, 6: x86_64, 5:arm64, 4:mips64, 3: x86, 2: armeabi-v7a, 1:mips)
    // B: ANDROID_VERSION_CODE
    Preconditions.checkNotNull(context);
    int rawVersionCode = getVersionCode(context);
    String versionCode = Integer.toString(getVersionCode(context));
    if (versionCode.length() == 7 && versionCode.charAt(0) == '5') {
      return Integer.valueOf(versionCode.substring(1, versionCode.length() - 1));
    }
    return rawVersionCode;
  }

  /**
   * For testing purpose.
   *
   * @param isDevChannel Optional.absent() if default behavior is preferable
   */
  public static final void setDevChannel(Optional<Boolean> isDevChannel) {
    MozcUtil.isDevChannel = Preconditions.checkNotNull(isDevChannel);
  }

  /**
   * Returns true if {@code versionName} indicates dev channel.
   *
   * This method sees only the characters between the last period and hyphen.
   * If the characters is greater than or equal to (int)100,
   * this method returns true.
   */
  @VisibleForTesting static boolean isDevChannelVersionName(String versionName) {
    Preconditions.checkNotNull(versionName);

    int lastDot = versionName.lastIndexOf('.');
    if (lastDot < 0) {
      return false;
    }
    int lastHyphen = versionName.lastIndexOf('-');
    if (lastHyphen < 0) {
      lastHyphen = versionName.length();
    }
    try {
      return Integer.parseInt(versionName.substring(lastDot + 1, lastHyphen)) >= 100;
    } catch (NumberFormatException e) {
      return false;
    }
  }

  /**
   * @param context an application context. Shouldn't be {@code null}.
   * @return {@code true} if Mozc is enabled. Otherwise {@code false}.
   */
  public static boolean isMozcEnabled(Context context) {
    Preconditions.checkNotNull(context);
    if (isMozcEnabled.isPresent()) {
      return isMozcEnabled.get();
    }

    InputMethodManager inputMethodManager = getInputMethodManager(context);
    if (inputMethodManager == null) {
      MozcLog.w("InputMethodManager is not found.");
      return false;
    }
    String packageName = context.getPackageName();
    for (InputMethodInfo inputMethodInfo : inputMethodManager.getEnabledInputMethodList()) {
      if (inputMethodInfo.getServiceName().startsWith(packageName)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Just injects the result of isMozcEnabled for testing purpose,
   * doesn't actually enable Mozc.
   *
   * @param isMozcEnabled Optional.absent() for default behavior
   */
  public static void setMozcEnabled(Optional<Boolean> isMozcEnabled) {
    MozcUtil.isMozcEnabled = Preconditions.checkNotNull(isMozcEnabled);
  }

  /**
   * @param context an application context. Shouldn't be {@code null}.
   * @return {@code true} if the default IME is Mozc. Otherwise {@code false}.
   */
  public static boolean isMozcDefaultIme(Context context) {
    Preconditions.checkNotNull(context);
    if (isMozcDefaultIme.isPresent()) {
      return isMozcDefaultIme.get();
    }

    Optional<InputMethodInfo> mozcInputMethodInfo = getMozcInputMethodInfo(context);
    if (!mozcInputMethodInfo.isPresent()) {
      MozcLog.w("Mozc's InputMethodInfo is not found.");
      return false;
    }

    String currentIme = Settings.Secure.getString(
        context.getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
    return mozcInputMethodInfo.get().getId().equals(currentIme);
  }

  /**
   * Just injects the result of isMozcDefaultIme for testing purpose,
   * doesn't actually set mozc as the default ime.
   *
   * @param isMozcDefaultIme Optional.absent() for default behavior
   */
  public static void setMozcDefaultIme(Optional<Boolean> isMozcDefaultIme) {
    MozcUtil.isMozcDefaultIme = Preconditions.checkNotNull(isMozcDefaultIme);
  }

  private static Optional<InputMethodInfo> getMozcInputMethodInfo(Context context) {
    Preconditions.checkNotNull(context);
    InputMethodManager inputMethodManager = getInputMethodManager(context);
    if (inputMethodManager == null) {
      MozcLog.w("InputMethodManager is not found.");
      return Optional.absent();
    }
    String packageName = context.getPackageName();
    for (InputMethodInfo inputMethodInfo : inputMethodManager.getInputMethodList()) {
      if (inputMethodInfo.getPackageName().equals(packageName)) {
        return Optional.of(inputMethodInfo);
      }
    }

    // Not found.
    return Optional.absent();
  }

  /**
   * Returns true is touch UI should be shown.
   */
  public static boolean isTouchUI(Context context) {
    Preconditions.checkNotNull(context);
    if (isTouchUI.isPresent()) {
      return isTouchUI.get();
    }
    return context.getResources().getConfiguration().touchscreen
               != Configuration.TOUCHSCREEN_NOTOUCH;
  }

  /**
   * For testing purpose.
   *
   * @param isTouchUI Optional.absent() if default behavior is preferable
   */
  public static final void setTouchUI(Optional<Boolean> isTouchUI) {
    MozcUtil.isTouchUI = Preconditions.checkNotNull(isTouchUI);
  }

  public static long getUptimeMillis() {
    if (uptimeMillis.isPresent()) {
      return uptimeMillis.get();
    }
    return SystemClock.uptimeMillis();
  }

  /**
   * For testing purpose.
   *
   * @param uptimeMillis Optional.absent() if default behavior is preferable
   */
  public static void setUptimeMillis(Optional<Long> uptimeMillis) {
    MozcUtil.uptimeMillis = Preconditions.checkNotNull(uptimeMillis);
  }

  public static boolean requestShowInputMethodPicker(Context context) {
    Preconditions.checkNotNull(context);
    Handler showInputMethodPickerHandler = getShowInputMethodPickerHandler();
    return showInputMethodPickerHandler.sendMessage(
        showInputMethodPickerHandler.obtainMessage(SHOW_INPUT_METHOD_PICKER_WHAT, context));
  }

  public static void cancelShowInputMethodPicker(Context context) {
    Preconditions.checkNotNull(context);
    Handler showInputMethodPickerHandler = getShowInputMethodPickerHandler();
    showInputMethodPickerHandler.removeMessages(SHOW_INPUT_METHOD_PICKER_WHAT, context);
  }

  public static boolean hasShowInputMethodPickerRequest(Context context) {
    Preconditions.checkNotNull(context);
    Handler showInputMethodPickerHandler = getShowInputMethodPickerHandler();
    return showInputMethodPickerHandler.hasMessages(SHOW_INPUT_METHOD_PICKER_WHAT, context);
  }

  /**
   * Returns the {@code TelephonyManagerInterface} corresponding to the given {@code context}.
   */
  public static TelephonyManagerInterface getTelephonyManager(Context context) {
    Preconditions.checkNotNull(context);
    return new TelephonyManagerImpl(
        TelephonyManager.class.cast(context.getSystemService(Context.TELEPHONY_SERVICE)));
  }

  public static Context getContextWithOutOfMemoryRetrial(Context context) {
    Preconditions.checkNotNull(context);
    return new ContextWrapper(context) {
      final Resources resources =
          new OutOfMemoryRetryingResources(super.getResources(), OUT_OF_MEMORY_RETRY_COUNT);

      @Override
      public Resources getResources() {
        return resources;
      }
    };
  }

  public static <T extends View> T inflateWithOutOfMemoryRetrial(
      Class<T> clazz, LayoutInflater inflater,
      int resourceId, Optional<ViewGroup> root, boolean attachToRoot) {
    Preconditions.checkNotNull(clazz);
    Preconditions.checkNotNull(inflater);
    Preconditions.checkNotNull(root);
    for (int i = 0; i < OUT_OF_MEMORY_RETRY_COUNT; ++i) {
      try {
        return clazz.cast(inflater.inflate(resourceId, root.orNull(), attachToRoot));
      } catch (OutOfMemoryError e) {
        // Retry with GC.
        System.gc();
      }
    }

    return clazz.cast(inflater.inflate(resourceId, root.orNull(), attachToRoot));
  }

  public static Bitmap createBitmap(int width, int height, Config config) {
    Preconditions.checkNotNull(config);
    for (int i = 0; i < OUT_OF_MEMORY_RETRY_COUNT; ++i) {
      try {
        return Bitmap.createBitmap(width, height, config);
      } catch (OutOfMemoryError e) {
        // Retry with GC.
        System.gc();
      }
    }

    return Bitmap.createBitmap(width, height, config);
  }

  public static Bitmap createBitmap(Bitmap src) {
    Preconditions.checkNotNull(src);
    for (int i = 0; i < OUT_OF_MEMORY_RETRY_COUNT; ++i) {
      try {
        return Bitmap.createBitmap(src);
      } catch (OutOfMemoryError e) {
        // Retry with GC.
        System.gc();
      }
    }

    return Bitmap.createBitmap(src);
  }

  /**
   * Sets the given {@code token} and some layout parameters required to show the dialog from
   * the IME service correctly to the {@code dialog}.
   */
  public static void setWindowToken(IBinder token, Dialog dialog) {
    Preconditions.checkNotNull(token);
    Preconditions.checkNotNull(dialog);

    Window window = dialog.getWindow();
    WindowManager.LayoutParams layoutParams = window.getAttributes();
    layoutParams.token = token;
    layoutParams.type = WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
    layoutParams.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
    window.setAttributes(layoutParams);
  }

  private static Request.Builder getRequestBuilderInternal(
      KeyboardSpecification specification, Configuration configuration) {
    return Request.newBuilder()
        .setKeyboardName(
            specification.getKeyboardSpecificationName().formattedKeyboardName(configuration))
        .setSpecialRomanjiTable(specification.getSpecialRomanjiTable())
        .setSpaceOnAlphanumeric(specification.getSpaceOnAlphanumeric())
        .setKanaModifierInsensitiveConversion(
            specification.isKanaModifierInsensitiveConversion())
        .setCrossingEdgeBehavior(specification.getCrossingEdgeBehavior());
  }

  private static void setHardwareKeyboardRequest(Request.Builder builder, Resources resources) {
    builder.setMixedConversion(false)
        .setZeroQuerySuggestion(false)
        .setUpdateInputModeFromSurroundingText(true)
        .setAutoPartialSuggestion(false)
        .setCandidatePageSize(resources.getInteger(R.integer.floating_candidate_candidate_num));
  }

  public static void setSoftwareKeyboardRequest(Request.Builder builder) {
    builder.setMixedConversion(true)
        .setZeroQuerySuggestion(true)
        .setUpdateInputModeFromSurroundingText(false)
        .setAutoPartialSuggestion(true);
  }

  public static Request.Builder getRequestBuilder(
      Resources resources, KeyboardSpecification specification, Configuration configuration) {
    Preconditions.checkNotNull(resources);
    Preconditions.checkNotNull(specification);
    Preconditions.checkNotNull(configuration);
    Request.Builder builder = getRequestBuilderInternal(specification, configuration);
    if (specification.isHardwareKeyboard()) {
      setHardwareKeyboardRequest(builder, resources);
    } else {
      setSoftwareKeyboardRequest(builder);
    }
    return builder;
  }

  @SuppressLint("InlinedApi")
  public static boolean isPasswordField(int inputType) {
    int inputClass = inputType & InputType.TYPE_MASK_CLASS;
    int inputVariation = inputType & InputType.TYPE_MASK_VARIATION;
    return inputClass == InputType.TYPE_CLASS_TEXT
        && (inputVariation == InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD
            || inputVariation == InputType.TYPE_TEXT_VARIATION_PASSWORD
            || inputVariation == InputType.TYPE_TEXT_VARIATION_WEB_PASSWORD);
  }

  /**
   * Returns true if voice input is preferred by EditorInfo.inputType.
   *
   * <p>Caller should check that voice input is allowed or not by isVoiceInputAllowed().
   */
  public static boolean isVoiceInputPreferred(EditorInfo editorInfo) {
    Preconditions.checkNotNull(editorInfo);

    // Check privateImeOptions to ensure the text field supports voice input.
    if (editorInfo.privateImeOptions != null) {
      for (String option : editorInfo.privateImeOptions.split(",")) {
        if (option.equals(IME_OPTION_NO_MICROPHONE)
            || option.equals(IME_OPTION_NO_MICROPHONE_COMPAT)) {
          return false;
        }
      }
    }

    int inputType = editorInfo.inputType;
    if (isNumberKeyboardPreferred(inputType) || isPasswordField(inputType)) {
      return false;
    }
    if ((inputType & EditorInfo.TYPE_MASK_CLASS) == InputType.TYPE_CLASS_TEXT) {
      switch (inputType & EditorInfo.TYPE_MASK_VARIATION) {
        case InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS:
        case InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS:
        case InputType.TYPE_TEXT_VARIATION_URI:
          return false;
        default:
          break;
      }
    }
    return true;
  }

  /** Returns true if number keyboard is preferred by EditorInfo.inputType. */
  public static boolean isNumberKeyboardPreferred(int inputType) {
    int typeClass = inputType & InputType.TYPE_MASK_CLASS;
    // As of API Level 21, following condition equals to "typeClass != InputType.TYPE_CLASS_TEXT".
    // However type-class might be added in future so safer expression is employed here.
    return typeClass == InputType.TYPE_CLASS_DATETIME
        || typeClass == InputType.TYPE_CLASS_NUMBER
        || typeClass == InputType.TYPE_CLASS_PHONE;
  }

  public static String utf8CStyleByteStringToString(ByteString value) {
    Preconditions.checkNotNull(value);
    // Find '\0' terminator. (if value doesn't contain '\0', the size should be as same as
    // value's.)
    int index = 0;
    while (index < value.size() && value.byteAt(index) != 0) {
      ++index;
    }

    byte[] bytes = new byte[index];
    value.copyTo(bytes, 0, 0, bytes.length);
    try {
      return new String(bytes, "UTF-8");
    } catch (UnsupportedEncodingException e) {
      // Should never happen because of Java's spec.
      throw new IllegalStateException("UTF-8 charset is not available.");
    }
  }

  /**
   * Simple utility to close {@link Closeable} instance.
   *
   * A typical usage is as follows:
   * <pre>{@code
   *   Closeable stream = ...;
   *   boolean succeeded = false;
   *   try {
   *     // Read data from stream here.
   *     ...
   *
   *     succeeded = true;
   *   } finally {
   *     close(stream, !succeeded);
   *   }
   * }</pre>
   *
   * @param closeable
   * @param ignoreException
   * @throws IOException
   */
  public static void close(Closeable closeable, boolean ignoreException) throws IOException {
    Preconditions.checkNotNull(closeable);
    try {
      closeable.close();
    } catch (IOException e) {
      if (!ignoreException) {
        throw e;
      }
    }
  }

  /**
   * Simple utility to close {@link Socket} instance.
   * See {@link MozcUtil#close(Closeable,boolean)} for details.
   */
  public static void close(Socket socket, boolean ignoreIOException) throws IOException {
    Preconditions.checkNotNull(socket);
    try {
      socket.close();
    } catch (IOException e) {
      if (!ignoreIOException) {
        throw e;
      }
    }
  }

  /**
   * Simple utility to close {@link ServerSocket} instance.
   * See {@link MozcUtil#close(Closeable,boolean)} for details.
   */
  public static void close(ServerSocket socket, boolean ignoreIOException) throws IOException {
    Preconditions.checkNotNull(socket);
    try {
      socket.close();
    } catch (IOException e) {
      if (!ignoreIOException) {
        throw e;
      }
    }
  }

  /**
   * Simple utility to close {@link ParcelFileDescriptor} instance.
   * See {@link MozcUtil#close(Closeable,boolean)} for details.
   *
   * On later OS ParcelFileDescriptor implements {@link Closeable} but on earlier OS it doesn't.
   */
  public static void close(ParcelFileDescriptor descriptor, boolean ignoreIOException)
      throws IOException {
    Preconditions.checkNotNull(descriptor);
    try {
      descriptor.close();
    } catch (IOException e) {
      if (!ignoreIOException) {
        throw e;
      }
    }
  }

  /**
   * Closes the given {@code closeable}, and ignore any {@code IOException}s.
   */
  public static void closeIgnoringIOException(Closeable closeable) {
    try {
      Preconditions.checkNotNull(closeable).close();
    } catch (IOException e) {
      MozcLog.e("Failed to close.", e);
    }
  }

  /**
   * Closes the given {@code closeable}, and ignore any {@code IOException}s.
   */
  public static void closeIgnoringIOException(ZipFile zipFile) {
    try {
      Preconditions.checkNotNull(zipFile).close();
    } catch (IOException e) {
      MozcLog.e("Failed to close.", e);
    }
  }

  public static InputMethodManager getInputMethodManager(Context context) {
    Preconditions.checkNotNull(context);
    return InputMethodManager.class.cast(context.getSystemService(Context.INPUT_METHOD_SERVICE));
  }

  /**
   * Get temporary directory for user dictionary export feature.
   *
   * This method creates a new directory if it doesn't exist.
   */
  public static File getUserDictionaryExportTempDirectory(Context context) {
    File directory = new File(context.getCacheDir().getAbsolutePath(), USER_DICTIONARY_EXPORT_DIR);
    if (directory.exists()) {
      Preconditions.checkState(directory.isDirectory());
    } else {
      directory.mkdir();
    }
    return directory;
  }

  /**
   * Delete contents of the directory.
   *
   * The root directory itself is NOT deleted.
   *
   * @return true if all entries are successfully deleted.
   */
  public static boolean deleteDirectoryContents(File directory) {
    Preconditions.checkArgument(Preconditions.checkNotNull(directory).isDirectory());
    boolean result = true;
    for (File entry : directory.listFiles()) {
      if (entry.isDirectory()) {
        result &= deleteDirectoryContents(entry);
      }
      result &= entry.delete();
    }
    return result;
  }

  /**
   * Relaxes ThreadPolicy to enable network access.
   *
   * public accessibility for easier invocation via reflection.
   */
  @TargetApi(9)
  public static class StrictModeRelaxer {
    private StrictModeRelaxer() {}
    public static void relaxStrictMode() {
      StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitNetwork().build());
    }
  }

  // The restriction is applied since API Level 9.
  private static boolean isStrictModeRelaxed = Build.VERSION.SDK_INT < 9;

  /**
   * Relaxes the main thread's restriction.
   *
   * On newer Android OS, network access from the main thread is forbidden by default.
   * This method may relax the restriction.
   *
   * Note that this method works only in Debug build because this depends on reflection and
   * ProGuard will obfuscate the symbol name.
   * This behavior will not be fixed because this method is used only from Debug utilities
   * (i.e. SocketSessionHandler).
   */
  public static void relaxMainthreadStrictMode() {
    if (isStrictModeRelaxed) {
      // Already relaxed.
      return;
    }
    if (!Thread.currentThread().equals(Looper.getMainLooper().getThread())) {
      // Not on the main thread.
      return;
    }
    try {
      Class<?> clazz =
          Class.forName(new StringBuilder(MozcUtil.class.getCanonicalName())
                                          .append('$')
                                          .append("StrictModeRelaxer").toString());
      clazz.getMethod("relaxStrictMode").invoke(null);
      isStrictModeRelaxed = true;
    } catch (ClassNotFoundException e) {
      MozcLog.e(e.getMessage(), e);
    } catch (NoSuchMethodException e) {
      MozcLog.e(e.getMessage(), e);
    } catch (IllegalArgumentException e) {
      MozcLog.e(e.getMessage(), e);
    } catch (IllegalAccessException e) {
      MozcLog.e(e.getMessage(), e);
    } catch (InvocationTargetException e) {
      MozcLog.e(e.getMessage(), e);
    }
  }

  /**
   * If value &gt;= max returns max. If value &lt;= min returns min. Otherwise returns value.
   */
  public static int clamp(int value, int min, int max) {
    return Math.max(Math.min(value, max), min);
  }

  /**
   * If value &gt;= max returns max. If value &lt;= min returns min. Otherwise returns value.
   */
  public static float clamp(float value, float min, float max) {
    return Math.max(Math.min(value, max), min);
  }
}
