// 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.FeedbackManager.FeedbackEvent;
import org.mozc.android.inputmethod.japanese.FeedbackManager.FeedbackListener;
import org.mozc.android.inputmethod.japanese.KeycodeConverter.KeyEventInterface;
import org.mozc.android.inputmethod.japanese.emoji.EmojiProviderType;
import org.mozc.android.inputmethod.japanese.emoji.EmojiUtil;
import org.mozc.android.inputmethod.japanese.hardwarekeyboard.HardwareKeyboard.CompositionSwitchMode;
import org.mozc.android.inputmethod.japanese.hardwarekeyboard.HardwareKeyboardSpecification;
import org.mozc.android.inputmethod.japanese.keyboard.Keyboard.KeyboardSpecification;
import org.mozc.android.inputmethod.japanese.model.SelectionTracker;
import org.mozc.android.inputmethod.japanese.model.SymbolCandidateStorage.SymbolHistoryStorage;
import org.mozc.android.inputmethod.japanese.model.SymbolMajorCategory;
import org.mozc.android.inputmethod.japanese.mushroom.MushroomResultProxy;
import org.mozc.android.inputmethod.japanese.preference.ClientSidePreference;
import org.mozc.android.inputmethod.japanese.preference.PreferenceUtil;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCandidates;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.Command;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.Context.InputFieldType;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.DeletionRange;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.GenericStorageEntry.StorageType;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.Input;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.Input.TouchEvent;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.Output;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.Preedit;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.Preedit.Segment;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.Preedit.Segment.Annotation;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.SessionCommand;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.SessionCommand.UsageStatsEvent;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoConfig.Config;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoConfig.Config.SelectionShortcut;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoConfig.Config.SessionKeymap;
import org.mozc.android.inputmethod.japanese.resources.R;
import org.mozc.android.inputmethod.japanese.session.SessionExecutor;
import org.mozc.android.inputmethod.japanese.session.SessionHandlerFactory;
import org.mozc.android.inputmethod.japanese.util.ImeSwitcherFactory;
import org.mozc.android.inputmethod.japanese.util.ImeSwitcherFactory.ImeSwitcher;
import org.mozc.android.inputmethod.japanese.util.LauncherIconManagerFactory;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.protobuf.ByteString;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.content.res.Configuration;
import android.inputmethodservice.InputMethodService;
import android.media.AudioManager;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.Vibrator;
import android.preference.PreferenceManager;
import android.text.InputType;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.style.BackgroundColorSpan;
import android.text.style.CharacterStyle;
import android.text.style.UnderlineSpan;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.CursorAnchorInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputBinding;
import android.view.inputmethod.InputConnection;

import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Nullable;


/**
 * The input method service.
 *
 */
public class MozcService extends InputMethodService {

  /**
   * InputMethod implementation for MozcService.
   * This injects the composing text tracking feature by wrapping InputConnection.
   */
  public class MozcInputMethod extends InputMethodService.InputMethodImpl {
    @Override
    public void bindInput(InputBinding binding) {
      binding = new InputBinding(
          ComposingTextTrackingInputConnection.newInstance(binding.getConnection()),
          binding.getConnectionToken(),
          binding.getUid(),
          binding.getPid());
      super.bindInput(binding);
    }

    @Override
    public void startInput(InputConnection inputConnection, EditorInfo attribute) {
      super.startInput(
          ComposingTextTrackingInputConnection.newInstance(inputConnection), attribute);
    }

    @Override
    public void restartInput(InputConnection inputConnection, EditorInfo attribute) {
      super.restartInput(
          ComposingTextTrackingInputConnection.newInstance(inputConnection), attribute);
    }
  }

  private static class RealFeedbackListener implements FeedbackListener {
    private final Vibrator vibrator;
    private final AudioManager audioManager;

    private RealFeedbackListener(Vibrator vibrator, AudioManager audioManager) {
      if (vibrator == null) {
        MozcLog.w("vibrator must be non-null. Vibration is disabled.");
      }
      this.vibrator = vibrator;
      if (audioManager == null) {
        MozcLog.w("audioManager must be non-null. Sound feedback is disabled.");
      }
      this.audioManager = audioManager;
    }

    @Override
    public void onVibrate(long duration) {
      if (duration < 0) {
        MozcLog.w("duration must be >= 0 but " + duration);
        return;
      }
      if (vibrator != null) {
        vibrator.vibrate(duration);
      }
    }

    @Override
    public void onSound(int soundEffectType, float volume) {
      if (audioManager != null && soundEffectType != FeedbackManager.FeedbackEvent.NO_SOUND) {
        audioManager.playSoundEffect(soundEffectType, volume);
      }
    }
  }

  /** Adapter implementation of the symbol history manipulation. */
  static class SymbolHistoryStorageImpl implements SymbolHistoryStorage {
    static final Map<SymbolMajorCategory, StorageType> STORAGE_TYPE_MAP;
    static {
      Map<SymbolMajorCategory, StorageType> map =
          new EnumMap<SymbolMajorCategory, StorageType>(SymbolMajorCategory.class);
      map.put(SymbolMajorCategory.SYMBOL, StorageType.SYMBOL_HISTORY);
      map.put(SymbolMajorCategory.EMOTICON, StorageType.EMOTICON_HISTORY);
      map.put(SymbolMajorCategory.EMOJI, StorageType.EMOJI_HISTORY);
      STORAGE_TYPE_MAP = Collections.unmodifiableMap(map);
    }

    private final SessionExecutor sessionExecutor;

    SymbolHistoryStorageImpl(SessionExecutor sessionExecutor) {
      this.sessionExecutor = sessionExecutor;
    }

    @Override
    public List<String> getAllHistory(SymbolMajorCategory majorCategory) {
      List<ByteString> historyList =
          sessionExecutor.readAllFromStorage(STORAGE_TYPE_MAP.get(majorCategory));
      List<String> result = new ArrayList<String>(historyList.size());
      for (ByteString value : historyList) {
        result.add(MozcUtil.utf8CStyleByteStringToString(value));
      }
      return result;
    }

    @Override
    public void addHistory(SymbolMajorCategory majorCategory, String value) {
      Preconditions.checkNotNull(majorCategory);
      Preconditions.checkNotNull(value);
      sessionExecutor.insertToStorage(
          STORAGE_TYPE_MAP.get(majorCategory),
          value,
          Collections.singletonList(ByteString.copyFromUtf8(value)));
    }
  }

  // Called back from ViewManager
  @VisibleForTesting class MozcEventListener implements ViewEventListener {
    @Override
    public void onConversionCandidateSelected(int candidateId, Optional<Integer> rowIndex) {
      sessionExecutor.submitCandidate(candidateId, rowIndex, renderResultCallback);
      feedbackManager.fireFeedback(FeedbackEvent.CANDIDATE_SELECTED);
    }

    @Override
    public void onPageUp() {
      sessionExecutor.pageUp(renderResultCallback);
      feedbackManager.fireFeedback(FeedbackEvent.KEY_DOWN);
    }

    @Override
    public void onPageDown() {
      sessionExecutor.pageDown(renderResultCallback);
      feedbackManager.fireFeedback(FeedbackEvent.KEY_DOWN);
    }

    @Override
    public void onSymbolCandidateSelected(SymbolMajorCategory majorCategory, String candidate,
                                          boolean updateHistory) {
      Preconditions.checkNotNull(majorCategory);
      Preconditions.checkNotNull(candidate);

      // Directly commit the text.
      commitText(candidate);

      if (updateHistory) {
        symbolHistoryStorage.addHistory(majorCategory, candidate);
      }
      feedbackManager.fireFeedback(FeedbackEvent.CANDIDATE_SELECTED);
    }

    private void commitText(String text) {
      InputConnection inputConnection = getCurrentInputConnection();
      if (inputConnection == null) {
        return;
      }
      inputConnection.beginBatchEdit();
      try {
        inputConnection.commitText(text, MozcUtil.CURSOR_POSITION_TAIL);
      } finally {
        inputConnection.endBatchEdit();
      }
    }

    @Override
    public void onKeyEvent(
        @Nullable ProtoCommands.KeyEvent mozcKeyEvent, @Nullable KeyEventInterface keyEvent,
        @Nullable KeyboardSpecification keyboardSpecification, List<TouchEvent> touchEventList) {
      if (mozcKeyEvent == null && keyboardSpecification == null) {
        // We don't send a key event to Mozc native layer since {@code mozcKeyEvent} is null, and we
        // don't need to update the keyboard specification since {@code keyboardSpecification} is
        // also null.
        if (keyEvent == null) {
          // Send a usage information to Mozc native layer.
          sessionExecutor.touchEventUsageStatsEvent(touchEventList);
        } else {
          // Send a key event (which is generated by Mozc in the usual case) to application.
          Preconditions.checkArgument(touchEventList.isEmpty());
          sessionExecutor.sendKeyEvent(keyEvent, sendKeyToApplicationCallback);
        }
        return;
      }

      sendKeyWithKeyboardSpecification(mozcKeyEvent, keyEvent,
                                       keyboardSpecification, getConfiguration(),
                                       touchEventList);
    }

    @Override
    public void onUndo(List<TouchEvent> touchEventList) {
      sessionExecutor.undoOrRewind(touchEventList, renderResultCallback);
    }

    @Override
    public void onFireFeedbackEvent(FeedbackEvent event) {
      feedbackManager.fireFeedback(event);
      if (event.equals(FeedbackEvent.INPUTVIEW_EXPAND)) {
        sessionExecutor.sendUsageStatsEvent(UsageStatsEvent.KEYBOARD_EXPAND_EVENT);
      } else if (event.equals(FeedbackEvent.INPUTVIEW_FOLD)) {
        sessionExecutor.sendUsageStatsEvent(UsageStatsEvent.KEYBOARD_FOLD_EVENT);
      }
    }

    @Override
    public void onSubmitPreedit() {
      sessionExecutor.submit(renderResultCallback);
    }

    @Override
    public void onExpandSuggestion() {
      sessionExecutor.expandSuggestion(renderResultCallback);
    }

    @Override
    public void onShowMenuDialog(List<TouchEvent> touchEventList) {
      sessionExecutor.touchEventUsageStatsEvent(touchEventList);
    }

    @Override
    public void onShowSymbolInputView(List<TouchEvent> touchEventList) {
      changeKeyboardSpecificationAndSendKey(
          null, null, KeyboardSpecification.SYMBOL_NUMBER, getConfiguration(),
          Collections.<TouchEvent>emptyList());
      viewManager.onShowSymbolInputView();
    }

    @Override
    public void onCloseSymbolInputView() {
      viewManager.onCloseSymbolInputView();
      // This callback is called in two ways: one is from touch event on symbol input view.
      // The other is from onKeyDown event by hardware keyboard.  ViewManager.isNarrowMode()
      // is abused to distinguish these two triggers where its true value indicates that
      // onCloseSymbolInputView() is called on hardware keyboard event.  In the case of hardware
      // keyboard event, keyboard specification has been already updated so we shouldn't update it.
      if (!viewManager.isNarrowMode()) {
        changeKeyboardSpecificationAndSendKey(
            null, null, viewManager.getKeyboardSpecification(), getConfiguration(),
            Collections.<TouchEvent>emptyList());
      }
    }

    @Override
    public void onHardwareKeyboardCompositionModeChange(CompositionSwitchMode mode) {
      viewManager.switchHardwareKeyboardCompositionMode(mode);
    }

    @Override
    public void onActionKey() {
      // false means that the key is for Action and not ENTER.
      sendEditorAction(false);
    }

    @Override
    public void onNarrowModeChanged(boolean newNarrowMode) {
      if (!newNarrowMode) {
        // Hardware keyboard to software keyboard transition: Submit composition.
        sessionExecutor.submit(renderResultCallback);
      }
      updateImposedConfig();
    }

    @Override
    public void onUpdateKeyboardLayoutAdjustment(
        ViewManagerInterface.LayoutAdjustment layoutAdjustment) {
      Preconditions.checkNotNull(layoutAdjustment);
      Configuration configuration = getConfiguration();
      if (sharedPreferences == null || configuration == null) {
        return;
      }
      boolean isLandscapeKeyboardSettingActive =
          PreferenceUtil.isLandscapeKeyboardSettingActive(
              sharedPreferences, configuration.orientation);
      String key;
      if (isLandscapeKeyboardSettingActive) {
        key = PreferenceUtil.PREF_LANDSCAPE_LAYOUT_ADJUSTMENT_KEY;
      } else {
        key = PreferenceUtil.PREF_PORTRAIT_LAYOUT_ADJUSTMENT_KEY;
      }
      sharedPreferences.edit()
          .putString(key, layoutAdjustment.toString())
          .apply();
    }
  }

  /**
   * Callback to render the result received from Mozc server.
   */
  private class RenderResultCallback implements SessionExecutor.EvaluationCallback {

    @Override
    public void onCompleted(
        Optional<Command> command, Optional<KeyEventInterface> triggeringKeyEvent) {
      Preconditions.checkArgument(Preconditions.checkNotNull(command).isPresent());
      Preconditions.checkNotNull(triggeringKeyEvent);
      if (command.get().getInput().getCommand().getType()
          != SessionCommand.CommandType.EXPAND_SUGGESTION) {
        // For expanding suggestions, we don't need to update our rendering result.
        renderInputConnection(command.get(), triggeringKeyEvent.orNull());
      }
      // Transit to narrow mode if required (e.g., Typed 'a' key from h/w keyboard).
      viewManager.maybeTransitToNarrowMode(command.get(), triggeringKeyEvent.orNull());
      viewManager.render(command.get());
    }
  }

  /**
   * Callback to send key event to a application.
   */
  @VisibleForTesting
  class SendKeyToApplicationCallback implements SessionExecutor.EvaluationCallback {

    @Override
    public void onCompleted(Optional<Command> command,
                            Optional<KeyEventInterface> triggeringKeyEvent) {
      Preconditions.checkArgument(!Preconditions.checkNotNull(command).isPresent());
      sendKeyEvent(triggeringKeyEvent.orNull());
    }
  }

  /**
   * Callback to send key event to view layer.
   */
  private class SendKeyToViewCallback implements SessionExecutor.EvaluationCallback {

    @Override
    public void onCompleted(
        Optional<Command> command, Optional<KeyEventInterface> triggeringKeyEvent) {
      Preconditions.checkArgument(!Preconditions.checkNotNull(command).isPresent());
      Preconditions.checkArgument(Preconditions.checkNotNull(triggeringKeyEvent).isPresent());
      viewManager.consumeKeyOnViewSynchronously(triggeringKeyEvent.get().getNativeEvent().orNull());
    }
  }

  /**
   * Callback to invoke onUpdateSelectionInternal with delay for onConfigurationChanged.
   * See onConfigurationChanged for the details.
   */
  private class ConfigurationChangeCallback implements Handler.Callback {
    @Override
    public boolean handleMessage(Message msg) {
      int selectionStart = msg.arg1;
      int selectionEnd = msg.arg2;
      onUpdateSelectionInternal(selectionStart, selectionEnd, selectionStart, selectionEnd, -1, -1);
      return true;
    }
  }

  /**
   * We need to send SYNC_DATA command periodically. This class handles it.
   */
  @SuppressLint("HandlerLeak")
  private class SendSyncDataCommandHandler extends Handler {
    /**
     * The current period of sending SYNC_DATA is 15 mins (as same as desktop version).
     */
    static final int SYNC_DATA_COMMAND_PERIOD = 15 * 60 * 1000;

    @Override
    public void handleMessage(Message msg) {
      if (sessionExecutor != null) {
        sessionExecutor.syncData();
      }
      sendEmptyMessageDelayed(0, SYNC_DATA_COMMAND_PERIOD);
    }
  }

  /**
   * To trim memory, a message is handled to invoke trimMemory method
   * 10 seconds after hiding window.
   *
   * This class handles callback operation.
   * Posting and removing messages should be done in appropriate point.
   */
  @SuppressLint("HandlerLeak")
  private class MemoryTrimmingHandler extends Handler {

    /**
     * "what" value of message. Always use this.
     */
    static final int WHAT = 0;

    /**
     * Duration after hiding window in milliseconds.
     */
    static final int DURATION_MS = 10 * 1000;

    @Override
    public void handleMessage(Message msg) {
      trimMemory();
      // Other messages in the queue are removed as they will do the same thing
      // and will affect nothing.
      removeMessages(WHAT);
    }
  }


  // Keys for tweak preferences.
  private static final String PREF_TWEAK_PREFIX = "pref_tweak_";
  private static final String PREF_TWEAK_LOGGING_PROTOCOL_BUFFERS =
      "pref_tweak_logging_protocol_buffers";

  // Focused segment's attribute.
  @VisibleForTesting static final CharacterStyle SPAN_CONVERT_HIGHLIGHT =
      new BackgroundColorSpan(0x66EF3566);

  // Background color span for non-focused conversion segment.
  // We don't create a static CharacterStyle instance since there are multiple segments at the same
  // time. Otherwise, segments except for the last one cannot have style.
  @VisibleForTesting static final int CONVERT_NORMAL_COLOR = 0x19EF3566;

  // Cursor position.
  // Note that InputConnection seems not to be able to show cursor. This is a workaround.
  @VisibleForTesting static final CharacterStyle SPAN_BEFORE_CURSOR =
      new BackgroundColorSpan(0x664DB6AC);

  // Background color span for partial conversion.
  @VisibleForTesting static final CharacterStyle SPAN_PARTIAL_SUGGESTION_COLOR =
      new BackgroundColorSpan(0x194DB6AC);

  // Underline.
  @VisibleForTesting static final CharacterStyle SPAN_UNDERLINE = new UnderlineSpan();

  // Mozc's session. All session related task should be done via this instance.
  @VisibleForTesting SessionExecutor sessionExecutor;
  @VisibleForTesting final RenderResultCallback renderResultCallback = new RenderResultCallback();
  @VisibleForTesting final SendKeyToApplicationCallback sendKeyToApplicationCallback =
      new SendKeyToApplicationCallback();
  private final SendKeyToViewCallback sendKeyToViewCallback = new SendKeyToViewCallback();

  // A manager for all views and feedbacks.
  @VisibleForTesting
  public ViewManagerInterface viewManager;
  @VisibleForTesting FeedbackManager feedbackManager;
  @VisibleForTesting SymbolHistoryStorage symbolHistoryStorage;

  @VisibleForTesting SharedPreferences sharedPreferences;

  // A handler for onSharedPreferenceChanged().
  // Note: the handler is needed to be held by the service not to be GC'ed.
  @VisibleForTesting final OnSharedPreferenceChangeListener sharedPreferenceChangeListener =
      new SharedPreferenceChangeAdapter();

  // Preference information which are propagated. Null if not propagated yet.
  @VisibleForTesting ClientSidePreference propagatedClientSidePreference = null;

  // Track the selection.
  @VisibleForTesting SelectionTracker selectionTracker = new SelectionTracker();

  // A receiver to accept a notification via intents.
  @VisibleForTesting Handler configurationChangedHandler =
      new Handler(new ConfigurationChangeCallback());

  // Handler to process SYNC_DATA command for storing history data.
  @VisibleForTesting Handler sendSyncDataCommandHandler = new SendSyncDataCommandHandler();

  // Handler to process SYNC_DATA command for storing history data.
  private final Handler memoryTrimmingHandler = new MemoryTrimmingHandler();

  // This is a cache of MozcUtil.isDebug. It will be set in onCreateInternal and
  // will never be changed.
  private boolean isDebugBuild;

  // Current KeyboardSpecification, which is determined by the last key event.
  // Note that this might be different from what a user sees.
  // For example when a user is in narrow mode (this field is for H/W keyboard)
  // and (s)he taps widen button to see S/W keyboard,
  // (s)he will see S/W keyboard but this field keep to point H/W keyboard because
  // widen button is not a key event.
  // This behavior is error-prone and might be a kind of bug. At least the name doesn't represent
  // the behavior.
  // TODO(matsuzakit): Clarify the usage of this field (change the behavior to keep the latest
  //   state or change the name to represent current behavior).
  @VisibleForTesting KeyboardSpecification currentKeyboardSpecification =
      KeyboardSpecification.TWELVE_KEY_TOGGLE_KANA;

  // Current HardKeyboardHidden configuration value.
  // This is updated only when onConfigurationChanged is called and
  // Configuration.HARDKEYBOARDHIDDEN_* differs to this.
  private int currentHardKeyboardHidden = Configuration.HARDKEYBOARDHIDDEN_UNDEFINED;

  @VisibleForTesting boolean inputBound = false;

  private ApplicationCompatibility applicationCompatibility =
      ApplicationCompatibility.getDefaultInstance();

  // Listener called by views.
  // Held for testing.
  private ViewEventListener eventListener;

  @SuppressWarnings("deprecation")
  @SuppressLint("NewApi")
  public MozcService() {
    super();
    if (Build.VERSION.SDK_INT >= 17) {
      enableHardwareAcceleration();
    }
  }

  @Override
  public void onBindInput() {
    super.onBindInput();
    inputBound = true;
  }

  @Override
  public void onUnbindInput() {
    inputBound = false;
    super.onUnbindInput();
  }

  @Override
  public void onUpdateCursorAnchorInfo(CursorAnchorInfo cursorAnchorInfo) {
    if (viewManager != null) {
      viewManager.setCursorAnchorInfo(cursorAnchorInfo);
    }
  }

  @Override
  public MozcInputMethod onCreateInputMethodInterface() {
    return new MozcInputMethod();
  }

  @Override
  public void onCreate() {
    // Note: super.onCreate() is invoked in onCreateInternal. So, do not call it, here.
    MozcLog.d("start MozcService#onCreate " + System.nanoTime());

    // TODO(hidehiko): Restructure around initialization code in order to make tests stable.
    // Callback object mainly used by views.
    MozcEventListener eventListener = new MozcEventListener();
    SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
    Preconditions.checkNotNull(sharedPreferences);
    SessionExecutor sessionExecutor =
        SessionExecutor.getInstanceInitializedIfNecessary(
            new SessionHandlerFactory(Optional.of(sharedPreferences)), this);
    onCreateInternal(eventListener, null, sharedPreferences, getConfiguration(),
                     sessionExecutor);

    MozcLog.d("end MozcService#onCreate " + System.nanoTime());
  }

  @Override
  public void onDestroy() {
    feedbackManager.release();
    if (sessionExecutor != null) {
      sessionExecutor.syncData();
    }
    super.onDestroy();
  }

  @VisibleForTesting
  void onCreateInternal(ViewEventListener eventListener, @Nullable ViewManagerInterface viewManager,
                        @Nullable SharedPreferences sharedPreferences,
                        Configuration deviceConfiguration, SessionExecutor sessionExecutor) {
    super.onCreate();

    Context context = getApplicationContext();
    isDebugBuild = MozcUtil.isDebug(context);

    // TODO(hidehiko): Split following methods by functionalities to improve test coverage and
    //   test stableness.
    this.sessionExecutor = sessionExecutor;
    this.symbolHistoryStorage = new SymbolHistoryStorageImpl(sessionExecutor);
    this.eventListener = eventListener;
    prepareOnce(eventListener, symbolHistoryStorage, viewManager, sharedPreferences);
    prepareEveryTime(sharedPreferences, deviceConfiguration);

    if (propagatedClientSidePreference == null
        || propagatedClientSidePreference.getHardwareKeyMap() == null) {
      HardwareKeyboardSpecification.maybeSetDetectedHardwareKeyMap(
          sharedPreferences, deviceConfiguration, false);
    }

    // Start sending SYNC_DATA message to mozc server periodically.
    sendSyncDataCommandHandler.sendEmptyMessageDelayed(
        0, SendSyncDataCommandHandler.SYNC_DATA_COMMAND_PERIOD);
    this.sharedPreferences = sharedPreferences;
  }

  /**
   * Prepares something which should be done every time when the session is newly created.
   */
  private void prepareEveryTime(
      @Nullable SharedPreferences sharedPreferences, Configuration deviceConfiguration) {
    boolean isLogging = sharedPreferences != null
        && sharedPreferences.getBoolean(PREF_TWEAK_LOGGING_PROTOCOL_BUFFERS, false);
    // Force to initialize here.
    sessionExecutor.reset(
        new SessionHandlerFactory(Optional.fromNullable(sharedPreferences)), this);
    sessionExecutor.setLogging(isLogging);

    updateImposedConfig();
    viewManager.onConfigurationChanged(getConfiguration());
    // Make sure that the server and the client have the same keyboard specification.
    // User preference's keyboard will be set after this step.
    changeKeyboardSpecificationAndSendKey(
        null, null, currentKeyboardSpecification, deviceConfiguration,
        Collections.<TouchEvent>emptyList());
    if (sharedPreferences != null) {
      propagateClientSidePreference(
          new ClientSidePreference(
              sharedPreferences, getResources(), deviceConfiguration.orientation));
      // TODO(hidehiko): here we just set the config based on preferences. When we start
      //   to support sync on Android, we need to revisit the config related design.
      sessionExecutor.setConfig(ConfigUtil.toConfig(sharedPreferences));
      sessionExecutor.preferenceUsageStatsEvent(sharedPreferences, getResources());
    }

    maybeSetNarrowMode(deviceConfiguration);
  }

  /**
   * Prepares something which should be done only once.
   */
  private void prepareOnce(ViewEventListener eventListener,
      SymbolHistoryStorage symbolHistoryStorage,
      @Nullable ViewManagerInterface viewManager,
      @Nullable SharedPreferences sharedPreferences) {
    Context context = getApplicationContext();
    Optional<Intent> forwardIntent =
        ApplicationInitializerFactory.createInstance(this).initialize(
            MozcUtil.isSystemApplication(context),
            MozcUtil.isDevChannel(context),
            DependencyFactory.getDependency(getApplicationContext()).isWelcomeActivityPreferrable(),
            MozcUtil.getAbiIndependentVersionCode(context),
            LauncherIconManagerFactory.getDefaultInstance(),
            PreferenceUtil.getDefaultPreferenceManagerStatic());
    if (forwardIntent.isPresent()) {
      startActivity(forwardIntent.get());
    }

    // Create a ViewManager.
    if (viewManager == null) {
      ImeSwitcher imeSwitcher = ImeSwitcherFactory.getImeSwitcher(this);
      viewManager = DependencyFactory.getDependency(
          getApplicationContext()).createViewManager(
              getApplicationContext(),
              eventListener,
              symbolHistoryStorage,
              imeSwitcher,
              new MozcMenuDialogListenerImpl(this));
    }

    // Setup FeedbackManager.
    feedbackManager = new FeedbackManager(new RealFeedbackListener(
        Vibrator.class.cast(getSystemService(Context.VIBRATOR_SERVICE)),
        AudioManager.class.cast(getSystemService(Context.AUDIO_SERVICE))));

    this.viewManager = viewManager;

    // Set a callback for preference changing.
    if (sharedPreferences != null) {
      sharedPreferences.registerOnSharedPreferenceChangeListener(sharedPreferenceChangeListener);
    }
  }

  @Override
  public boolean onEvaluateInputViewShown() {
    // TODO(matsuzakit): Implement me
    return true;
  }

  @Override
  public View onCreateInputView() {
    MozcLog.d("start MozcService#onCreateInputView " + System.nanoTime());
    View inputView = viewManager.createMozcView(this);
    MozcLog.d("end MozcService#onCreateInputView " + System.nanoTime());
    return inputView;
  }

  private void resetContext() {
    if (sessionExecutor != null) {
      sessionExecutor.resetContext();
    }
    if (viewManager != null) {
      viewManager.reset();
    }
  }

  @Override
  public void onFinishInput() {
    // Omit rendering because the input view will soon disappear.
    resetContext();
    selectionTracker.onFinishInput();
    applicationCompatibility = ApplicationCompatibility.getDefaultInstance();
    super.onFinishInput();
  }

  @Override
  public void onStartInput(EditorInfo attribute, boolean restarting) {
    super.onStartInput(attribute, restarting);

    applicationCompatibility = ApplicationCompatibility.getInstance(attribute);

    // Update full screen mode, because the application may be changed.
    viewManager.setFullscreenMode(
        applicationCompatibility.isFullScreenModeSupported()
        && propagatedClientSidePreference != null
        && propagatedClientSidePreference.isFullscreenMode());

    // Some applications, e.g. gmail or maps, send onStartInput with restarting = true, when a user
    // rotates a device. In such cases, we don't want to update caret positions, nor reset
    // the context basically. However, some other applications, such as one with a webview widget
    // like a browser, send onStartInput with restarting = true, too. Unfortunately,
    // there seems no way to figure out which one causes this invocation.
    // So, as a point of compromise, we reset the context every time here. Also, we'll send
    // finishComposingText as well, in case the new attached field has already had composing text
    // (we hit such a situation on webview, too).
    // See also onConfigurationChanged for caret position handling on gmail-like applications'
    // device rotation events.
    resetContext();
    InputConnection connection = getCurrentInputConnection();
    if (connection != null) {
      connection.finishComposingText();
      maybeCommitMushroomResult(attribute, connection);
    }

    // Send the connected field's attributes to the mozc server.
    sessionExecutor.switchInputFieldType(getInputFieldType(attribute));
    sessionExecutor.updateRequest(
        EmojiUtil.createEmojiRequest(
            Build.VERSION.SDK_INT,
            (propagatedClientSidePreference != null && EmojiUtil.isCarrierEmojiAllowed(attribute))
                ? propagatedClientSidePreference.getEmojiProviderType() : EmojiProviderType.NONE),
        Collections.<TouchEvent>emptyList());
    selectionTracker.onStartInput(
        attribute.initialSelStart, attribute.initialSelEnd, isWebEditText(attribute));
  }

  /**
   * Hook to support mushroom protocol. If there is pending Mushroom result for the connecting
   * field, commit it. Then, (regardless of whether there exists pending result,) clears
   * all remaining pending result.
   */
  private static void maybeCommitMushroomResult(EditorInfo attribute, InputConnection connection) {
    if (connection == null) {
      return;
    }

    MushroomResultProxy resultProxy = MushroomResultProxy.getInstance();
    String result;
    synchronized (resultProxy) {
      // We need to obtain the result and then clear the all remaining result atomically.
      result = resultProxy.getReplaceKey(attribute.fieldId);
      resultProxy.clear();
    }
    if (result != null) {
      // Found the pending mushroom application result to the connecting field. Commit it.
      connection.commitText(result, MozcUtil.CURSOR_POSITION_TAIL);
    }
  }

  @SuppressLint("NewApi")
  private static boolean enableCursorAnchorInfo(InputConnection connection) {
    Preconditions.checkNotNull(connection);
    if (Build.VERSION.SDK_INT < 21) {
      return false;
    }
    return connection.requestCursorUpdates(
        InputConnection.CURSOR_UPDATE_IMMEDIATE | InputConnection.CURSOR_UPDATE_MONITOR);
  }

  /**
   * @return true if connected view is WebEditText (or the application pretends it)
   */
  private boolean isWebEditText(EditorInfo editorInfo) {
    if (editorInfo == null) {
      return false;
    }

    if (applicationCompatibility.isPretendingWebEditText()) {
      return true;
    }

    // TODO(hidehiko): Refine the heuristic to check isWebEditText related stuff.
    MozcLog.d("inputType: " + editorInfo.inputType);
    int variation = editorInfo.inputType & InputType.TYPE_MASK_VARIATION;
    return variation == InputType.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT;
  }

  @Override
  public void onStartInputView(EditorInfo attribute, boolean restarting) {
    InputConnection inputConnection = getCurrentInputConnection();
    if (inputConnection != null && Build.VERSION.SDK_INT >= 21) {
      viewManager.setCursorAnchorInfoEnabled(enableCursorAnchorInfo(inputConnection));
      updateImposedConfig();
    }

    viewManager.setTextForActionButton(getTextForImeAction(attribute.imeOptions));
    viewManager.setEditorInfo(attribute);
    // updateXxxxxButtonEnabled cannot be placed in onStartInput because
    // the view might be created after onStartInput with *reset* status.
    viewManager.updateGlobeButtonEnabled();
    viewManager.updateMicrophoneButtonEnabled();
  }

  static InputFieldType getInputFieldType(EditorInfo attribute) {
    int inputType = attribute.inputType;
    if (MozcUtil.isPasswordField(inputType)) {
      return InputFieldType.PASSWORD;
    }
    int inputClass = inputType & InputType.TYPE_MASK_CLASS;
    if (inputClass == InputType.TYPE_CLASS_PHONE) {
      return InputFieldType.TEL;
    }
    if (inputClass == InputType.TYPE_CLASS_NUMBER) {
      return InputFieldType.NUMBER;
    }
    return InputFieldType.NORMAL;
  }

  @Override
  public void onComputeInsets(InputMethodService.Insets outInsets) {
    viewManager.computeInsets(getApplicationContext(), outInsets, getWindow().getWindow());
  }

  /**
   * KeyDown event handler.
   *
   * This method is called only by the android framework e.g HOME,BACK or H/W keyboard input.
   */
  @Override
  public boolean onKeyDown(int keyCode, KeyEvent event) {
    return onKeyDownInternal(keyCode, event, getConfiguration());
  }

  /**
   * GenericMotionEvent handler.
   *
   * This method is called only by the android framework e.g H/W mouse, touch pad input, etc.
   */
  @TargetApi(17)
  @Override
  public boolean onGenericMotionEvent(MotionEvent event) {
    if (!isInputViewShown()) {
      return super.onGenericMotionEvent(event);
    }
    if (viewManager.isGenericMotionToConsume(event)) {
      return viewManager.consumeGenericMotion(event);
    }
    return super.onGenericMotionEvent(event);
  }

  @SuppressLint("DefaultLocale")
  @VisibleForTesting
  boolean onKeyDownInternal(int keyCode, KeyEvent event, Configuration configuration) {
    if (MozcLog.isLoggable(Log.DEBUG)) {
      MozcLog.d(
          String.format(
              "onKeyDown keyCode:0x%x, metaState:0x%x, scanCode:0x%x, uniCode:0x%x, deviceId:%d",
              event.getKeyCode(), event.getMetaState(), event.getScanCode(),
              event.getUnicodeChar(), event.getDeviceId()));
    }

    // Send back the event if the input view is not shown.
    if (!isInputViewShown()) {
      return super.onKeyDown(keyCode, event);
    }

    // Send back the event if the event is one of the system keys, which invoke
    // system's action. (e.g. back, home, power, volume and so on).
    if (event.isSystem()) {
      // Special handle for back key. We need to post it to the server and maybeProcessBackKey
      // should handle it later. The posting the event is done in onKeyUp, so we just consume the
      // down key event here.
      if (keyCode == KeyEvent.KEYCODE_BACK) {
        return true;
      }
      return super.onKeyDown(keyCode, event);
    }

    // Push the event to the asynchronous execution queue if it should be processed
    // directly in the view.
    if (viewManager.isKeyConsumedOnViewAsynchronously(event)) {
      sessionExecutor.sendKeyEvent(KeycodeConverter.getKeyEventInterface(event),
                                   sendKeyToViewCallback);
      return true;
    }

    // Lazy evaluation.
    // If hardware keyboard is not set in the preference screen,
    // set it based on the configuration.
    if (propagatedClientSidePreference == null
        || propagatedClientSidePreference.getHardwareKeyMap() == null) {
      HardwareKeyboardSpecification.maybeSetDetectedHardwareKeyMap(
          sharedPreferences, configuration, true);
    }

    // Here we decided to send the event to the server.

    viewManager.onHardwareKeyEvent(event);
    return true;
  }

  @Override
  public boolean onKeyUp(int keyCode, KeyEvent event) {
    if (isInputViewShown()) {
      if (event.isSystem()) {
        // The back key should be processed as same as the meta keys.
        // See also comments described below.
        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
          sessionExecutor.sendKeyEvent(
              KeycodeConverter.getKeyEventInterface(event), sendKeyToApplicationCallback);
          return true;
        }
      } else {
        if (viewManager.isKeyConsumedOnViewAsynchronously(event)) {
          sessionExecutor.sendKeyEvent(KeycodeConverter.getKeyEventInterface(event),
                                       sendKeyToViewCallback);
          return true;
        }

        // The IME is active and the server can handle the event so consume the event.
        // Currently the server does not consume UP event for not meta keys.
        // For meta keys, to guarantee that this up event is sent to InputConnection after down key,
        // this is sent to evaluation handler.
        if (KeycodeConverter.isMetaKey(event)) {
          sessionExecutor.sendKeyEvent(KeycodeConverter.getKeyEventInterface(event),
                                       sendKeyToApplicationCallback);
        }
        return true;
      }
    }

    // If the IME is turned off or the event should not be sent to the server,
    // delegate to the super class.
    // Note that delegation should be done only when needed.
    // For example hardware keyboard's enter key should not be delegated
    // because its DOWN event is sent to the sever.
    // If delegated, enter key event is sent to the application twice (DOWN and UP).
    return super.onKeyUp(keyCode, event);
  }

  /**
   * Sends mozcKeyEvent and/or Request to mozc server.
   *
   * This skips to send request if the given keyboard specification is same as before.
   */
  @VisibleForTesting
  void sendKeyWithKeyboardSpecification(
      @Nullable ProtoCommands.KeyEvent mozcKeyEvent, @Nullable KeyEventInterface event,
      @Nullable KeyboardSpecification keyboardSpecification, Configuration configuration,
      List<TouchEvent> touchEventList) {
    if (keyboardSpecification != null && currentKeyboardSpecification != keyboardSpecification) {
      // Submit composition on the transition from software KB to hardware KB by key event.
      if (!currentKeyboardSpecification.isHardwareKeyboard()
          && keyboardSpecification.isHardwareKeyboard()) {
        sessionExecutor.submit(renderResultCallback);
      }
      changeKeyboardSpecificationAndSendKey(
          mozcKeyEvent, event, keyboardSpecification, configuration, touchEventList);
      updateStatusIcon();
    } else if (mozcKeyEvent != null) {
      // Send mozcKeyEvent as usual.
      sessionExecutor.sendKey(mozcKeyEvent, event, touchEventList, renderResultCallback);
    } else if (event != null) {
      // Send event back to the application to handle key events which cannot be converted into Mozc
      // key event (e.g. Shift) correctly.
      sessionExecutor.sendKeyEvent(event, sendKeyToApplicationCallback);
    }
  }

  /**
   * Sends Request for changing keyboard setting to mozc server and sends key.
   */
  private void changeKeyboardSpecificationAndSendKey(
      @Nullable ProtoCommands.KeyEvent mozcKeyEvent, @Nullable KeyEventInterface event,
      KeyboardSpecification keyboardSpecification, Configuration configuration,
      List<TouchEvent> touchEventList) {
    // Send Request to change composition table.
    sessionExecutor.updateRequest(
        MozcUtil.getRequestBuilder(getResources(), keyboardSpecification, configuration).build(),
        touchEventList);
    if (mozcKeyEvent == null) {
      // Change composition mode.
      sessionExecutor.switchInputMode(
          Optional.fromNullable(event), keyboardSpecification.getCompositionMode(),
          renderResultCallback);
    } else {
      // Send key with composition mode change.
      sessionExecutor.sendKey(
          ProtoCommands.KeyEvent.newBuilder(mozcKeyEvent)
              .setMode(keyboardSpecification.getCompositionMode()).build(),
          event, touchEventList, renderResultCallback);
    }
    currentKeyboardSpecification = keyboardSpecification;
  }

  /**
   * Shows/Hides status icon according to the input view status.
   */
  private void updateStatusIcon() {
    if (isInputViewShown()) {
      showStatusIcon();
    } else {
      hideStatusIcon();
    }
  }

  /**
   * Shows the status icon basing on the current keyboard spec.
   */
  private void showStatusIcon() {
    switch (currentKeyboardSpecification.getCompositionMode()) {
      case HIRAGANA:
        showStatusIcon(R.drawable.status_icon_hiragana);
        break;
      default:
        showStatusIcon(R.drawable.status_icon_alphabet);
        break;
    }
  }

  @Override
  public boolean onEvaluateFullscreenMode() {
    return viewManager.isFullscreenMode();
  }

  @Override
  public boolean onShowInputRequested(int flags, boolean configChange) {
    boolean result = super.onShowInputRequested(flags, configChange);
    boolean isHardwareKeyboardConnected =
        getResources().getConfiguration().keyboard != Configuration.KEYBOARD_NOKEYS;
    // Original result becomes false when a hardware keyboard is connected.
    // This means that the window won't be shown in such situation.
    // We want to show it even with a hardware keyboard so override the result here.
    return result || isHardwareKeyboardConnected;
  }

  @Override
  public void onWindowShown() {
    showStatusIcon();
    // Remove memory trimming message.
    memoryTrimmingHandler.removeMessages(MemoryTrimmingHandler.WHAT);
    // Ensure keyboard's request.
    // The session might be deleted by trimMemory caused by onWindowHidden.
    // Note that this logic must be placed *after* removing the messages in memoryTrimmingHandler.
    // Otherwise the session might be unexpectedly deleted and newly re-created one will be used
    // without appropriate request which is sent below.
    changeKeyboardSpecificationAndSendKey(
        null, null, currentKeyboardSpecification, getConfiguration(),
        Collections.<TouchEvent>emptyList());
  }

  @Override
  public void onWindowHidden() {
    // "Hiding IME's window" is very similar to "Turning off IME" for PC.
    // Thus
    // - Committing composing text.
    // - Removing all pending messages.
    // - Resetting Mozc server
    // are needed.
    sessionExecutor.removePendingEvaluations();

    resetContext();
    selectionTracker.onWindowHidden();
    viewManager.reset();
    hideStatusIcon();
    // MemoryTrimmingHandler.DURATION_MS from now, memory trimming will be done.
    // If the window is shown before MemoryTrimmingHandler.DURATION_MS,
    // the message posted here will be removed.
    memoryTrimmingHandler.removeMessages(MemoryTrimmingHandler.WHAT);
    memoryTrimmingHandler.sendEmptyMessageDelayed(MemoryTrimmingHandler.WHAT,
                                                  MemoryTrimmingHandler.DURATION_MS);
    super.onWindowHidden();
  }

  /**
   * Updates InputConnection.
   *
   * @param command Output message. Rendering is based on this parameter.
   * @param keyEvent Trigger event for this calling. When direct input is
   *        needed, this event is sent to InputConnection.
   */
  @VisibleForTesting
  void renderInputConnection(Command command, @Nullable KeyEventInterface keyEvent) {
    Preconditions.checkNotNull(command);

    InputConnection inputConnection = getCurrentInputConnection();
    if (inputConnection == null) {
      return;
    }

    Output output = command.getOutput();
    if (!output.hasConsumed() || !output.getConsumed()) {
      maybeCommitText(output, inputConnection);
      sendKeyEvent(keyEvent);
      return;
    }

    // Meta key may invoke a command for Mozc server like SWITCH_INPUT_MODE session command. In this
    // case, the command is consumed by Mozc server and the application cannot get the key event.
    // To avoid such situation, we should send the key event back to application. b/13238551
    // The command itself is consumed by Mozc server, so we should NOT put a return statement here.
    if (keyEvent != null && keyEvent.getNativeEvent().isPresent()
        && KeycodeConverter.isMetaKey(keyEvent.getNativeEvent().get())) {
      sendKeyEvent(keyEvent);
    }

    // Here the key is consumed by the Mozc server.
    inputConnection.beginBatchEdit();
    try {
      maybeDeleteSurroundingText(output, inputConnection);
      maybeCommitText(output, inputConnection);
      setComposingText(command, inputConnection);
      maybeSetSelection(output, inputConnection);
      selectionTracker.onRender(
          output.hasDeletionRange() ? output.getDeletionRange() : null,
          output.hasResult() ? output.getResult().getValue() : null,
          output.hasPreedit() ? output.getPreedit() : null);
    } finally {
      inputConnection.endBatchEdit();
    }
  }

  private static KeyEvent createKeyEvent(
      KeyEvent original, long eventTime, int action, int repeatCount) {
    return new KeyEvent(
        original.getDownTime(), eventTime, action, original.getKeyCode(),
        repeatCount, original.getMetaState(), original.getDeviceId(), original.getScanCode(),
        original.getFlags());
  }

  /**
   * Sends the {@code KeyEvent}, which is not consumed by the mozc server.
   */
  @VisibleForTesting void sendKeyEvent(KeyEventInterface keyEvent) {
    if (keyEvent == null) {
      return;
    }

    int keyCode = keyEvent.getKeyCode();
    // Some keys have a potential to be consumed from mozc client.
    if (maybeProcessBackKey(keyCode) || maybeProcessActionKey(keyCode)) {
      // The key event is consumed.
      return;
    }

    // Following code is to fallback to target activity.
    Optional<KeyEvent> nativeKeyEvent = keyEvent.getNativeEvent();
    InputConnection inputConnection = getCurrentInputConnection();

    if (nativeKeyEvent.isPresent() && inputConnection != null) {
      // Meta keys are from this.onKeyDown/Up so fallback each time.
      if (KeycodeConverter.isMetaKey(nativeKeyEvent.get())) {
        inputConnection.sendKeyEvent(createKeyEvent(
            nativeKeyEvent.get(), MozcUtil.getUptimeMillis(),
            nativeKeyEvent.get().getAction(), nativeKeyEvent.get().getRepeatCount()));
        return;
      }

      // Other keys are from this.onKeyDown so create dummy Down/Up events.
      inputConnection.sendKeyEvent(createKeyEvent(
          nativeKeyEvent.get(), MozcUtil.getUptimeMillis(), KeyEvent.ACTION_DOWN, 0));

      inputConnection.sendKeyEvent(createKeyEvent(
          nativeKeyEvent.get(), MozcUtil.getUptimeMillis(), KeyEvent.ACTION_UP, 0));
      return;
    }

    // Otherwise, just delegates the key event to the connected application.
    sendDownUpKeyEvents(keyCode);
  }

  /**
   * @return true if the key event is consumed
   */
  private boolean maybeProcessBackKey(int keyCode) {
    if (keyCode != KeyEvent.KEYCODE_BACK || !isInputViewShown()) {
      return false;
    }

    // Special handling for back key event, to close the software keyboard or its subview.
    // First, try to hide the subview, such as the symbol input view or the cursor view.
    // If neither is shown, hideSubInputView would fail, then hide the whole software keyboard.
    if (!viewManager.hideSubInputView()) {
      requestHideSelf(0);
    }
    return true;
  }

  private boolean maybeProcessActionKey(int keyCode) {
    // Handle the event iff the enter is pressed.
    if (keyCode != KeyEvent.KEYCODE_ENTER || !isInputViewShown()) {
      return false;
    }
    return sendEditorAction(true);
  }

  /**
   * Sends editor action to {@code InputConnection}.
   * <p>
   * The difference from {@link InputMethodService#sendDefaultEditorAction(boolean)} is
   * that if custom action label is specified {@code EditorInfo#actionId} is sent instead.
   */
  private boolean sendEditorAction(boolean fromEnterKey) {
    // If custom action label is specified (=non-null), special action id is also specified.
    // If there is no IME_FLAG_NO_ENTER_ACTION option, we should send the id to the InputConnection.
    EditorInfo editorInfo = getCurrentInputEditorInfo();
    if (editorInfo != null
        && (editorInfo.imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) == 0
        && editorInfo.actionLabel != null) {
      InputConnection inputConnection = getCurrentInputConnection();
      if (inputConnection != null) {
        inputConnection.performEditorAction(editorInfo.actionId);
        return true;
      }
    }
    // No custom action label is specified. Fall back to default EditorAction.
    return sendDefaultEditorAction(fromEnterKey);
  }

  private static void maybeDeleteSurroundingText(Output output, InputConnection inputConnection) {
    if (!output.hasDeletionRange()) {
      return;
    }

    DeletionRange range = output.getDeletionRange();
    int leftRange = -range.getOffset();
    int rightRange = range.getLength() - leftRange;
    if (leftRange < 0 || rightRange < 0) {
      // If the range does not include the current position, do nothing
      // because Android's API does not expect such situation.
      MozcLog.w("Deletion range has unsupported parameters: " + range.toString());
      return;
    }

    if (!inputConnection.deleteSurroundingText(leftRange, rightRange)) {
      MozcLog.e("Failed to delete surrounding text.");
    }
  }

  private static void maybeCommitText(Output output, InputConnection inputConnection) {
    if (!output.hasResult()) {
      return;
    }

    String outputText = output.getResult().getValue();
    if (outputText.equals("")) {
      // Do nothing for an empty result string.
      return;
    }

    int position = MozcUtil.CURSOR_POSITION_TAIL;
    if (output.getResult().hasCursorOffset()) {
      if (output.getResult().getCursorOffset()
          == -outputText.codePointCount(0, outputText.length())) {
        position = MozcUtil.CURSOR_POSITION_HEAD;
      } else {
        MozcLog.e("Unsupported position: " + output.getResult().toString());
      }
    }

    if (!inputConnection.commitText(outputText, position)) {
      MozcLog.e("Failed to commit text.");
    }
  }

  private void setComposingText(Command command, InputConnection inputConnection) {
    Preconditions.checkNotNull(command);
    Preconditions.checkNotNull(inputConnection);

    Output output = command.getOutput();
    if (!output.hasPreedit()) {
      // If preedit field is empty, we should clear composing text in the InputConnection
      // because Mozc server asks us to do so.
      // But there is special situation in Android.
      // On onWindowShown, SWITCH_INPUT_MODE command is sent as a step of initialization.
      // In this case we reach here with empty preedit.
      // As described above we should clear the composing text but if we do so
      // texts in selection range (e.g., URL in OmniBox) is always cleared.
      // To avoid from this issue, we don't clear the composing text if the input
      // is SWITCH_INPUT_MODE.
      Input input = command.getInput();
      if (input.getType() != Input.CommandType.SEND_COMMAND
          || input.getCommand().getType() != SessionCommand.CommandType.SWITCH_INPUT_MODE) {
        if (!inputConnection.setComposingText("", 0)) {
          MozcLog.e("Failed to set composing text.");
        }
      }
      return;
    }

    // Builds preedit expression.
    Preedit preedit = output.getPreedit();

    SpannableStringBuilder builder = new SpannableStringBuilder();
    for (Segment segment : preedit.getSegmentList()) {
      builder.append(segment.getValue());
    }

    // Set underline for all the preedit text.
    builder.setSpan(SPAN_UNDERLINE, 0, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

    // Draw cursor if in composition mode.
    int cursor = preedit.getCursor();
    int spanFlags = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | Spanned.SPAN_COMPOSING;
    if (output.hasAllCandidateWords()
        && output.getAllCandidateWords().hasCategory()
        && output.getAllCandidateWords().getCategory() == ProtoCandidates.Category.CONVERSION) {
      int offsetInString = 0;
      for (Segment segment : preedit.getSegmentList()) {
        int length = segment.getValue().length();
        builder.setSpan(
            segment.hasAnnotation() && segment.getAnnotation() == Annotation.HIGHLIGHT
                ? SPAN_CONVERT_HIGHLIGHT
                : CharacterStyle.class.cast(new BackgroundColorSpan(CONVERT_NORMAL_COLOR)),
            offsetInString, offsetInString + length, spanFlags);
        offsetInString += length;
      }
    } else {
      // We cannot show system cursor inside preedit here.
      // Instead we change text style before the preedit's cursor.
      int cursorOffsetInString = builder.toString().offsetByCodePoints(0, cursor);
      if (cursor != builder.length()) {
        builder.setSpan(SPAN_PARTIAL_SUGGESTION_COLOR, cursorOffsetInString, builder.length(),
                        spanFlags);
      }
      if (cursor > 0) {
        builder.setSpan(SPAN_BEFORE_CURSOR, 0, cursorOffsetInString, spanFlags);
      }
    }

    // System cursor will be moved to the tail of preedit.
    // It triggers onUpdateSelection again.
    int cursorPosition = cursor > 0 ? MozcUtil.CURSOR_POSITION_TAIL : 0;
    if (!inputConnection.setComposingText(builder, cursorPosition)) {
      MozcLog.e("Failed to set composing text.");
    }
  }

  private void maybeSetSelection(Output output, InputConnection inputConnection) {
    if (!output.hasPreedit()) {
      return;
    }

    Preedit preedit = output.getPreedit();
    int cursor = preedit.getCursor();
    if (cursor == 0 || cursor == getPreeditLength(preedit)) {
      // The cursor is at the beginning/ending of the preedit. So we don't anything about the
      // caret setting.
      return;
    }

    int caretPosition = selectionTracker.getPreeditStartPosition();
    if (output.hasDeletionRange()) {
      caretPosition += output.getDeletionRange().getOffset();
    }
    if (output.hasResult()) {
      caretPosition += output.getResult().getValue().length();
    }
    if (output.hasPreedit()) {
      caretPosition += output.getPreedit().getCursor();
    }

    if (!inputConnection.setSelection(caretPosition, caretPosition)) {
      MozcLog.e("Failed to set selection.");
    }
  }

  private static int getPreeditLength(Preedit preedit) {
    int result = 0;
    for (int i = 0; i < preedit.getSegmentCount(); ++i) {
      result += preedit.getSegment(i).getValueLength();
    }
    return result;
  }

  /**
   * Propagates the preferences which affect client-side.
   *
   * If the previous parameter (this.clientSidePreference) is null,
   * all the fields in the latest parameter are propagated.
   * If not, only differences are propagated.
   *
   * After the execution, {@code this.propagatedClientSidePreference} is updated.
   *
   * @param newPreference the ClientSidePreference to be propagated
   */
  @VisibleForTesting void propagateClientSidePreference(ClientSidePreference newPreference) {
    // TODO(matsuzakit): Receive a Config to reflect the current device configuration.
    if (newPreference == null) {
      MozcLog.e("newPreference must be non-null. No update is performed.");
      return;
    }
    ClientSidePreference oldPreference = propagatedClientSidePreference;
    if (oldPreference == null
        || oldPreference.isHapticFeedbackEnabled() != newPreference.isHapticFeedbackEnabled()) {
      feedbackManager.setHapticFeedbackEnabled(newPreference.isHapticFeedbackEnabled());
    }
    if (oldPreference == null
        || oldPreference.getHapticFeedbackDuration() != newPreference.getHapticFeedbackDuration()) {
      feedbackManager.setHapticFeedbackDuration(newPreference.getHapticFeedbackDuration());
    }
    if (oldPreference == null
        || oldPreference.isSoundFeedbackEnabled() != newPreference.isSoundFeedbackEnabled()) {
      feedbackManager.setSoundFeedbackEnabled(newPreference.isSoundFeedbackEnabled());
    }
    if (oldPreference == null
        || oldPreference.getSoundFeedbackVolume() != newPreference.getSoundFeedbackVolume()) {
      // The default value is 0.4f. In order to set the 50 to the default value, divide the
      // preference value by 125f heuristically.
      feedbackManager.setSoundFeedbackVolume(newPreference.getSoundFeedbackVolume() / 125f);
    }
    if (oldPreference == null
        || oldPreference.isPopupFeedbackEnabled() != newPreference.isPopupFeedbackEnabled()) {
      viewManager.setPopupEnabled(newPreference.isPopupFeedbackEnabled());
    }
    if (oldPreference == null
        || oldPreference.getKeyboardLayout() != newPreference.getKeyboardLayout()) {
      viewManager.setKeyboardLayout(newPreference.getKeyboardLayout());
    }
    if (oldPreference == null
        || oldPreference.getInputStyle() != newPreference.getInputStyle()) {
      viewManager.setInputStyle(newPreference.getInputStyle());
    }
    if (oldPreference == null
        || oldPreference.isQwertyLayoutForAlphabet() != newPreference.isQwertyLayoutForAlphabet()) {
      viewManager.setQwertyLayoutForAlphabet(newPreference.isQwertyLayoutForAlphabet());
    }
    if (oldPreference == null
        || oldPreference.isFullscreenMode() != newPreference.isFullscreenMode()) {
      viewManager.setFullscreenMode(
          applicationCompatibility.isFullScreenModeSupported() && newPreference.isFullscreenMode());
    }
    if (oldPreference == null
        || oldPreference.getFlickSensitivity() != newPreference.getFlickSensitivity()) {
      viewManager.setFlickSensitivity(newPreference.getFlickSensitivity());
    }
    if (oldPreference == null
        || oldPreference.getEmojiProviderType() != newPreference.getEmojiProviderType()) {
      viewManager.setEmojiProviderType(newPreference.getEmojiProviderType());
    }
    if (oldPreference == null
        || oldPreference.getHardwareKeyMap() != newPreference.getHardwareKeyMap()) {
      viewManager.setHardwareKeyMap(newPreference.getHardwareKeyMap());
    }
    if (oldPreference == null
        || oldPreference.getSkinType() != newPreference.getSkinType()) {
      viewManager.setSkin(newPreference.getSkinType().getSkin(getResources()));
    }
    if (oldPreference == null
        || oldPreference.isMicrophoneButtonEnabled() != newPreference.isMicrophoneButtonEnabled()) {
      viewManager.setMicrophoneButtonEnabledByPreference(newPreference.isMicrophoneButtonEnabled());
    }
    if (oldPreference == null
        || oldPreference.getLayoutAdjustment() != newPreference.getLayoutAdjustment()) {
      viewManager.setLayoutAdjustment(newPreference.getLayoutAdjustment());
    }
    if (oldPreference == null
        || oldPreference.getKeyboardHeightRatio() != newPreference.getKeyboardHeightRatio()) {
      viewManager.setKeyboardHeightRatio(newPreference.getKeyboardHeightRatio());
    }

    propagatedClientSidePreference  = newPreference;
  }

  /**
   * Sends imposed config to the Mozc server.
   *
   * Some config items should be mobile ones.
   * For example, "selection shortcut" should be disabled on software keyboard
   * regardless of stored config if there is no hardware keyboard.
   */
  private void updateImposedConfig() {
    // TODO(hsumita): Respect Config.SelectionShortcut.
    SelectionShortcut shortcutMode = (viewManager != null && viewManager.isFloatingCandidateMode())
        ? SelectionShortcut.SHORTCUT_123456789 : SelectionShortcut.NO_SHORTCUT;

    // TODO(matsuzakit): deviceConfig should be used to set following config items.
    sessionExecutor.setImposedConfig(Config.newBuilder()
        .setSessionKeymap(SessionKeymap.MOBILE)
        .setSelectionShortcut(shortcutMode)
        .setUseEmojiConversion(true)
        .build());
  }

  /**
   * A call-back to catch all the change on any preferences.
   */
  private class SharedPreferenceChangeAdapter implements OnSharedPreferenceChangeListener {
    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
      if (isDebugBuild) {
        MozcLog.d("onSharedPreferenceChanged : " + key);
      }
      if (key.startsWith(PREF_TWEAK_PREFIX)) {
        // If the key belongs to PREF_TWEAK group, re-create SessionHandler and view.
        prepareEveryTime(sharedPreferences, getConfiguration());
        setInputView(onCreateInputView());
        return;
      }
      propagateClientSidePreference(
          new ClientSidePreference(
              sharedPreferences, getResources(), getConfiguration().orientation));
      sessionExecutor.setConfig(ConfigUtil.toConfig(sharedPreferences));
      sessionExecutor.preferenceUsageStatsEvent(sharedPreferences, getResources());
    }
  }

  @VisibleForTesting void maybeSetNarrowMode(Configuration configuration) {
    // If given hardKeyboardHidden is equal to current one, skip updating narrow mode.
    // In other words, only hardKeyboardHidden flag changes narrow mode automatically.
    // This behavior is beneficial for a user who want to change narrow/full mode manually
    // because this method keeps current narrow mode unless hardware keyboard connection is changed.
    if (viewManager != null && configuration.hardKeyboardHidden != currentHardKeyboardHidden) {
      currentHardKeyboardHidden = configuration.hardKeyboardHidden;
      switch (currentHardKeyboardHidden) {
        case Configuration.HARDKEYBOARDHIDDEN_NO:
          if (!viewManager.isNarrowMode()) {
            viewManager.hideSubInputView();
            viewManager.setNarrowMode(true);
          }
          break;
        case Configuration.HARDKEYBOARDHIDDEN_YES:
          if (viewManager.isNarrowMode()) {
            viewManager.setNarrowMode(false);
          }
          break;
        case Configuration.HARDKEYBOARDHIDDEN_UNDEFINED:
          break;
      }
    }
  }

  @VisibleForTesting void onConfigurationChangedInternal(Configuration newConfig) {
    InputConnection inputConnection = getCurrentInputConnection();
    if (inputConnection != null) {
      if (inputBound) {
        inputConnection.finishComposingText();
      }
      int selectionStart = selectionTracker.getLastSelectionStart();
      int selectionEnd = selectionTracker.getLastSelectionEnd();
      if (selectionStart >= 0 && selectionEnd >= 0) {
        // We need to keep the last caret position, but it will be soon overwritten in
        // onStartInput. Theoretically, we should prohibit the overwriting, but unfortunately
        // there is no good way to figure out whether the invocation of onStartInput is caused by
        // configuration change, or not. Thus, instead, we'll make an event to invoke
        // onUpdateSelectionInternal with an expected position after the onStartInput invocation,
        // so that it will again overwrite the caret position.
        // Note that, if a user rotates the device with holding preedit text, it will be committed
        // by finishComposingText above, and onUpdateSelection will be invoked from the framework.
        // Invoke onUpdateSelectionInternal twice with same arguments should be safe in this
        // situation.
        configurationChangedHandler.sendMessage(
            configurationChangedHandler.obtainMessage(0, selectionStart, selectionEnd));
      }
    }
    resetContext();
    selectionTracker.onConfigurationChanged();

    sessionExecutor.updateRequest(
        MozcUtil.getRequestBuilder(getResources(), currentKeyboardSpecification, newConfig).build(),
        Collections.<TouchEvent>emptyList());

    // NOTE : This method is not called at the time when the service is started.
    // Based on newConfig, client side preferences should be sent
    // because they change based on device config.
    propagateClientSidePreference(new ClientSidePreference(
        Preconditions.checkNotNull(PreferenceManager.getDefaultSharedPreferences(this)),
        getResources(), newConfig.orientation));
    maybeSetNarrowMode(newConfig);
    viewManager.onConfigurationChanged(newConfig);
  }

  @Override
  public void onConfigurationChanged(Configuration newConfig) {
    onConfigurationChangedInternal(newConfig);
    // super.onConfigurationChanged must be called after propagateClientSidePreference
    // to use updated MobileConfiguration.
    super.onConfigurationChanged(newConfig);
  }

  @VisibleForTesting
  void onUpdateSelectionInternal(int oldSelStart, int oldSelEnd,
                                 int newSelStart, int newSelEnd,
                                 int candidatesStart, int candidatesEnd) {
    MozcLog.d("start MozcService#onUpdateSelectionInternal " + System.nanoTime());
    if (isDebugBuild) {
      MozcLog.d("selection updated: [" + oldSelStart + ":" + oldSelEnd + "] "
                    + "to: [" + newSelStart + ":" + newSelEnd + "] "
                    + "candidates: [" + candidatesStart + ":" + candidatesEnd + "]");
    }

    int updateStatus = selectionTracker.onUpdateSelection(
        oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd);
    if (isDebugBuild) {
      MozcLog.d(selectionTracker.toString());
    }
    switch (updateStatus) {
      case SelectionTracker.DO_NOTHING:
        // Do nothing.
        break;
      case SelectionTracker.RESET_CONTEXT: {
        sessionExecutor.resetContext();

        // Commit the current composing text (preedit text), in case we hit an unknown state.
        // Keeping the composing text sometimes makes it impossible for users to input characters,
        // because it can cause consecutive mis-understanding of caret positions.
        // We do this iff the keyboard is shown, because some other application may edit
        // composition string, such as Google Translate.
        if (isInputViewShown() && inputBound) {
          InputConnection inputConnection = getCurrentInputConnection();
          if (inputConnection != null) {
            inputConnection.finishComposingText();
          }
        }

        // Rendering default Command causes hiding candidate window,
        // and re-showing the keyboard view.
        viewManager.render(Command.getDefaultInstance());
        break;
      }
      default:
        // Otherwise, the updateStatus is the position of the cursor to be moved.
        if (updateStatus < 0) {
          throw new AssertionError("Unknown update status: " + updateStatus);
        }
        sessionExecutor.moveCursor(updateStatus, renderResultCallback);
        break;
    }

    MozcLog.d("end MozcService#onUpdateSelectionInternal " + System.nanoTime());
  }

  @Override
  public void onUpdateSelection(int oldSelStart, int oldSelEnd,
                                int newSelStart, int newSelEnd,
                                int candidatesStart, int candidatesEnd) {
    onUpdateSelectionInternal(
        oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd);
    super.onUpdateSelection(
        oldSelStart, oldSelEnd, newSelStart, newSelEnd, candidatesStart, candidatesEnd);
  }

  private void trimMemory() {
    // We must guarantee the contract of MemoryManageable#trimMemory.
    if (!isInputViewShown()) {
      MozcLog.d("Trimming memory");
      sessionExecutor.deleteSession();
      viewManager.trimMemory();
    }
  }

  // To use special Configuration for testing, overriding this method might works.
  @VisibleForTesting
  Configuration getConfiguration() {
    return getResources().getConfiguration();
  }

  @VisibleForTesting
  ViewEventListener getViewEventListener() {
    return eventListener;
  }

  @Override
  @VisibleForTesting
  public void attachBaseContext(Context base) {
    super.attachBaseContext(base);
  }
}
