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

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

import org.mozc.android.inputmethod.japanese.MemoryManageable;
import org.mozc.android.inputmethod.japanese.accessibility.AccessibilityUtil;
import org.mozc.android.inputmethod.japanese.accessibility.KeyboardAccessibilityDelegate;
import org.mozc.android.inputmethod.japanese.keyboard.KeyState.MetaState;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.Input.TouchAction;
import org.mozc.android.inputmethod.japanese.protobuf.ProtoCommands.Input.TouchEvent;
import org.mozc.android.inputmethod.japanese.resources.R;
import org.mozc.android.inputmethod.japanese.view.DrawableCache;
import org.mozc.android.inputmethod.japanese.view.Skin;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.google.common.collect.ForwardingMap;
import com.google.common.collect.Sets;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.os.Looper;
import android.support.v4.view.ViewCompat;
import android.text.InputType;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;

import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Basic implementation of a keyboard's view.
 * This class supports taps and flicks. The clients of this class can handle them via
 * {@code KeyboardActionListener}.
 *
 */
public class KeyboardView extends View implements MemoryManageable {

  private final BackgroundDrawableFactory backgroundDrawableFactory =
      new BackgroundDrawableFactory(getResources());
  private final DrawableCache drawableCache = new DrawableCache(getResources());
  private final PopUpPreview.Pool popupPreviewPool =
      new PopUpPreview.Pool(
          this, Looper.getMainLooper(), backgroundDrawableFactory, drawableCache);
  private final long popupDismissDelay;

  private Optional<Keyboard> keyboard = Optional.absent();
  // Do not update directly. Use setMetaState instead.
  @VisibleForTesting Set<MetaState> metaState;
  @VisibleForTesting final KeyboardViewBackgroundSurface backgroundSurface =
      new KeyboardViewBackgroundSurface(backgroundDrawableFactory, drawableCache);
  @VisibleForTesting boolean isKeyPressed;

  private final float scaledDensity;

  private int flickSensitivity;
  private boolean popupEnabled = true;

  private final KeyboardAccessibilityDelegate accessibilityDelegate;

  /**
   * Decorator class for {@code Map} for {@code KeyEventContextMap}.
   * <p>
   * When the number of the content is changed, meta state "HANDLING_TOUCH_EVENT"
   * is updated.
   */
  private final class KeyEventContextMap extends ForwardingMap<Integer, KeyEventContext>{

    private final Map<Integer, KeyEventContext> delegate;

    private KeyEventContextMap(Map<Integer, KeyEventContext> delegate) {
      this.delegate = delegate;
    }

    @Override
    protected Map<Integer, KeyEventContext> delegate() {
      return delegate;
    }

    @Override
    public void clear() {
      super.clear();
      updateHandlingTouchEventMetaState();
    }

    @Override
    public KeyEventContext put(Integer key, KeyEventContext value) {
      KeyEventContext result = super.put(key, value);
      updateHandlingTouchEventMetaState();
      return result;
    }

    @Override
    public void putAll(Map<? extends Integer, ? extends KeyEventContext> map) {
      super.putAll(map);
      updateHandlingTouchEventMetaState();
    }

    @Override
    public KeyEventContext remove(Object object) {
      KeyEventContext result = super.remove(object);
      updateHandlingTouchEventMetaState();
      return result;
    }

    private void updateHandlingTouchEventMetaState() {
      if (keyEventContextMap.isEmpty()) {
        updateMetaStates(Collections.<MetaState>emptySet(),
                         Collections.singleton(MetaState.HANDLING_TOUCH_EVENT));
      } else {
        updateMetaStates(Collections.singleton(MetaState.HANDLING_TOUCH_EVENT),
                         Collections.<MetaState>emptySet());
      }
    }
  }

  // A map from pointerId to KeyEventContext.
  // Note: the pointerId should be small integers, e.g. 0, 1, 2... So if it turned out
  //   that the usage of Map is heavy, we probably can replace this map by a List or
  //   an array.
  // We use LinkedHashMap with accessOrder=false here, in order to ensure sending key events
  // in the pressing order in flushPendingKeyEvent.
  // Its initial capacity (16) and load factor (0.75) are just heuristics.
  @VisibleForTesting public final Map<Integer, KeyEventContext> keyEventContextMap =
      new KeyEventContextMap(new LinkedHashMap<Integer, KeyEventContext>(16, 0.75f, false));

  private Optional<KeyEventHandler> keyEventHandler = Optional.absent();

  // This constructor is package private for this unit test.
  public KeyboardView(Context context) {
    super(context);
  }

  public KeyboardView(Context context, AttributeSet attrSet) {
    super(context, attrSet);
  }

  public KeyboardView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }

  // Initializer shared by constructors.
  {
    Context context = getContext();
    Resources res = context.getResources();
    popupDismissDelay = res.getInteger(R.integer.config_popup_dismiss_delay);
    scaledDensity = res.getDisplayMetrics().scaledDensity;
    accessibilityDelegate = new KeyboardAccessibilityDelegate(
        this, new KeyboardAccessibilityDelegate.TouchEventEmulator() {
          @Override
          public void emulateLongPress(Key key) {
            Preconditions.checkNotNull(key);
            emulateImpl(key, true);
          }

          @Override
          public void emulateKeyInput(Key key) {
            Preconditions.checkNotNull(key);
            emulateImpl(key, false);
          }

          private void emulateImpl(Key key, boolean isLongPress) {
            KeyEventContext keyEventContext = new KeyEventContext(key, 0, 0, 0, 0, 0, 0, metaState);
            processKeyEventContextForOnDownEvent(keyEventContext);
            if (isLongPress && keyEventHandler.isPresent()) {
              keyEventHandler.get().handleMessageLongPress(keyEventContext);
            }
            processKeyEventContextForOnUpEvent(keyEventContext);
            // Without the invalidation this view cannot know that its content
            // has been updated.
            invalidate();
          }
        });
    ViewCompat.setAccessibilityDelegate(this, accessibilityDelegate);
    // Not sure if globe is really activated.
    // However metastate requires GLOBE or NO_GLOBE state.
    setMetaStates(EnumSet.of(MetaState.NO_GLOBE));
  }

  /**
   * At the moment, it is not limited to, but we expected the range of the flickSensitivity
   * is [-10,+10] inclusive. 0 is the keyboard default sensitivity.
   */
  public void setFlickSensitivity(int flickSensitivity) {
    this.flickSensitivity = flickSensitivity;
  }

  public int getFlickSensitivity() {
    return flickSensitivity;
  }

  private float getFlickSensitivityInDip() {
    // To adapt the flickSensitiy Level to actual length, we scale 1.5f heuristically.
    return -flickSensitivity * 1.5f * scaledDensity;
  }

  private Optional<KeyEventContext> getKeyEventContextByKey(Key key) {
    Preconditions.checkNotNull(key);
    for (KeyEventContext keyEventContext : keyEventContextMap.values()) {
      if (key == keyEventContext.key) {
        return Optional.of(keyEventContext);
      }
    }
    return Optional.absent();
  }

  private void disposeKeyEventContext(KeyEventContext keyEventContext) {
    Preconditions.checkNotNull(keyEventContext);
    if (keyEventHandler.isPresent()) {
      keyEventHandler.get().cancelDelayedKeyEvent(keyEventContext);
    }
    backgroundSurface.requestUpdateKey(keyEventContext.key, Optional.<Flick.Direction>absent());
    if (popupEnabled || keyEventContext.longPressCallback.isPresent()) {
      popupPreviewPool.releaseDelayed(keyEventContext.pointerId, popupDismissDelay);
    }
  }

  /**
   * Reset the internal state of this view.
   */
  public void resetState() {
    // To re-render the key in the normal state, notify the background surface about it.
    for (KeyEventContext keyEventContext : keyEventContextMap.values()) {
      disposeKeyEventContext(keyEventContext);
    }
    keyEventContextMap.clear();
  }

  private void flushPendingKeyEvent(Optional<TouchEvent> relativeTouchEvent) {
    Preconditions.checkNotNull(relativeTouchEvent);

    // Back up values and clear the map first to avoid stack overflow
    // in case this method is invoked recursively from the callback.
    // TODO(hidehiko): Refactor around keyEventHandler and keyEventContext. Also we should be
    //   able to refactor this method with resetState.
    KeyEventContext[] keyEventContextArray =
        keyEventContextMap.values().toArray(new KeyEventContext[keyEventContextMap.size()]);
    keyEventContextMap.clear();

    for (KeyEventContext keyEventContext : keyEventContextArray) {
      int keyCode = keyEventContext.getKeyCode();
      int pressedKeyCode = keyEventContext.getPressedKeyCode();
      disposeKeyEventContext(keyEventContext);
      if (keyEventHandler.isPresent()) {
        // Send relativeTouchEvent as well if exists.
        // TODO(hsumita): Confirm that we can put null on touchEventList or not.
        List<TouchEvent> touchEventList = relativeTouchEvent.isPresent()
            ? Arrays.asList(relativeTouchEvent.get(), keyEventContext.getTouchEvent().orNull())
            : Collections.singletonList(keyEventContext.getTouchEvent().orNull());
        keyEventHandler.get().sendKey(keyCode, touchEventList);
        keyEventHandler.get().sendRelease(pressedKeyCode);
      }
    }
  }

  /** Set a given keyboard to this view, and send a request to update. */
  public void setKeyboard(Keyboard keyboard) {
    flushPendingKeyEvent(Optional.<TouchEvent>absent());

    this.keyboard = Optional.of(keyboard);
    updateMetaStates(Collections.<MetaState>emptySet(), MetaState.CHAR_TYPE_EXCLUSIVE_GROUP);
    accessibilityDelegate.setKeyboard(this.keyboard);
    this.drawableCache.clear();
    backgroundSurface.requestUpdateKeyboard(keyboard, metaState);
    backgroundSurface.requestUpdateSize(keyboard.contentRight - keyboard.contentLeft,
                                        keyboard.contentBottom - keyboard.contentTop);
    invalidate();
  }

  public void setPopupEnabled(boolean popupEnabled) {
    this.popupEnabled = popupEnabled;
    if (!popupEnabled) {
      // When popup up is disabled, release all resources for popup immediately.
      popupPreviewPool.releaseAll();
    }
  }

  public boolean isPopupEnabled() {
    return popupEnabled;
  }

  @Override
  public void onDetachedFromWindow() {
    backgroundSurface.reset();
    super.onDetachedFromWindow();
  }

  /** @return the current keyboard instance */
  public Optional<Keyboard> getKeyboard() {
    return keyboard;
  }

  @SuppressWarnings("deprecation")
  public void setSkin(Skin skin) {
    Preconditions.checkNotNull(skin);
    drawableCache.setSkin(skin);
    backgroundDrawableFactory.setSkin(skin);
    if (keyboard.isPresent()) {
      backgroundSurface.requestUpdateKeyboard(keyboard.get(), metaState);
    }
    setBackgroundDrawable(skin.windowBackgroundDrawable.getConstantState().newDrawable());
  }

  public void setKeyEventHandler(KeyEventHandler keyEventHandler) {
    // This method needs to be invoked from a thread which the looper held by older keyEventHandler
    // points. Otherwise, there can be inconsistent state.
    Optional<KeyEventHandler> oldKeyEventHandler = this.keyEventHandler;
    if (oldKeyEventHandler.isPresent()) {
      // Cancel pending key event messages sent by this view.
      for (KeyEventContext keyEventContext : keyEventContextMap.values()) {
        oldKeyEventHandler.get().cancelDelayedKeyEvent(keyEventContext);
      }
    }
    this.keyEventHandler = Optional.of(keyEventHandler);
  }

  @Override
  public void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    if (!keyboard.isPresent()) {
      // We have nothing to do.
      return;
    }
    // Draw keyboard.
    backgroundSurface.update();
    backgroundSurface.draw(canvas);
  }

  @SuppressLint("InlinedApi")
  private static int getPointerIndex(int action) {
    return
        (action & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
  }

  private void onDown(MotionEvent event) {
    Preconditions.checkState(keyboard.isPresent());

    int pointerIndex = getPointerIndex(event.getAction());
    float x = event.getX(pointerIndex);
    float y = event.getY(pointerIndex);

    Optional<Key> optionalKey = getKeyByCoord(x, y);
    if (!optionalKey.isPresent()) {
      // Just ignore if a key isn't found.
      return;
    }

    if (getKeyEventContextByKey(optionalKey.get()).isPresent()) {
      // If the key is already pressed, we simply ignore event sequence related to this press.
      return;
    }

    // Create a new key event context.
    int pointerId = event.getPointerId(pointerIndex);
    float flickThreshold =
        Math.max(keyboard.get().getFlickThreshold() + getFlickSensitivityInDip(), 1);
    final KeyEventContext keyEventContext = new KeyEventContext(
        optionalKey.get(), pointerId, x, y, getWidth(), getHeight(),
        flickThreshold * flickThreshold, metaState);

    // Show popup.
    updatePopUp(keyEventContext, false);
    Optional<KeyEntity> keyEntity =
        KeyEventContext.getKeyEntity(keyEventContext.key, metaState,
                                     Optional.of(Flick.Direction.CENTER));
    if (keyEntity.isPresent() && keyEntity.get().getPopUp().isPresent()
        && !keyEntity.get().isLongPressTimeoutTrigger()) {
      keyEventContext.setLongPressCallback(new Runnable() {
          @Override
          public void run() {
            updatePopUp(keyEventContext, true);
          }
        });
    }

    // Process the KeyEventContext (e.g., sending messages to KeyEventHandler, updating the surface,
    // flushing pending key events and so on)
    processKeyEventContextForOnDownEvent(keyEventContext);
    // keyEventContextMap contains older event.
    // TODO(hidehiko): Switch to ignoring new event, or overwriting the old event
    //   not to show unknown exceptions to users.
    Preconditions.checkState(
        keyEventContextMap.put(pointerId, keyEventContext) == null,
        "Conflicting keyEventContext is found: " + pointerId);
  }

  private void processKeyEventContextForOnDownEvent(
      final KeyEventContext keyEventContext) {
    Set<MetaState> nextMetaStates = keyEventContext.getNextMetaStates(metaState);

    if (!nextMetaStates.equals(metaState)) {
      // This is a modifier key, so we toggle the keyboard UI at the press timing instead of
      // releasing timing. It is in order to support multi-touch with the modifier key.
      // For example, "SHIFT + a" multi-touch will produce 'A' keycode, not 'a' keycode.

      // At first, we flush all pending key event under the current (older) keyboard.
      flushPendingKeyEvent(keyEventContext.getTouchEvent());

      // And then set isKeyPressed flag to false, in order to reset keyboard to unmodified state
      // after multi-touch key events.
      // For example, we expect the metaState will be back to unmodified if a user types
      // "SHIFT + a".
      isKeyPressed = false;

      // Update the metaState and request to update the full keyboard image
      // to update all key icons.
      setMetaStates(nextMetaStates);
      backgroundSurface.requestUpdateKeyboard(keyboard.get(), nextMetaStates);
    } else {
      // Remember if a non-modifier key is pressed.
      isKeyPressed = true;

      // Request to update the image of only this key on the view.
      backgroundSurface.requestUpdateKey(keyEventContext.key,
                                         Optional.of(keyEventContext.flickDirection));
    }
    if (keyEventHandler.isPresent()) {
      // Clear pending key events and overwrite by this press key's one.
      for (KeyEventContext context : keyEventContextMap.values()) {
        keyEventHandler.get().cancelDelayedKeyEvent(context);
      }
      keyEventHandler.get().maybeStartDelayedKeyEvent(keyEventContext);
      // Finally we send a notification to listeners.
      keyEventHandler.get().sendPress(keyEventContext.getPressedKeyCode());
    }
  }

  private void onUp(MotionEvent event) {
    Preconditions.checkState(keyboard.isPresent());

    int pointerIndex = getPointerIndex(event.getAction());
    KeyEventContext keyEventContext = keyEventContextMap.remove(event.getPointerId(pointerIndex));
    if (keyEventContext == null) {
      // No corresponding event is found, so we have nothing to do.
      return;
    }

    float x = event.getX(pointerIndex);
    float y = event.getY(pointerIndex);
    keyEventContext.update(x, y, TouchAction.TOUCH_UP, event.getEventTime() - event.getDownTime());

    processKeyEventContextForOnUpEvent(keyEventContext);
  }

  private void processKeyEventContextForOnUpEvent(KeyEventContext keyEventContext) {
    disposeKeyEventContext(keyEventContext);

    int keyCode = keyEventContext.getKeyCode();
    int pressedKeyCode = keyEventContext.getPressedKeyCode();

    if (keyEventHandler.isPresent()) {
      if (keyCode != KeyEntity.INVALID_KEY_CODE) {
        // TODO(hsumita): Confirm that we can put null as a touch event or not.
        keyEventHandler.get().sendKey(keyCode,
            Collections.singletonList(keyEventContext.getTouchEvent().orNull()));
      }
      keyEventHandler.get().sendRelease(pressedKeyCode);
    }

    if (keyEventContext.isMetaStateToggleEvent()) {
      if (isKeyPressed) {
        // A user pressed at least one key with pressing modifier key, and then the user
        // released this modifier key. So, we flush all pending events here, and
        // reset the keyboard's meta state to unmodified.
        flushPendingKeyEvent(keyEventContext.getTouchEvent());
        updateMetaStates(Collections.<MetaState>emptySet(), MetaState.CHAR_TYPE_EXCLUSIVE_GROUP);
        backgroundSurface.requestUpdateKeyboard(keyboard.get(), Collections.<MetaState>emptySet());
      }
    } else {
      if (!metaState.isEmpty() && keyEventContextMap.isEmpty()) {
        Set<MetaState> nextMetaState = Sets.newEnumSet(metaState, MetaState.class);
        for (MetaState state : metaState) {
          if (state.isOneTimeMetaState) {
            // The current state is one time only, and we hit a release non-modifier key event here.
            // So, we reset the meta state to unmodified.
            nextMetaState.remove(state);
          }
        }
        if (!nextMetaState.equals(metaState)) {
          setMetaStates(nextMetaState);
          backgroundSurface.requestUpdateKeyboard(
              keyboard.get(), Collections.<MetaState>emptySet());
        }
      }
    }
  }

  private void onMove(MotionEvent event) {
    int pointerCount = event.getPointerCount();
    for (int i = 0; i < pointerCount; ++i) {
      KeyEventContext keyEventContext = keyEventContextMap.get(event.getPointerId(i));
      if (keyEventContext == null) {
        continue;
      }

      Key key = keyEventContext.key;
      if (keyEventContext.update(event.getX(i), event.getY(i), TouchAction.TOUCH_MOVE,
                                 event.getEventTime() - event.getDownTime())) {
        if (keyEventHandler.isPresent()) {
          // The key's state is updated from, at least, initial state, so we'll cancel the
          // pending key events, and invoke new pending key events if necessary.
          keyEventHandler.get().cancelDelayedKeyEvent(keyEventContext);
          if (keyEventContext.flickDirection == Flick.Direction.CENTER) {
            keyEventHandler.get().maybeStartDelayedKeyEvent(keyEventContext);
          }
        }
        updatePopUp(keyEventContext, false);
      }
      backgroundSurface.requestUpdateKey(key, Optional.of(keyEventContext.flickDirection));
    }
  }

  // Note that event is not used but this function takes it to standardize the signature to
  // other onXXX methods defined above.
  private void onCancel(@SuppressWarnings("unused") MotionEvent event) {
    resetState();
    if (keyEventHandler.isPresent()) {
      keyEventHandler.get().sendCancel();
    }
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    switch (event.getActionMasked()) {
      case MotionEvent.ACTION_DOWN:
      case MotionEvent.ACTION_POINTER_DOWN:
        onDown(event);
        break;
      case MotionEvent.ACTION_UP:
      case MotionEvent.ACTION_POINTER_UP:
        onUp(event);
        break;
      case MotionEvent.ACTION_MOVE:
        onMove(event);
        break;
      case MotionEvent.ACTION_CANCEL:
        onCancel(event);
        break;
      default:
        // The event is not handled by this class.
        return false;
    }

    // The keyboard's state is somehow changed. Update the view.
    invalidate();
    return true;
  }

  /**
   * Finds a key containing the given coordinate.
   * @param x {@code x}-coordinate.
   * @param y {@code y}-coordinate.
   * @return A corresponding {@code Key} instance, or {@code Optional.<Key>absent()} if not found.
   */
  @VisibleForTesting Optional<Key> getKeyByCoord(float x, float y) {
    if (y < 0 || !keyboard.isPresent() || keyboard.get().getRowList().isEmpty()) {
      return Optional.absent();
    }

    List<Row> rowList = keyboard.get().getRowList();
    int rowBottom = 0;
    Row lastRow = rowList.get(rowList.size() - 1);
    for (Row row : rowList) {
      rowBottom += row.getHeight() + row.getVerticalGap();
      Key prevKey = null;
      for (Key key : row.getKeyList()) {
        if ((// Stick vertical gaps to the keys above.
             y < key.getY() + key.getHeight() + row.getVerticalGap()
             // Or the key is at the bottom of the keyboard.
             // Note: Some devices sense touch events of out-side of screen.
             //   So, for better user experiences, we return the bottom row
             //   if a user touches below the screen bottom boundary.
             || row == lastRow
             || key.getY() + key.getHeight() >= keyboard.get().contentBottom)
            // Horizontal gap is included in the width,
            // so we don't need to calculate horizontal gap in addition to width.
            && x < key.getX() + key.getWidth()
            // The following condition selects a key hit in A, C, or D
            // (C and D are on the same key), and excludes a key hit in B.
            //                +---+---+
            // current row -> | A | C |
            //                +---+   |
            // next row    -> | B | D |
            //                +---+---+
            // The condition y < rowBottom allows hits on A and C, and the other
            // condition key.getX() <= x allows hits on C and D but not B.
            // Hence, the hits on B are excluded.
            && (y < rowBottom || key.getX() <= x)) {
          if (!key.isSpacer()) {
            return Optional.of(key);  // Found a key.
          }

          switch (key.getStick()) {
            case LEFT:
              if (prevKey != null) {
                return Optional.of(prevKey);
              }
              break;
            case EVEN:
              // Split the spacer evenly, assuming we don't have any consecutive spacers.
              if (x < key.getX() + key.getWidth() / 2 && prevKey != null) {
                return Optional.of(prevKey);
              }
              break;
            case RIGHT:
              // Do nothing to delegate the target to the next one.
          }
        }

        if (!key.isSpacer()) {
          prevKey = key;
        }
      }

      if ((y < rowBottom || row == lastRow) && prevKey != null) {
        return Optional.of(prevKey);
      }
    }

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

  @Override
  public void trimMemory() {
    backgroundSurface.trimMemory();
    drawableCache.clear();
    popupPreviewPool.releaseAll();
  }

  @Override
  public boolean dispatchTouchEvent(MotionEvent event) {
    Preconditions.checkNotNull(event);
    if (AccessibilityUtil.isTouchExplorationEnabled(getContext())) {
      return accessibilityDelegate.dispatchTouchEvent(event);
    }
    return super.dispatchTouchEvent(event);
  }

  @Override
  public boolean dispatchHoverEvent(MotionEvent event) {
    Preconditions.checkNotNull(event);
    if (AccessibilityUtil.isTouchExplorationEnabled(getContext())) {
      return accessibilityDelegate.dispatchHoverEvent(event);
    }
    return false;
  }

  @VisibleForTesting
  public Set<MetaState> getMetaStates() {
    return this.metaState;
  }

  private void setMetaStates(Set<MetaState> metaState) {
    Preconditions.checkNotNull(metaState);
    Preconditions.checkArgument(MetaState.isValidSet(metaState));
    this.metaState = metaState;
    accessibilityDelegate.setMetaState(metaState);
    backgroundSurface.requestMetaState(metaState);
  }

  public void updateMetaStates(Set<MetaState> addedMetaStates, Set<MetaState> removedMetaStates) {
    Preconditions.checkNotNull(addedMetaStates);
    Preconditions.checkNotNull(removedMetaStates);

    setMetaStates(Sets.union(Sets.difference(metaState, removedMetaStates),
                             addedMetaStates).immutableCopy());
    invalidate();
  }

  public void setPasswordField(boolean isPasswordField) {
    accessibilityDelegate.setPasswordField(isPasswordField);
  }

  public void setEditorInfo(EditorInfo editorInfo) {
    Preconditions.checkNotNull(editorInfo);

    Set<MetaState> metaStates = EnumSet.noneOf(MetaState.class);
    // If IME_FLAG_NO_ENTER_ACTION is set, normal action icon should be shown.
    if ((editorInfo.imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) == 0) {
      switch (editorInfo.imeOptions & EditorInfo.IME_MASK_ACTION) {
        case EditorInfo.IME_ACTION_DONE:
          metaStates.add(MetaState.ACTION_DONE);
          break;
        case EditorInfo.IME_ACTION_GO:
          metaStates.add(MetaState.ACTION_GO);
          break;
        case EditorInfo.IME_ACTION_NEXT:
          metaStates.add(MetaState.ACTION_NEXT);
          break;
        case EditorInfo.IME_ACTION_NONE:
          metaStates.add(MetaState.ACTION_NONE);
          break;
        case EditorInfo.IME_ACTION_PREVIOUS:
          metaStates.add(MetaState.ACTION_PREVIOUS);
          break;
        case EditorInfo.IME_ACTION_SEARCH:
          metaStates.add(MetaState.ACTION_SEARCH);
          break;
        case EditorInfo.IME_ACTION_SEND:
          metaStates.add(MetaState.ACTION_SEND);
          break;
        default:
          // Do nothing
      }
    }

    // InputType variation is *NOT* bit-fields in fact.
    int clazz = editorInfo.inputType & InputType.TYPE_MASK_CLASS;
    int variation = editorInfo.inputType & InputType.TYPE_MASK_VARIATION;
    switch (clazz) {
      case InputType.TYPE_CLASS_TEXT:
        switch (variation) {
          case InputType.TYPE_TEXT_VARIATION_URI:
            metaStates.add(MetaState.VARIATION_URI);
            break;
          case InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS:
          case InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS:
            metaStates.add(MetaState.VARIATION_EMAIL_ADDRESS);
            break;
          default:
            // Do nothing
        }
        break;
      default:
        // Do nothing
    }

    updateMetaStates(metaStates, Sets.union(MetaState.ACTION_EXCLUSIVE_GROUP,
                                            MetaState.VARIATION_EXCLUSIVE_GROUP));
  }

  public void setGlobeButtonEnabled(boolean isGlobeButtonEnabled) {
    if (isGlobeButtonEnabled) {
      updateMetaStates(EnumSet.of(MetaState.GLOBE), EnumSet.of(MetaState.NO_GLOBE));
    } else {
      updateMetaStates(EnumSet.of(MetaState.NO_GLOBE), EnumSet.of(MetaState.GLOBE));
    }
  }

  private void updatePopUp(KeyEventContext keyEventContext, boolean isDelayedPopUp) {
    PopUpPreview popUpPreview = popupPreviewPool.getInstance(keyEventContext.pointerId);
    // Even if popup is disabled by preference, delayed popup (== popup for long-press)
    // is shown otherwise a user cannot know how long (s)he has to press the key
    // to get a character corresponding to long-press.
    if (popupEnabled || isDelayedPopUp) {
      popUpPreview.showIfNecessary(
          keyEventContext.key, keyEventContext.getCurrentPopUp(), isDelayedPopUp);
    } else {
      popUpPreview.dismiss();
    }
  }
}
