// 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.keyboard;

import static org.easymock.EasyMock.capture;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.isA;
import static org.easymock.EasyMock.same;

import org.mozc.android.inputmethod.japanese.MozcUtil;
import org.mozc.android.inputmethod.japanese.keyboard.BackgroundDrawableFactory.DrawableType;
import org.mozc.android.inputmethod.japanese.keyboard.Flick.Direction;
import org.mozc.android.inputmethod.japanese.keyboard.Key.Stick;
import org.mozc.android.inputmethod.japanese.keyboard.KeyState.MetaState;
import org.mozc.android.inputmethod.japanese.keyboard.Keyboard.KeyboardSpecification;
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.testing.InstrumentationTestCaseWithMock;
import org.mozc.android.inputmethod.japanese.testing.MockResourcesWithDisplayMetrics;
import org.mozc.android.inputmethod.japanese.testing.Parameter;
import org.mozc.android.inputmethod.japanese.testing.VisibilityProxy;
import org.mozc.android.inputmethod.japanese.view.DrawableCache;
import org.mozc.android.inputmethod.japanese.view.SkinType;
import com.google.common.base.Optional;

import android.content.res.Resources;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Looper;
import android.test.mock.MockResources;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.InputType;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;

import org.easymock.Capture;
import org.easymock.EasyMock;
import org.easymock.IAnswer;

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

/**
 * Unit tests for {@code org.mozc.android.inputmethod.japanese.keyboard.KeyboardView}.
 */
public class KeyboardViewTest extends InstrumentationTestCaseWithMock {

  /**
   * The number of steps of a drag path.
   */
  private static final int STEP_COUNT = 20;

  // The following are parameters of a dummy key.
  private static final int WIDTH = 50;
  private static final int HEIGHT = 30;
  private static final int HORIZONTAL_GAP = 0;
  private static final int VERTICAL_GAP = 0;

  private KeyboardView view;

  private static boolean touchEvent(KeyboardView view, int action, int x, int y) {
    return touchEvent(view, 0, 0, action, x, y);
  }

  private static boolean touchEvent(
      KeyboardView view, long downTime, long eventTime, int action, int x, int y) {
    MotionEvent e = MotionEvent.obtain(downTime, eventTime, action, x, y, 0);
    try {
      return view.onTouchEvent(e);
    } finally {
      e.recycle();
    }
  }

  /** Emulates dragging from @{code (fromX, fromY)} to @{code (toX, toY)}. */
  private static boolean drag(KeyboardView view, int fromX, int toX, int fromY, int toY) {
    long downTime = MozcUtil.getUptimeMillis();

    boolean result = true;
    result &= touchEvent(view, downTime, downTime, MotionEvent.ACTION_DOWN, fromX, fromY);

    for (int i = 0; i < STEP_COUNT; ++i) {
      int x = fromX + (toX - fromX) * i / STEP_COUNT;
      int y = fromY + (toY - fromY) * i / STEP_COUNT;

      long eventTime = MozcUtil.getUptimeMillis();
      result &= touchEvent(view, downTime, eventTime, MotionEvent.ACTION_MOVE, x, y);
    }

    long eventTime = MozcUtil.getUptimeMillis();
    result &= touchEvent(view, downTime, eventTime, MotionEvent.ACTION_UP, toX, toY);
    return result;
  }

  private static KeyEntity createInvalidKeyEntity(int sourceId, int keyCode) {
    return new KeyEntity(
        sourceId, keyCode, KeyEntity.INVALID_KEY_CODE, true, 0,
        Optional.<String>absent(), false, Optional.<PopUp>absent(), 0, 0, 0, 0);
  }

  private static KeyState createKeyStateWithKeyEntity(
      Set<MetaState> metaState, KeyEntity keyEntity) {
    Flick flick = new Flick(Flick.Direction.CENTER, keyEntity);
    return new KeyState(
        "",
        metaState,
        Collections.<MetaState>emptySet(),
        Collections.<MetaState>emptySet(),
        Collections.singletonList(flick));
  }

  private static KeyState createKeyState(Set<MetaState> metaState, int keyCode) {
    return createKeyStateWithKeyEntity(metaState, createInvalidKeyEntity(1, keyCode));
  }

  private static Key createKey(int x, int y, int keyCode) {
    return new Key(
        x, y, WIDTH, HEIGHT, HORIZONTAL_GAP, 0, false, false, Stick.EVEN,
        DrawableType.TWELVEKEYS_REGULAR_KEY_BACKGROUND,
        Collections.singletonList(createKeyState(Collections.<MetaState>emptySet(), keyCode)));
  }

  private static Key createKeyWithKeyEntity(int x, int y, KeyEntity keyEntity) {
    return new Key(
        x, y, WIDTH, HEIGHT, HORIZONTAL_GAP, 0, false, false, Stick.EVEN,
        DrawableType.TWELVEKEYS_REGULAR_KEY_BACKGROUND,
        Collections.singletonList(
            createKeyStateWithKeyEntity(Collections.<MetaState>emptySet(), keyEntity)));
  }

  private static Key createSpacer(int x, int y, Stick stick) {
    return new Key(
        x, y, WIDTH, HEIGHT, HORIZONTAL_GAP, 0, false, false, stick,
        DrawableType.TWELVEKEYS_REGULAR_KEY_BACKGROUND,
        Collections.<KeyState>emptyList());
  }

  private static Key createKeyWithModifiedState(int x, int y, int keyCode, int modifiedKeyCode) {
    return new Key(
        x, y, WIDTH, HEIGHT, HORIZONTAL_GAP, 0, false, false, Stick.EVEN,
        DrawableType.TWELVEKEYS_REGULAR_KEY_BACKGROUND,
        Arrays.asList(createKeyState(Collections.<MetaState>emptySet(), keyCode),
                      createKeyState(EnumSet.of(MetaState.CAPS_LOCK), modifiedKeyCode)));
  }

  private static Key createFlickKey(
      int x, int y,
      int centerKeyCode, int leftKeyCode, int rightKeyCode, int upKeyCode, int downKeyCode) {
    Flick center = new Flick(Flick.Direction.CENTER, createInvalidKeyEntity(1, centerKeyCode));
    Flick left = new Flick(Flick.Direction.LEFT, createInvalidKeyEntity(1, leftKeyCode));
    Flick right = new Flick(Flick.Direction.RIGHT, createInvalidKeyEntity(1, rightKeyCode));
    Flick up = new Flick(Flick.Direction.UP, createInvalidKeyEntity(1, upKeyCode));
    Flick down = new Flick(Flick.Direction.DOWN, createInvalidKeyEntity(1, downKeyCode));
    KeyState keyState = new KeyState(
        "",
        Collections.<MetaState>emptySet(),
        Collections.<MetaState>emptySet(),
        Collections.<MetaState>emptySet(),
        Arrays.asList(center, left, right, up, down));
    return new Key(x, y, WIDTH, HEIGHT, HORIZONTAL_GAP, 0, false, false, Stick.EVEN,
                   DrawableType.TWELVEKEYS_REGULAR_KEY_BACKGROUND,
                   Collections.singletonList(keyState));
  }

  private static Key createModifierKey(int x, int y, int keyCode, Set<MetaState> nextAddMetaStates,
                                       Set<MetaState> nextRemoveMetaStates) {
    KeyEntity entity = createInvalidKeyEntity(1, keyCode);
    Flick flick = new Flick(Flick.Direction.CENTER, entity);
    KeyState keyState = new KeyState(
        "",
        Collections.<MetaState>emptySet(),
        nextAddMetaStates,
        nextRemoveMetaStates,
        Collections.singletonList(flick));
    return new Key(x, y, WIDTH, HEIGHT, HORIZONTAL_GAP, 0, false, true, Stick.EVEN,
                   DrawableType.TWELVEKEYS_REGULAR_KEY_BACKGROUND,
                   Collections.singletonList(keyState));
  }

  /**
   * Creates a dummy keyboard which has only {@code key}.
   * @return a new dummy keyboard.
   */
  private static Keyboard createDummyKeyboard(Key key) {
    Row row = new Row(Collections.singletonList(key), HEIGHT, VERTICAL_GAP);
    return new Keyboard(Optional.<String>absent(), Collections.singletonList(row), 1,
                        KeyboardSpecification.TWELVE_KEY_TOGGLE_FLICK_KANA);
  }

  private KeyEventHandler createKeyEventHandlerMock() {
    KeyboardActionListener keyboardActionListener = createNiceMock(KeyboardActionListener.class);
    return createMockBuilder(KeyEventHandler.class)
        .withConstructor(Looper.class, KeyboardActionListener.class,
                         int.class, int.class, int.class)
        .withArgs(Looper.myLooper(), keyboardActionListener, 0, 0, 0)
        .createMock();
  }

  private KeyboardViewBackgroundSurface createKeyboardViewBackgroundSurfaceMock() {
    return createMockBuilder(KeyboardViewBackgroundSurface.class)
        .withConstructor(BackgroundDrawableFactory.class, DrawableCache.class)
        .withArgs(new BackgroundDrawableFactory(new MockResourcesWithDisplayMetrics()),
                  new DrawableCache(getInstrumentation().getContext().getResources()))
        .createMock();
  }

  @Override
  public void setUp() throws Exception {
    super.setUp();

    view = new KeyboardView(getInstrumentation().getTargetContext());
    view.setKeyboard(createDummyKeyboard(createKey(0, 0, 'a')));
    view.layout(0, 0, 100, 60);
  }

  @Override
  public void tearDown() throws Exception {
    view = null;
    super.tearDown();
  }

  @SmallTest
  public void testFlushPendingKeyEventRecursiveCall() {
    Key targetKey = view.getKeyboard().get().getRowList().get(0).getKeyList().get(0);
    KeyEventContext keyEventContext =
        new KeyEventContext(targetKey, 0, 0, 0, 100, 60, 1, Collections.<MetaState>emptySet());

    KeyEventHandler keyEventHandler = createKeyEventHandlerMock();
    keyEventHandler.cancelDelayedKeyEvent(keyEventContext);
    keyEventHandler.sendKey(
        keyEventContext.getKeyCode(),
        Collections.singletonList(keyEventContext.getTouchEvent().get()));
    expectLastCall().andAnswer(new IAnswer<Void>() {
      @Override
      public Void answer() throws Throwable {
        // Set Keyboard in this callback which invokes flushPendingKeyEvent again.
        Key key = createKeyWithModifiedState(0, 0, 'a', 'A');
        view.setKeyboard(createDummyKeyboard(key));
        return null;
      }
    });
    keyEventHandler.sendRelease(keyEventContext.getPressedKeyCode());
    replayAll();

    view.setKeyEventHandler(keyEventHandler);

    // Set pressed condition.
    view.metaState = EnumSet.of(MetaState.CAPS_LOCK);
    Map<Integer, KeyEventContext> keyEventContextMap = view.keyEventContextMap;
    keyEventContextMap.put(0, keyEventContext);

    Key key = createKeyWithModifiedState(0, 0, 'a', 'A');
    view.setKeyboard(createDummyKeyboard(key));

    verifyAll();
  }

  @SmallTest
  public void testOnTouchEvent_press() {
    KeyEventHandler keyEventHandler = createKeyEventHandlerMock();
    keyEventHandler.cancelDelayedKeyEvent(isA(KeyEventContext.class));
    expectLastCall().anyTimes();
    keyEventHandler.maybeStartDelayedKeyEvent(isA(KeyEventContext.class));
    keyEventHandler.sendPress('a');
    replayAll();

    view.setKeyEventHandler(keyEventHandler);

    // By pressing a key, internal pressedKey field should be filled.
    Map<Integer, KeyEventContext> keyEventContextMap = view.keyEventContextMap;
    assertTrue(keyEventContextMap.isEmpty());
    assertTrue(touchEvent(view, MotionEvent.ACTION_DOWN, 25, 15));

    verifyAll();
    assertEquals(1, keyEventContextMap.size());
    assertEquals(Flick.Direction.CENTER,
                 keyEventContextMap.values().iterator().next().flickDirection);
    assertTrue(view.isKeyPressed);
  }

  @SmallTest
  public void testOnTouchEvent_pressModified() {
    KeyEventHandler keyEventHandler = createKeyEventHandlerMock();
    keyEventHandler.cancelDelayedKeyEvent(isA(KeyEventContext.class));
    expectLastCall().anyTimes();
    keyEventHandler.maybeStartDelayedKeyEvent(isA(KeyEventContext.class));
    keyEventHandler.sendPress('A');
    replayAll();

    view.setKeyEventHandler(keyEventHandler);

    Key key = createKeyWithModifiedState(0, 0, 'a', 'A');
    view.setKeyboard(createDummyKeyboard(key));

    // Set modified state.
    view.metaState = EnumSet.of(MetaState.CAPS_LOCK);

    // By pressing a key, internal pressedKey field should be filled.
    Map<Integer, KeyEventContext> keyEventContextMap = view.keyEventContextMap;
    assertTrue(keyEventContextMap.isEmpty());
    assertTrue(touchEvent(view, MotionEvent.ACTION_DOWN, 25, 15));

    verifyAll();
    assertEquals(1, keyEventContextMap.size());
    assertEquals(Flick.Direction.CENTER,
                 keyEventContextMap.values().iterator().next().flickDirection);
  }

  @SmallTest
  public void testOnTouchEvent_pressModifier() {
    KeyEventHandler keyEventHandler = createKeyEventHandlerMock();
    keyEventHandler.cancelDelayedKeyEvent(isA(KeyEventContext.class));
    expectLastCall().anyTimes();
    keyEventHandler.sendKey(
        'a',
        Arrays.asList(
            // A TouchEvent for the modifier Key.
            TouchEvent.newBuilder()
                .setSourceId(1)
                .addStroke(KeyEventContext.createTouchPosition(
                    TouchAction.TOUCH_DOWN, 25, 15, 100, 60, 0))
                .build(),
            // A TouchEvent for 'a' key.
            TouchEvent.newBuilder()
                .setSourceId(1)
                .addStroke(KeyEventContext.createTouchPosition(
                    TouchAction.TOUCH_DOWN, 100, 60, 100, 60, 0))
                .build()));
    keyEventHandler.sendRelease('a');
    keyEventHandler.maybeStartDelayedKeyEvent(isA(KeyEventContext.class));
    keyEventHandler.sendPress(-1);
    replayAll();
    view.setKeyEventHandler(keyEventHandler);

    view.setKeyboard(createDummyKeyboard(
        createModifierKey(0, 0, -1, EnumSet.of(MetaState.CAPS_LOCK),
                          EnumSet.of(MetaState.SHIFT))));

    // Set modified state.
    view.metaState = EnumSet.of(MetaState.SHIFT);

    KeyEventContext pendingKeyEventContext =
        new KeyEventContext(createKey(0, 0, 'a'), 1, 100, 60, 100, 60, 0,
                            Collections.<MetaState>emptySet());
    // By pressing a key, the pending events should be flushed and
    // the metaState should be updated.
    Map<Integer, KeyEventContext> keyEventContextMap = view.keyEventContextMap;
    keyEventContextMap.put(1, pendingKeyEventContext);
    assertTrue(touchEvent(view, MotionEvent.ACTION_DOWN, 25, 15));

    verifyAll();
    assertEquals(1, keyEventContextMap.size());
    assertEquals(EnumSet.of(MetaState.CAPS_LOCK, MetaState.HANDLING_TOUCH_EVENT), view.metaState);
  }

  @SmallTest
  public void testOnTouchEvent_pressOutside() {
    KeyEventHandler keyEventHandler = createKeyEventHandlerMock();
    replayAll();
    view.setKeyEventHandler(keyEventHandler);

    // Pressing non-key region shouldn't cause filling the pressedKey.
    Map<Integer, KeyEventContext> keyEventContextMap = view.keyEventContextMap;
    assertTrue(keyEventContextMap.isEmpty());
    assertTrue(touchEvent(view, MotionEvent.ACTION_DOWN, 100, -100));

    verifyAll();
    assertTrue(keyEventContextMap.isEmpty());
  }

  @SmallTest
  public void testOnTouchEvent_pressBelowOutside() {
    KeyEventHandler keyEventHandler = createKeyEventHandlerMock();
    keyEventHandler.cancelDelayedKeyEvent(isA(KeyEventContext.class));
    expectLastCall().anyTimes();
    keyEventHandler.maybeStartDelayedKeyEvent(isA(KeyEventContext.class));
    keyEventHandler.sendPress('a');
    replayAll();
    view.setKeyEventHandler(keyEventHandler);

    Map<Integer, KeyEventContext> keyEventContextMap = view.keyEventContextMap;
    assertTrue(keyEventContextMap.isEmpty());
    assertTrue(touchEvent(view, MotionEvent.ACTION_DOWN, 100, 100));

    verifyAll();
    assertEquals(1, keyEventContextMap.size());
    assertEquals(Flick.Direction.CENTER,
                 keyEventContextMap.values().iterator().next().flickDirection);
    assertTrue(view.isKeyPressed);
  }

  @SmallTest
  public void testOnTouchEvent_release() {
    Key targetKey = view.getKeyboard().get().getRowList().get(0).getKeyList().get(0);
    KeyEventContext keyEventContext =
        new KeyEventContext(targetKey, 0, 0, 0, 100, 60, 1, Collections.<MetaState>emptySet());

    KeyEventHandler keyEventHandler = createKeyEventHandlerMock();
    // The listener should receive two events.
    // - onKey event with 'a' code.
    // - onRelease event with 'a' code.
    // in this order.
    keyEventHandler.cancelDelayedKeyEvent(keyEventContext);
    keyEventHandler.sendKey(
        'a',
        Collections.singletonList(TouchEvent.newBuilder()
            .setSourceId(1)
            .addStroke(KeyEventContext.createTouchPosition(
                TouchAction.TOUCH_DOWN, 0, 0, 100, 60, 0))
            .addStroke(KeyEventContext.createTouchPosition(
                TouchAction.TOUCH_UP, 25, 15, 100, 60, 0))
            .build()));
    keyEventHandler.sendRelease('a');
    replayAll();
    view.setKeyEventHandler(keyEventHandler);

    // Set pressed condition.
    Map<Integer, KeyEventContext> keyEventContextMap = view.keyEventContextMap;
    keyEventContextMap.put(0, keyEventContext);

    assertEquals(Flick.Direction.CENTER,
                 keyEventContextMap.values().iterator().next().flickDirection);
    assertTrue(touchEvent(view, MotionEvent.ACTION_UP, 25, 15));

    verifyAll();
    assertTrue(keyEventContextMap.isEmpty());
  }

  @SmallTest
  public void testOnTouchEvent_releaseInvalidKey() {
    class TestData extends Parameter {
      private final Key key;
      private final int deltaX;
      private final int deltaY;
      TestData(Key key, int deltaX, int deltaY) {
        this.key = key;
        this.deltaX = deltaX;
        this.deltaY = deltaY;
      }
    }

    // Center is valid, but other dictions are invalid.
    Key validCenter = createFlickKey(0, 0, 'a',
                                     KeyEntity.INVALID_KEY_CODE,
                                     KeyEntity.INVALID_KEY_CODE,
                                     KeyEntity.INVALID_KEY_CODE,
                                     KeyEntity.INVALID_KEY_CODE);

    int delta = 100;
    TestData[] testDataList = {
        new TestData(createKey(0, 0, KeyEntity.INVALID_KEY_CODE), 0, 0),
        // Try four directions, which are assigned INVALID_KEY_CODE.
        new TestData(validCenter, -delta, 0),
        new TestData(validCenter, +delta, 0),
        new TestData(validCenter, 0, -delta),
        new TestData(validCenter, 0, +delta),
    };

    for (TestData testData : testDataList) {
      resetAll();

      // Prepare a keyboard having a key with invalid key code.
      KeyboardView view = new KeyboardView(getInstrumentation().getTargetContext());
      view.setKeyboard(createDummyKeyboard(testData.key));
      view.layout(0, 0, 100, 60);

      Key targetKey = view.getKeyboard().get().getRowList().get(0).getKeyList().get(0);
      KeyEventContext keyEventContext =
          new KeyEventContext(targetKey, 0, 0, 0, 100, 60, 1, Collections.<MetaState>emptySet());

      KeyEventHandler keyEventHandler = createKeyEventHandlerMock();
      // cancelDelayedKeyEvent is called by each MOVE event.
      keyEventHandler.cancelDelayedKeyEvent(keyEventContext);
      expectLastCall().asStub();
      // Pay no attention the parameter of sendRelease.
      keyEventHandler.sendRelease(EasyMock.anyInt());
      // The handler's sendKey shouldn't be sent.
      replayAll();

      view.setKeyEventHandler(keyEventHandler);

      // Set pressed condition.
      Map<Integer, KeyEventContext> keyEventContextMap = view.keyEventContextMap;
      keyEventContextMap.put(0, keyEventContext);

      int startX = 25;
      int startY = 15;
      assertTrue(testData.toString(),
                 drag(view, startX, startX + testData.deltaX, startY, startY + testData.deltaY));

      verifyAll();
      assertTrue(testData.toString(), keyEventContextMap.isEmpty());
    }
  }

  @SmallTest
  public void testOnTouchEvent_releaseModified() {
    Key key = createKeyWithModifiedState(0, 0, 'a', 'A');
    view.setKeyboard(createDummyKeyboard(key));
    Key targetKey = view.getKeyboard().get().getRowList().get(0).getKeyList().get(0);
    KeyEventContext keyEventContext =
        new KeyEventContext(targetKey, 0, 0, 0, 100, 60, 1, EnumSet.of(MetaState.CAPS_LOCK));

    KeyEventHandler keyEventHandler = createKeyEventHandlerMock();
    // The listener should receive two events.
    // - onKey event with 'A' code.
    // - onRelease event with 'A' code.
    // in this order.
    keyEventHandler.cancelDelayedKeyEvent(keyEventContext);
    keyEventHandler.sendKey(
        'A',
        Collections.singletonList(TouchEvent.newBuilder()
            .setSourceId(1)
            .addStroke(KeyEventContext.createTouchPosition(
                TouchAction.TOUCH_DOWN, 0, 0, 100, 60, 0))
            .addStroke(KeyEventContext.createTouchPosition(
                TouchAction.TOUCH_UP, 25, 15, 100, 60, 0))
            .build()));
    keyEventHandler.sendRelease('A');
    replayAll();
    view.setKeyEventHandler(keyEventHandler);

    // Set pressed condition.
    view.metaState = EnumSet.of(MetaState.CAPS_LOCK);
    Map<Integer, KeyEventContext> keyEventContextMap = view.keyEventContextMap;
    keyEventContextMap.put(0, keyEventContext);

    assertTrue(touchEvent(view, MotionEvent.ACTION_UP, 25, 15));

    verifyAll();
    assertTrue(keyEventContextMap.isEmpty());
    assertEquals(EnumSet.of(MetaState.CAPS_LOCK), view.metaState);
  }

  @SmallTest
  public void testOnTouchEvent_releaseModifierSimple() {
    Key key = createModifierKey(0, 0, -1, EnumSet.of(MetaState.SHIFT),
                                Collections.<MetaState>emptySet());
    view.setKeyboard(createDummyKeyboard(key));

    KeyEventContext keyEventContext =
        new KeyEventContext(key, 0, 0, 0, 100, 60, 1, Collections.<MetaState>emptySet());

    KeyEventHandler keyEventHandler = createKeyEventHandlerMock();
    keyEventHandler.cancelDelayedKeyEvent(keyEventContext);
    keyEventHandler.sendKey(
        -1,
        Collections.singletonList(TouchEvent.newBuilder()
            .setSourceId(1)
            .addStroke(KeyEventContext.createTouchPosition(
                TouchAction.TOUCH_DOWN, 0, 0, 100, 60, 0))
            .addStroke(KeyEventContext.createTouchPosition(
                TouchAction.TOUCH_UP, 25, 15, 100, 60, 0))
            .build()));
    keyEventHandler.sendRelease(-1);
    replayAll();
    view.setKeyEventHandler(keyEventHandler);

    // Set pressed condition.
    view.metaState = EnumSet.of(MetaState.SHIFT);
    Map<Integer, KeyEventContext> keyEventContextMap = view.keyEventContextMap;
    view.isKeyPressed = false;
    keyEventContextMap.put(0, keyEventContext);

    assertTrue(touchEvent(view, MotionEvent.ACTION_UP, 25, 15));

    verifyAll();
    assertTrue(keyEventContextMap.isEmpty());
    // Simple releasing a modifier key shouldn't change the metaState.
    assertEquals(EnumSet.of(MetaState.SHIFT), view.metaState);
  }

  @SmallTest
  public void testOnTouchEvent_releaseModifierWithOtherKey() {
    Key key = createModifierKey(0, 0, -1, EnumSet.of(MetaState.SHIFT),
                                Collections.<MetaState>emptySet());
    view.setKeyboard(createDummyKeyboard(key));

    KeyEventContext keyEventContext =
        new KeyEventContext(key, 0, 0, 0, 100, 60, 1, Collections.<MetaState>emptySet());

    // Another key event context for 'a' key.
    KeyEventContext keyEventContext2 =
        new KeyEventContext(createKey(0, 0, 'a'), 0, 0, 0, 100, 60, 1,
                            EnumSet.of(MetaState.SHIFT));

    KeyEventHandler keyEventHandler = createKeyEventHandlerMock();
    // The listener should receive two events.
    // - onKey event with 'A' code.
    // - onRelease event with 'A' code.
    // in this order.
    keyEventHandler.cancelDelayedKeyEvent(keyEventContext2);
    keyEventHandler.sendKey(
        'a',
        Arrays.asList(
            // A TouchEvent for the SHIFT key.
            TouchEvent.newBuilder()
                .setSourceId(1)
                .addStroke(KeyEventContext.createTouchPosition(
                    TouchAction.TOUCH_DOWN, 0, 0, 100, 60, 0))
                .addStroke(KeyEventContext.createTouchPosition(
                    TouchAction.TOUCH_UP, 25, 15, 100, 60, 0))
                .build(),
            // A TouchEvent for 'a' key.
            TouchEvent.newBuilder()
                .setSourceId(1)
                .addStroke(KeyEventContext.createTouchPosition(
                    TouchAction.TOUCH_DOWN, 0, 0, 100, 60, 0))
                .build()));
    keyEventHandler.sendRelease('a');
    keyEventHandler.cancelDelayedKeyEvent(keyEventContext);
    keyEventHandler.sendKey(
        -1,
        Collections.singletonList(TouchEvent.newBuilder()
            .setSourceId(1)
            .addStroke(KeyEventContext.createTouchPosition(
                TouchAction.TOUCH_DOWN, 0, 0, 100, 60, 0))
            .addStroke(KeyEventContext.createTouchPosition(
                TouchAction.TOUCH_UP, 25, 15, 100, 60, 0))
            .build()));
    keyEventHandler.sendRelease(-1);
    replayAll();
    view.setKeyEventHandler(keyEventHandler);

    // Set pressed condition.
    view.metaState = EnumSet.of(MetaState.SHIFT);
    Map<Integer, KeyEventContext> keyEventContextMap = view.keyEventContextMap;
    keyEventContextMap.put(0, keyEventContext);
    keyEventContextMap.put(1, keyEventContext2);
    view.isKeyPressed = true;

    assertTrue(touchEvent(view, MotionEvent.ACTION_UP, 25, 15));

    verifyAll();
    assertTrue(keyEventContextMap.isEmpty());
    // Simple releasing a modifier key shouldn't change the metaState.
    assertTrue(view.metaState.isEmpty());
  }

  @SmallTest
  public void testOnTouchEvent_releaseModifierOneTime() {
    Key targetKey = view.getKeyboard().get().getRowList().get(0).getKeyList().get(0);
    KeyEventContext keyEventContext =
        new KeyEventContext(targetKey, 0, 0, 0, 100, 60, 1, Collections.<MetaState>emptySet());

    KeyEventHandler keyEventHandler = createKeyEventHandlerMock();
    keyEventHandler.cancelDelayedKeyEvent(keyEventContext);
    keyEventHandler.sendKey(
        'a',
        Collections.singletonList(TouchEvent.newBuilder()
            .setSourceId(1)
            .addStroke(KeyEventContext.createTouchPosition(
                TouchAction.TOUCH_DOWN, 0, 0, 100, 60, 0))
            .addStroke(KeyEventContext.createTouchPosition(
                TouchAction.TOUCH_UP, 25, 15, 100, 60, 0))
            .build()));
    keyEventHandler.sendRelease('a');
    replayAll();
    view.setKeyEventHandler(keyEventHandler);

    // Set pressed condition.
    view.metaState = EnumSet.of(MetaState.SHIFT);
    Map<Integer, KeyEventContext> keyEventContextMap = view.keyEventContextMap;
    keyEventContextMap.put(0, keyEventContext);

    assertTrue(touchEvent(view, MotionEvent.ACTION_UP, 25, 15));

    verifyAll();
    assertTrue(keyEventContextMap.isEmpty());
    // Simple releasing a modifier key shouldn't change the metaState.
    assertTrue(view.metaState.isEmpty());
  }

  @SmallTest
  public void testOnTouchEvent_move() {
    // Moving events shouldn't trigger the listener, except canceling the delayed key event.
    KeyEventHandler keyEventHandler = createKeyEventHandlerMock();
    keyEventHandler.cancelDelayedKeyEvent(isA(KeyEventContext.class));
    expectLastCall().anyTimes();
    replayAll();

    // Following code emulates:
    // - press the center of the key
    // - move to up, which will make internal flickState to UP
    // - move to left, which will make internal flickState to LEFT
    // - move to down, which will make internal flickState to DOWN
    // - move to right, which will make internal flickState to RIGHT
    // - and, move back to the key, which will make internal flickState to CENTER.
    Map<Integer, KeyEventContext> keyEventContextMap = view.keyEventContextMap;
    assertTrue(keyEventContextMap.isEmpty());

    assertTrue(touchEvent(view, MotionEvent.ACTION_DOWN, 25, 15));
    assertEquals(1, keyEventContextMap.size());
    assertEquals(Flick.Direction.CENTER,
                 keyEventContextMap.values().iterator().next().flickDirection);

    view.setKeyEventHandler(keyEventHandler);

    assertTrue(touchEvent(view, MotionEvent.ACTION_MOVE, 25, -85));
    assertEquals(1, keyEventContextMap.size());
    assertEquals(Flick.Direction.UP,
                 keyEventContextMap.values().iterator().next().flickDirection);

    assertTrue(touchEvent(view, MotionEvent.ACTION_MOVE, -75, 15));
    assertEquals(1, keyEventContextMap.size());
    assertEquals(Flick.Direction.LEFT,
                 keyEventContextMap.values().iterator().next().flickDirection);

    assertTrue(touchEvent(view, MotionEvent.ACTION_MOVE, 25, 115));
    assertEquals(1, keyEventContextMap.size());
    assertEquals(Flick.Direction.DOWN,
                 keyEventContextMap.values().iterator().next().flickDirection);

    assertTrue(touchEvent(view, MotionEvent.ACTION_MOVE, 125, 15));
    assertEquals(1, keyEventContextMap.size());
    assertEquals(Flick.Direction.RIGHT,
                 keyEventContextMap.values().iterator().next().flickDirection);

    verifyAll();

    resetAll();
    keyEventHandler.cancelDelayedKeyEvent(isA(KeyEventContext.class));
    expectLastCall().anyTimes();
    // Delayed key event is invoked since the next flick direction is CENTER.
    keyEventHandler.maybeStartDelayedKeyEvent(isA(KeyEventContext.class));
    replayAll();

    assertTrue(touchEvent(view, MotionEvent.ACTION_MOVE, 25, 15));
    assertEquals(1, keyEventContextMap.size());
    assertEquals(Flick.Direction.CENTER,
                 keyEventContextMap.values().iterator().next().flickDirection);

    verifyAll();
  }

  @SmallTest
  public void testOnTouchEvent_cancel() {
    Key targetKey = view.getKeyboard().get().getRowList().get(0).getKeyList().get(0);
    KeyEventContext eventContext =
        new KeyEventContext(targetKey, 0, 0, 0, 100, 60, 1, Collections.<MetaState>emptySet());

    KeyEventHandler keyEventHandler = createKeyEventHandlerMock();
    keyEventHandler.cancelDelayedKeyEvent(same(eventContext));
    keyEventHandler.sendCancel();
    replayAll();

    view.setKeyEventHandler(keyEventHandler);

    // Set pressed condition.
    Map<Integer, KeyEventContext> keyEventContextMap = view.keyEventContextMap;
    keyEventContextMap.put(0, eventContext);

    assertTrue(touchEvent(view, MotionEvent.ACTION_CANCEL, 25, 15));
    assertTrue(keyEventContextMap.isEmpty());

    verifyAll();
  }

  @SmallTest
  public void testFlick() {
    view.setKeyboard(createDummyKeyboard(createFlickKey(0, 0, 'a', 'b', 'c', 'd', 'e')));

    view.layout(0, 0, 50, 30);

    int fromX = view.getWidth() / 2;
    int fromY = view.getHeight() / 2;

    class TestData {
      final int toX;
      final int toY;
      final int expectedCode;
      TestData(int toX, int toY, int expectedCode) {
        this.toX = toX;
        this.toY = toY;
        this.expectedCode = expectedCode;
      }
    }
    TestData[] testCases = {
        new TestData(fromX - 75, fromY, 'b'),  // Left
        new TestData(fromX + 75, fromY, 'c'),  // Right
        new TestData(fromX, fromY - 75, 'd'),  // Up
        new TestData(fromX, fromY + 75, 'e'),  // Down
    };

    KeyboardActionListener keyboardActionListener = createStrictMock(KeyboardActionListener.class);
    for (TestData testCase : testCases) {
      resetAll();
      keyboardActionListener.onPress('a');
      keyboardActionListener.onKey(
          eq(testCase.expectedCode), EasyMock.<List<TouchEvent>>notNull());
      keyboardActionListener.onRelease('a');
      replayAll();

      KeyEventHandler keyEventHandler =
          new KeyEventHandler(Looper.myLooper(), keyboardActionListener, 0, 0, 0);

      view.setKeyEventHandler(keyEventHandler);

      assertTrue(view.keyEventContextMap.isEmpty());
      assertTrue(drag(view, fromX, testCase.toX, fromY, testCase.toY));
      assertTrue(view.keyEventContextMap.isEmpty());

      verifyAll();
    }
  }

  @SmallTest
  public void testFlickSensitivity() {
    view.setKeyboard(createDummyKeyboard(createFlickKey(0, 0, 'a', 'b', 'c', 'd', 'e')));
    view.layout(0, 0, 50, 30);

    Map<Integer, KeyEventContext> keyEventContextMap = view.keyEventContextMap;

    int fromX = view.getWidth() / 2;
    int fromY = view.getHeight() / 2;

    view.setFlickSensitivity(-10);
    assertTrue(touchEvent(view, MotionEvent.ACTION_DOWN, fromX, fromY));
    float threshold1 = keyEventContextMap.values().iterator().next().getFlickThresholdSquared();

    view.resetState();
    view.setFlickSensitivity(0);
    assertTrue(touchEvent(view, MotionEvent.ACTION_DOWN, fromX, fromY));
    float threshold2 = keyEventContextMap.values().iterator().next().getFlickThresholdSquared();

    view.resetState();
    view.setFlickSensitivity(10);
    assertTrue(touchEvent(view, MotionEvent.ACTION_DOWN, fromX, fromY));
    float threshold3 = keyEventContextMap.values().iterator().next().getFlickThresholdSquared();

    assertTrue(0 < threshold3);
    assertTrue(threshold3 <= threshold2);
    assertTrue(threshold2 <= threshold1);
  }

  @SmallTest
  public void testPopUp() {
    final Drawable icon = new ColorDrawable();
    final Drawable flickIcon = new ColorDrawable();
    final int invalidResourceId = 0;
    final int iconResourceId = 1;
    final int flickIconResourceId = 3;

    PopUp popup = new PopUp(iconResourceId, invalidResourceId, 40, 0, -30, 10, 10);
    PopUp flickPopup = new PopUp(flickIconResourceId, invalidResourceId, 40, 0, -30, 10, 10);

    // Inject drawables as resources.
    Resources mockResources = new MockResourcesWithDisplayMetrics() {
      @Override
      public Drawable getDrawable(int resourceId) {
        if (resourceId == iconResourceId) {
          return icon;
        }
        if (resourceId == flickIconResourceId) {
          return flickIcon;
        }
        return null;
      }
    };
    DrawableCache drawableCache = new DrawableCache(mockResources);
    VisibilityProxy.setField(view, "drawableCache", drawableCache);

    int x1 = 0;
    int x2 = WIDTH + HORIZONTAL_GAP;
    int x3 = (WIDTH + HORIZONTAL_GAP) * 2;
    int y1 = 0;
    int y2 = HEIGHT + VERTICAL_GAP;
    int y3 = (HEIGHT + VERTICAL_GAP) * 2;

    Key popupKey = new Key(
        x2, y2,
        WIDTH, HEIGHT, HORIZONTAL_GAP, 0, false, false, Stick.EVEN,
        DrawableType.TWELVEKEYS_REGULAR_KEY_BACKGROUND,
        Collections.singletonList(new KeyState(
            "",
            Collections.<MetaState>emptySet(),
            Collections.<MetaState>emptySet(),
            Collections.<MetaState>emptySet(),
            Arrays.asList(
                new Flick(
                    Direction.CENTER,
                    new KeyEntity(
                        1, 'a', KeyEntity.INVALID_KEY_CODE, true, 0,
                        Optional.<String>absent(), false, Optional.of(popup), 0, 0, 0, 0)),
                new Flick(
                    Direction.LEFT,
                    new KeyEntity(
                        2, 'b', KeyEntity.INVALID_KEY_CODE, true, 0,
                        Optional.<String>absent(), false, Optional.of(flickPopup), 0, 0, 0, 0))))));

    Row row1 = new Row(
        Arrays.asList(createKey(x1, y1, 'c'), createKey(x2, y1, 'd'), createKey(x3, y1, 'e')),
        HEIGHT, VERTICAL_GAP);
    Row row2 = new Row(
        Arrays.asList(createKey(x1, y2, 'f'), popupKey, createKey(x3, y2, 'g')),
        HEIGHT, VERTICAL_GAP);
    Row row3 = new Row(
        Arrays.asList(createKey(x1, y3, 'h'), createKey(x2, y3, 'i'), createKey(x3, y3, 'j')),
        HEIGHT, VERTICAL_GAP);
    Keyboard keyboard = new Keyboard(Optional.<String>absent(),
                                     Arrays.asList(row1, row2, row3), 1,
                                     KeyboardSpecification.TWELVE_KEY_TOGGLE_FLICK_KANA);
    view.setKeyboard(keyboard);

    // Set mock preview.
    PopUpPreview mockPopUpPreview = createMockBuilder(PopUpPreview.class)
        .withConstructor(View.class, BackgroundDrawableFactory.class, DrawableCache.class)
        .withArgs(view, new BackgroundDrawableFactory(new MockResourcesWithDisplayMetrics()),
                                                      drawableCache)
        .createMock();
    PopUpPreview.Pool popupPreviewPool = VisibilityProxy.getField(view, "popupPreviewPool");
    VisibilityProxy.<List<PopUpPreview>>getField(
        popupPreviewPool, "freeList").add(mockPopUpPreview);
    Handler dismissHandler = new Handler(Looper.myLooper());
    VisibilityProxy.setField(popupPreviewPool, "dismissHandler", dismissHandler);

    // At first, emulate press event.
    mockPopUpPreview.showIfNecessary(popupKey, Optional.of(popup), false);
    replayAll();

    assertTrue(touchEvent(view, MotionEvent.ACTION_DOWN, 75, 45));
    verifyAll();

    // Then, moving to left.
    resetAll();
    mockPopUpPreview.showIfNecessary(popupKey, Optional.of(flickPopup), false);
    replayAll();

    assertTrue(touchEvent(view, MotionEvent.ACTION_MOVE, 25, 45));
    verifyAll();

    // Moving to top.
    resetAll();
    mockPopUpPreview.showIfNecessary(popupKey, Optional.<PopUp>absent(), false);
    replayAll();

    assertTrue(touchEvent(view, MotionEvent.ACTION_MOVE, 75, 15));
    verifyAll();

    // Moving to center again.
    resetAll();
    mockPopUpPreview.showIfNecessary(popupKey, Optional.of(popup), false);
    replayAll();

    assertTrue(touchEvent(view, MotionEvent.ACTION_MOVE, 75, 45));
    verifyAll();

    // Finally, release.
    resetAll();
    replayAll();

    assertTrue(touchEvent(view, MotionEvent.ACTION_UP, 75, 45));
    verifyAll();

    assertTrue(dismissHandler.hasMessages(0, mockPopUpPreview));
    dismissHandler.removeMessages(0);

    // If popup is disabled, no events should happen.
    resetAll();
    replayAll();

    view.setPopupEnabled(false);
    verifyAll();

    resetAll();
    replayAll();

    assertTrue(touchEvent(view, MotionEvent.ACTION_DOWN, 75, 45));
    verifyAll();
  }

  private void delayedPopupTestImpl(
      boolean popupEnabled, boolean longPressTimeoutTrigger, boolean popupPresent,
      boolean expectShowIfNecessaryIsCalled, boolean expectLongPressCallbackIsSet) {
    // Set up mock drawable cache.
    MockResources mockResources = new MockResources() {
      @Override
      public Drawable getDrawable(int resourceId) {
        return new ColorDrawable();
      }

      @Override
      public DisplayMetrics getDisplayMetrics() {
        return new DisplayMetrics();
      }
    };
    DrawableCache drawableCache = new DrawableCache(mockResources);
    VisibilityProxy.setField(view, "drawableCache", drawableCache);

    // Set up a dummy keyboard with one key entity and mock key event handler.
    view.setPopupEnabled(popupEnabled);
    Optional<PopUp> popup = Optional.absent();
    if (popupPresent) {
      popup = Optional.of(new PopUp(0, 0, 40, 0, -30, 10, 10));
    }
    KeyEntity keyEntity = new KeyEntity(
        1, 'a', 'A', longPressTimeoutTrigger, 0, Optional.<String>absent(), false, popup,
        0, 0, 0, 0);
    Key key = createKeyWithKeyEntity(0, 0, keyEntity);
    view.setKeyboard(createDummyKeyboard(key));
    KeyEventHandler mockKeyEventHandler = createKeyEventHandlerMock();
    view.setKeyEventHandler(mockKeyEventHandler);

    // Set up mock popup preview.
    PopUpPreview mockPopUpPreview = createMockBuilder(PopUpPreview.class)
        .withConstructor(View.class, BackgroundDrawableFactory.class, DrawableCache.class)
        .withArgs(view, new BackgroundDrawableFactory(mockResources), drawableCache)
        .createMock();
    PopUpPreview.Pool popupPreviewPool = VisibilityProxy.getField(view, "popupPreviewPool");
    VisibilityProxy.<List<PopUpPreview>>getField(
        popupPreviewPool, "freeList").add(mockPopUpPreview);
    Handler dismissHandler = new Handler(Looper.myLooper());
    VisibilityProxy.setField(popupPreviewPool, "dismissHandler", dismissHandler);

    // Run test scenario.
    if (expectShowIfNecessaryIsCalled) {
      mockPopUpPreview.showIfNecessary(key, popup, false);
    }
    if (!popupEnabled) {
      mockPopUpPreview.dismiss();
    }
    Capture<KeyEventContext> keyEventContextCapture = new Capture<KeyEventContext>();
    mockKeyEventHandler.cancelDelayedKeyEvent(isA(KeyEventContext.class));
    expectLastCall().anyTimes();
    mockKeyEventHandler.maybeStartDelayedKeyEvent(capture(keyEventContextCapture));
    mockKeyEventHandler.sendPress('a');
    replayAll();

    assertTrue(touchEvent(view, MotionEvent.ACTION_DOWN, 75, 45));
    verifyAll();
    KeyEventContext context = keyEventContextCapture.getValue();
    assertEquals(expectLongPressCallbackIsSet, context.longPressCallback.isPresent());
  }

  @SmallTest
  public void testDelayedPopup_PopupEnabled_Trigger_PopupIconPresent() {
    delayedPopupTestImpl(true, true, true, true, false);
  }

  @SmallTest
  public void testDelayedPopup_PopupEnabled_Trigger_PopupIconAbsent() {
    delayedPopupTestImpl(true, true, false, true, false);
  }

  @SmallTest
  public void testDelayedPopup_PopupEnabled_NotTrigger_PopupIconPresent() {
    delayedPopupTestImpl(true, false, true, true, true);
  }

  @SmallTest
  public void testDelayedPopup_PopupEnabled_NotTrigger_PopupIconAbsent() {
    delayedPopupTestImpl(true, false, false, true, false);
  }

  @SmallTest
  public void testDelayedPopup_PopupDisabled_Trigger_PopupIconPresent() {
    delayedPopupTestImpl(false, true, true, false, false);
  }

  @SmallTest
  public void testDelayedPopup_PopupDisabled_Trigger_PopupIconAbsent() {
    delayedPopupTestImpl(false, true, false, false, false);
  }

  @SmallTest
  public void testDelayedPopup_PopupDisabled_NotTrigger_PopupIconPresent() {
    delayedPopupTestImpl(false, false, true, false, true);
  }

  @SmallTest
  public void testDelayedPopup_PopupDisabled_NotTrigger_PopupIconAbsent() {
    delayedPopupTestImpl(false, false, false, false, false);
  }

  // Unfortunately, there are no way to test multi-touch events because we can create neither
  // MotionEvent class instances with multi-touch events nor mock instances.
  // So, just skip the tests for those cases.
  // TODO(hidehiko): Figure out how to write those tests, though we may need to get rid of
  //   supporting devices with lower APIs for that purpose...

  @SmallTest
  public void testGetKeyByCoord() {
    Key key1 = createKey(0, 0, 'a');
    Key key2 = createKey(WIDTH * 2, 0, 'b');

    class TestCase {
      final Key spacer;
      final Key expectedLeftHalf;
      final Key expectedRightHalf;

      TestCase(Key spacer, Key expectedLeftHalf, Key expectedRightHalf) {
        this.spacer = spacer;
        this.expectedLeftHalf = expectedLeftHalf;
        this.expectedRightHalf = expectedRightHalf;
      }
    }

    final TestCase[] testCases = {
        new TestCase(createSpacer(WIDTH, 0, Stick.EVEN), key1, key2),
        new TestCase(createSpacer(WIDTH, 0, Stick.LEFT), key1, key1),
        new TestCase(createSpacer(WIDTH, 0, Stick.RIGHT), key2, key2),
    };

    for (TestCase testCase : testCases) {
      Row row = new Row(Arrays.asList(key1, testCase.spacer, key2), HEIGHT, VERTICAL_GAP);
      view.setKeyboard(new Keyboard(Optional.<String>absent(), Collections.singletonList(row), 1,
                                    KeyboardSpecification.TWELVE_KEY_TOGGLE_FLICK_KANA));

      // Center of key1.
      assertSame(key1, view.getKeyByCoord(WIDTH / 2, HEIGHT / 2).get());

      // Center of key2.
      assertSame(key2, view.getKeyByCoord(WIDTH * 5 / 2, HEIGHT / 2).get());

      // On a spacer.
      assertSame(testCase.expectedLeftHalf, view.getKeyByCoord(WIDTH * 4 / 3, HEIGHT / 2).get());
      assertSame(testCase.expectedRightHalf, view.getKeyByCoord(WIDTH * 5 / 3, HEIGHT / 2).get());

      // Both outside of the keyboard.
      assertSame(key1, view.getKeyByCoord(-WIDTH / 2, HEIGHT / 2).get());
      assertSame(key2, view.getKeyByCoord(WIDTH * 7 / 2, HEIGHT / 2).get());
    }
  }

  @SmallTest
  public void testOnDetachedFromWindow() {
    KeyboardViewBackgroundSurface keyboardViewBackgroundSurface =
        createKeyboardViewBackgroundSurfaceMock();
    keyboardViewBackgroundSurface.reset();
    replayAll();
    VisibilityProxy.setField(view, "backgroundSurface", keyboardViewBackgroundSurface);

    view.onDetachedFromWindow();

    verifyAll();
  }

  @SuppressWarnings("unchecked")
  @SmallTest
  public void testSetSkinType() {
    Resources resources = getInstrumentation().getTargetContext().getResources();
    KeyboardViewBackgroundSurface keyboardViewBackgroundSurface =
        createKeyboardViewBackgroundSurfaceMock();
    keyboardViewBackgroundSurface.requestUpdateKeyboard(
        isA(Keyboard.class), isA(Set.class));

    DrawableCache drawableCache = createMockBuilder(DrawableCache.class)
        .withConstructor(Resources.class)
        .withArgs(new MockResourcesWithDisplayMetrics())
        .createMock();
    drawableCache.setSkin(SkinType.ORANGE_LIGHTGRAY.getSkin(resources));

    BackgroundDrawableFactory backgroundDrawableFactory =
        new BackgroundDrawableFactory(createNiceMock(MockResourcesWithDisplayMetrics.class));
    backgroundDrawableFactory.setSkin(SkinType.ORANGE_LIGHTGRAY.getSkin(resources));
    replayAll();

    VisibilityProxy.setField(view, "backgroundSurface", keyboardViewBackgroundSurface);
    VisibilityProxy.setField(view, "drawableCache", drawableCache);
    VisibilityProxy.setField(view, "backgroundDrawableFactory", backgroundDrawableFactory);

    view.setSkin(SkinType.ORANGE_LIGHTGRAY.getSkin(resources));

    verifyAll();
  }

  @SmallTest
  public void testSetKeyboard() {
    KeyboardView view = new KeyboardView(getInstrumentation().getTargetContext());
    Set<MetaState> originalMetaStates = EnumSet.of(
        MetaState.NO_GLOBE,
        MetaState.CAPS_LOCK,
        MetaState.ACTION_GO,
        MetaState.VARIATION_EMAIL_ADDRESS,
        MetaState.COMPOSING);
    view.updateMetaStates(originalMetaStates, EnumSet.noneOf(MetaState.class));
    assertEquals(originalMetaStates, view.getMetaStates());
    view.setKeyboard(new Keyboard(Optional.<String>absent(), Collections.<Row>emptyList(), 0f,
                                  KeyboardSpecification.TWELVE_KEY_TOGGLE_FLICK_KANA));
    assertEquals(
        EnumSet.of(
            MetaState.NO_GLOBE,
            MetaState.ACTION_GO,
            MetaState.VARIATION_EMAIL_ADDRESS,
            MetaState.COMPOSING),
        view.getMetaStates());
  }

  @SmallTest
  public void testSetEditorInfo() {
    KeyboardView view = new KeyboardView(getInstrumentation().getTargetContext());

    class TestData extends Parameter {
      final int imeOptions;
      final int inputType;
      final Set<MetaState> expectedMetaStates;
      TestData(int imeOptions, int inputType, Set<MetaState> expectedMetaStates) {
        this.imeOptions = imeOptions;
        this.inputType = inputType;
        this.expectedMetaStates = expectedMetaStates;
      }
    }

    // Keep the order. KeyboardView's state is not reset in the iteration.
    TestData[] testDataList = {
        new TestData(0, 0, EnumSet.of(MetaState.NO_GLOBE)),
        new TestData(EditorInfo.IME_ACTION_DONE,
                     0, EnumSet.of(MetaState.NO_GLOBE, MetaState.ACTION_DONE)),
        new TestData(EditorInfo.IME_ACTION_GO,
                     0, EnumSet.of(MetaState.NO_GLOBE, MetaState.ACTION_GO)),
        new TestData(EditorInfo.IME_ACTION_NEXT,
                     0, EnumSet.of(MetaState.NO_GLOBE, MetaState.ACTION_NEXT)),
        new TestData(EditorInfo.IME_ACTION_NONE,
                     0, EnumSet.of(MetaState.NO_GLOBE, MetaState.ACTION_NONE)),
        new TestData(EditorInfo.IME_ACTION_PREVIOUS,
                     0, EnumSet.of(MetaState.NO_GLOBE, MetaState.ACTION_PREVIOUS)),
        new TestData(EditorInfo.IME_ACTION_SEARCH,
                     0, EnumSet.of(MetaState.NO_GLOBE, MetaState.ACTION_SEARCH)),
        new TestData(EditorInfo.IME_ACTION_SEND,
                     0, EnumSet.of(MetaState.NO_GLOBE, MetaState.ACTION_SEND)),
        new TestData(0, InputType.TYPE_TEXT_VARIATION_URI | InputType.TYPE_CLASS_TEXT,
                     EnumSet.of(MetaState.NO_GLOBE, MetaState.VARIATION_URI)),
        new TestData(0, InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS | InputType.TYPE_CLASS_TEXT,
                     EnumSet.of(MetaState.NO_GLOBE, MetaState.VARIATION_EMAIL_ADDRESS)),
        new TestData(0, InputType.TYPE_TEXT_VARIATION_WEB_EMAIL_ADDRESS | InputType.TYPE_CLASS_TEXT,
                     EnumSet.of(MetaState.NO_GLOBE, MetaState.VARIATION_EMAIL_ADDRESS)),
        new TestData(0, InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE | InputType.TYPE_CLASS_TEXT,
                     EnumSet.of(MetaState.NO_GLOBE)),
        new TestData(0, InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS | InputType.TYPE_CLASS_TEXT,
                     EnumSet.of(MetaState.NO_GLOBE, MetaState.VARIATION_EMAIL_ADDRESS)),
        new TestData(0, InputType.TYPE_NUMBER_VARIATION_PASSWORD | InputType.TYPE_CLASS_NUMBER,
                     EnumSet.of(MetaState.NO_GLOBE)),
        new TestData(EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_ENTER_ACTION,
                     0, EnumSet.of(MetaState.NO_GLOBE)),
    };

    for (TestData testData : testDataList) {
      EditorInfo editorInfo = new EditorInfo();
      editorInfo.imeOptions = testData.imeOptions;
      editorInfo.inputType = testData.inputType;
      view.setEditorInfo(editorInfo);
      assertEquals(testData.toString(), testData.expectedMetaStates, view.getMetaStates());
    }
  }
}
