// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/protocol/input_event_tracker.h"

#include <stdint.h>

#include "remoting/proto/event.pb.h"
#include "remoting/protocol/protocol_mock_objects.h"
#include "remoting/protocol/test_event_matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using ::testing::_;
using ::testing::ExpectationSet;
using ::testing::InSequence;

namespace remoting {
namespace protocol {

using test::EqualsKeyEventWithCapsLock;
using test::EqualsMouseEvent;
using test::EqualsKeyEventWithoutLockStates;

namespace {

static const MouseEvent::MouseButton BUTTON_LEFT = MouseEvent::BUTTON_LEFT;
static const MouseEvent::MouseButton BUTTON_RIGHT = MouseEvent::BUTTON_RIGHT;

MATCHER_P2(TouchPointIdsAndTypeEqual, ids, type, "") {
  if (arg.event_type() != type)
    return false;

  std::set<uint32_t> touch_ids;
  for (const TouchEventPoint& point : arg.touch_points()) {
    touch_ids.insert(point.id());
  }
  return touch_ids == ids;
}

static KeyEvent NewUsbEvent(uint32_t usb_keycode, bool pressed) {
  KeyEvent event;
  event.set_usb_keycode(usb_keycode);
  event.set_pressed(pressed);
  // Create all key events with the hardcoded |lock_state| in this test.
  event.set_lock_states(KeyEvent::LOCK_STATES_CAPSLOCK);
  return event;
}

static void PressAndReleaseUsb(InputStub* input_stub, uint32_t usb_keycode) {
  input_stub->InjectKeyEvent(NewUsbEvent(usb_keycode, true));
  input_stub->InjectKeyEvent(NewUsbEvent(usb_keycode, false));
}

static MouseEvent NewMouseEvent(int x,
                                int y,
                                MouseEvent::MouseButton button,
                                bool down) {
  MouseEvent event;
  event.set_x(x);
  event.set_y(y);
  event.set_button(button);
  event.set_button_down(down);
  return event;
}

void AddTouchPoint(uint32_t id, TouchEvent* event) {
  TouchEventPoint* p = event->add_touch_points();
  p->set_id(id);
}

}  // namespace

// Verify that keys that were pressed and released aren't re-released.
TEST(InputEventTrackerTest, NothingToRelease) {
  MockInputStub mock_stub;
  InputEventTracker input_tracker(&mock_stub);

  {
    InSequence s;

    EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsKeyEventWithCapsLock(1, true)));
    EXPECT_CALL(mock_stub,
                InjectKeyEvent(EqualsKeyEventWithCapsLock(1, false)));
    EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsKeyEventWithCapsLock(2, true)));
    EXPECT_CALL(mock_stub,
                InjectKeyEvent(EqualsKeyEventWithCapsLock(2, false)));

    EXPECT_CALL(mock_stub,
                InjectMouseEvent(EqualsMouseEvent(0, 0, BUTTON_LEFT, true)));
    EXPECT_CALL(mock_stub,
                InjectMouseEvent(EqualsMouseEvent(0, 0, BUTTON_LEFT, false)));
  }

  PressAndReleaseUsb(&input_tracker, 1);
  PressAndReleaseUsb(&input_tracker, 2);

  input_tracker.InjectMouseEvent(NewMouseEvent(0, 0, BUTTON_LEFT, true));
  input_tracker.InjectMouseEvent(NewMouseEvent(0, 0, BUTTON_LEFT, false));

  input_tracker.ReleaseAll();
}

// Verify that keys that were left pressed get released.
TEST(InputEventTrackerTest, ReleaseAllKeys) {
  MockInputStub mock_stub;
  InputEventTracker input_tracker(&mock_stub);
  ExpectationSet injects;

  {
    InSequence s;

    injects += EXPECT_CALL(mock_stub,
                           InjectKeyEvent(EqualsKeyEventWithCapsLock(3, true)));
    injects += EXPECT_CALL(mock_stub,
                           InjectKeyEvent(EqualsKeyEventWithCapsLock(1, true)));
    injects += EXPECT_CALL(
        mock_stub, InjectKeyEvent(EqualsKeyEventWithCapsLock(1, false)));
    injects += EXPECT_CALL(mock_stub,
                           InjectKeyEvent(EqualsKeyEventWithCapsLock(2, true)));
    injects += EXPECT_CALL(
        mock_stub, InjectKeyEvent(EqualsKeyEventWithCapsLock(2, false)));

    injects += EXPECT_CALL(mock_stub, InjectMouseEvent(EqualsMouseEvent(
                                          0, 0, BUTTON_RIGHT, true)));
    injects += EXPECT_CALL(
        mock_stub, InjectMouseEvent(EqualsMouseEvent(0, 0, BUTTON_LEFT, true)));
    injects += EXPECT_CALL(mock_stub, InjectMouseEvent(EqualsMouseEvent(
                                          1, 1, BUTTON_LEFT, false)));
  }

  // The key should be released but |lock_states| should not be set.
  EXPECT_CALL(mock_stub, InjectKeyEvent(EqualsKeyEventWithoutLockStates(
                             3, false))).After(injects);
  EXPECT_CALL(mock_stub, InjectMouseEvent(EqualsMouseEvent(
                             1, 1, BUTTON_RIGHT, false))).After(injects);

  input_tracker.InjectKeyEvent(NewUsbEvent(3, true));
  PressAndReleaseUsb(&input_tracker, 1);
  PressAndReleaseUsb(&input_tracker, 2);

  input_tracker.InjectMouseEvent(NewMouseEvent(0, 0, BUTTON_RIGHT, true));
  input_tracker.InjectMouseEvent(NewMouseEvent(0, 0, BUTTON_LEFT, true));
  input_tracker.InjectMouseEvent(NewMouseEvent(1, 1, BUTTON_LEFT, false));

  EXPECT_FALSE(input_tracker.IsKeyPressed(static_cast<ui::DomCode>(1)));
  EXPECT_FALSE(input_tracker.IsKeyPressed(static_cast<ui::DomCode>(2)));
  EXPECT_TRUE(input_tracker.IsKeyPressed(static_cast<ui::DomCode>(3)));
  EXPECT_EQ(1, input_tracker.PressedKeyCount());

  input_tracker.ReleaseAll();
}

// Verify that we track both USB-based key events correctly.
TEST(InputEventTrackerTest, TrackUsbKeyEvents) {
  MockInputStub mock_stub;
  InputEventTracker input_tracker(&mock_stub);
  ExpectationSet injects;

  {
    InSequence s;

    injects += EXPECT_CALL(mock_stub,
                           InjectKeyEvent(EqualsKeyEventWithCapsLock(3, true)));
    injects += EXPECT_CALL(mock_stub,
                           InjectKeyEvent(EqualsKeyEventWithCapsLock(6, true)));
    injects += EXPECT_CALL(mock_stub,
                           InjectKeyEvent(EqualsKeyEventWithCapsLock(7, true)));
    injects += EXPECT_CALL(mock_stub,
                           InjectKeyEvent(EqualsKeyEventWithCapsLock(5, true)));
    injects += EXPECT_CALL(mock_stub,
                           InjectKeyEvent(EqualsKeyEventWithCapsLock(5, true)));
    injects += EXPECT_CALL(mock_stub,
                           InjectKeyEvent(EqualsKeyEventWithCapsLock(2, true)));
    injects += EXPECT_CALL(
        mock_stub, InjectKeyEvent(EqualsKeyEventWithCapsLock(2, false)));
  }

  // The key should be auto released with no |lock_states|.
  EXPECT_CALL(mock_stub,
              InjectKeyEvent(EqualsKeyEventWithoutLockStates(3, false)))
      .After(injects);
  EXPECT_CALL(mock_stub,
              InjectKeyEvent(EqualsKeyEventWithoutLockStates(6, false)))
      .After(injects);
  EXPECT_CALL(mock_stub,
              InjectKeyEvent(EqualsKeyEventWithoutLockStates(7, false)))
      .After(injects);
  EXPECT_CALL(mock_stub,
              InjectKeyEvent(EqualsKeyEventWithoutLockStates(5, false)))
      .After(injects);

  input_tracker.InjectKeyEvent(NewUsbEvent(3, true));
  input_tracker.InjectKeyEvent(NewUsbEvent(6, true));
  input_tracker.InjectKeyEvent(NewUsbEvent(7, true));
  input_tracker.InjectKeyEvent(NewUsbEvent(5, true));
  input_tracker.InjectKeyEvent(NewUsbEvent(5, true));
  PressAndReleaseUsb(&input_tracker, 2);

  EXPECT_FALSE(input_tracker.IsKeyPressed(static_cast<ui::DomCode>(1)));
  EXPECT_FALSE(input_tracker.IsKeyPressed(static_cast<ui::DomCode>(2)));
  EXPECT_TRUE(input_tracker.IsKeyPressed(static_cast<ui::DomCode>(3)));
  EXPECT_TRUE(input_tracker.IsKeyPressed(static_cast<ui::DomCode>(5)));
  EXPECT_TRUE(input_tracker.IsKeyPressed(static_cast<ui::DomCode>(6)));
  EXPECT_TRUE(input_tracker.IsKeyPressed(static_cast<ui::DomCode>(7)));
  EXPECT_EQ(4, input_tracker.PressedKeyCount());

  input_tracker.ReleaseAll();
}

// Verify that invalid events get passed through but not tracked.
TEST(InputEventTrackerTest, InvalidEventsNotTracked) {
  MockInputStub mock_stub;
  InputEventTracker input_tracker(&mock_stub);
  ExpectationSet injects;

  {
    InSequence s;

    injects += EXPECT_CALL(mock_stub,
                           InjectKeyEvent(EqualsKeyEventWithCapsLock(3, true)));
    injects += EXPECT_CALL(mock_stub,
                           InjectKeyEvent(EqualsKeyEventWithCapsLock(1, true)));
    injects += EXPECT_CALL(
        mock_stub, InjectKeyEvent(EqualsKeyEventWithCapsLock(1, false)));
    injects += EXPECT_CALL(mock_stub, InjectKeyEvent(_)).Times(2);
    injects += EXPECT_CALL(mock_stub,
                           InjectKeyEvent(EqualsKeyEventWithCapsLock(2, true)));
    injects += EXPECT_CALL(
        mock_stub, InjectKeyEvent(EqualsKeyEventWithCapsLock(2, false)));
  }

  EXPECT_CALL(mock_stub,
              InjectKeyEvent(EqualsKeyEventWithoutLockStates(3, false)))
      .After(injects);

  input_tracker.InjectKeyEvent(NewUsbEvent(3, true));
  PressAndReleaseUsb(&input_tracker, 1);

  KeyEvent invalid_event1;
  invalid_event1.set_pressed(true);
  input_tracker.InjectKeyEvent(invalid_event1);

  KeyEvent invalid_event2;
  invalid_event2.set_usb_keycode(6);
  input_tracker.InjectKeyEvent(invalid_event2);

  PressAndReleaseUsb(&input_tracker, 2);

  EXPECT_FALSE(input_tracker.IsKeyPressed(static_cast<ui::DomCode>(1)));
  EXPECT_FALSE(input_tracker.IsKeyPressed(static_cast<ui::DomCode>(2)));
  EXPECT_TRUE(input_tracker.IsKeyPressed(static_cast<ui::DomCode>(3)));
  EXPECT_EQ(1, input_tracker.PressedKeyCount());

  input_tracker.ReleaseAll();
}

// All touch points added with multiple touch events should be released as a
// cancel event.
TEST(InputEventTrackerTest, ReleaseAllTouchPoints) {
  MockInputStub mock_stub;
  InputEventTracker input_tracker(&mock_stub);

  std::set<uint32_t> expected_ids1;
  expected_ids1.insert(1);
  expected_ids1.insert(2);
  std::set<uint32_t> expected_ids2;
  expected_ids2.insert(3);
  expected_ids2.insert(5);
  expected_ids2.insert(8);

  std::set<uint32_t> all_touch_point_ids;
  all_touch_point_ids.insert(expected_ids1.begin(), expected_ids1.end());
  all_touch_point_ids.insert(expected_ids2.begin(), expected_ids2.end());

  InSequence s;
  EXPECT_CALL(mock_stub, InjectTouchEvent(TouchPointIdsAndTypeEqual(
                             expected_ids1, TouchEvent::TOUCH_POINT_START)));
  EXPECT_CALL(mock_stub, InjectTouchEvent(TouchPointIdsAndTypeEqual(
                             expected_ids2, TouchEvent::TOUCH_POINT_START)));

  EXPECT_CALL(mock_stub,
              InjectTouchEvent(TouchPointIdsAndTypeEqual(
                  all_touch_point_ids, TouchEvent::TOUCH_POINT_CANCEL)));

  TouchEvent start_event1;
  start_event1.set_event_type(TouchEvent::TOUCH_POINT_START);
  AddTouchPoint(1, &start_event1);
  AddTouchPoint(2, &start_event1);
  input_tracker.InjectTouchEvent(start_event1);

  TouchEvent start_event2;
  start_event2.set_event_type(TouchEvent::TOUCH_POINT_START);
  AddTouchPoint(3, &start_event2);
  AddTouchPoint(5, &start_event2);
  AddTouchPoint(8, &start_event2);
  input_tracker.InjectTouchEvent(start_event2);

  input_tracker.ReleaseAll();
}

// Add some touch points and remove only a subset of them. ReleaseAll() should
// cancel all the remaining touch points.
TEST(InputEventTrackerTest, ReleaseAllRemainingTouchPoints) {
  MockInputStub mock_stub;
  InputEventTracker input_tracker(&mock_stub);

  std::set<uint32_t> start_expected_ids;
  start_expected_ids.insert(1);
  start_expected_ids.insert(2);
  start_expected_ids.insert(3);

  std::set<uint32_t> end_expected_ids;
  end_expected_ids.insert(1);
  std::set<uint32_t> cancel_expected_ids;
  cancel_expected_ids.insert(3);

  std::set<uint32_t> all_remaining_touch_point_ids;
  all_remaining_touch_point_ids.insert(2);

  InSequence s;
  EXPECT_CALL(mock_stub,
              InjectTouchEvent(TouchPointIdsAndTypeEqual(
                  start_expected_ids, TouchEvent::TOUCH_POINT_START)));
  EXPECT_CALL(mock_stub, InjectTouchEvent(TouchPointIdsAndTypeEqual(
                             end_expected_ids, TouchEvent::TOUCH_POINT_END)));
  EXPECT_CALL(mock_stub,
              InjectTouchEvent(TouchPointIdsAndTypeEqual(
                  cancel_expected_ids, TouchEvent::TOUCH_POINT_CANCEL)));

  EXPECT_CALL(mock_stub, InjectTouchEvent(TouchPointIdsAndTypeEqual(
                             all_remaining_touch_point_ids,
                             TouchEvent::TOUCH_POINT_CANCEL)));

  TouchEvent start_event;
  start_event.set_event_type(TouchEvent::TOUCH_POINT_START);
  AddTouchPoint(1, &start_event);
  AddTouchPoint(2, &start_event);
  AddTouchPoint(3, &start_event);
  input_tracker.InjectTouchEvent(start_event);

  TouchEvent end_event;
  end_event.set_event_type(TouchEvent::TOUCH_POINT_END);
  AddTouchPoint(1, &end_event);
  input_tracker.InjectTouchEvent(end_event);

  TouchEvent cancel_event;
  cancel_event.set_event_type(TouchEvent::TOUCH_POINT_CANCEL);
  AddTouchPoint(3, &cancel_event);
  input_tracker.InjectTouchEvent(cancel_event);

  input_tracker.ReleaseAll();
}

}  // namespace protocol
}  // namespace remoting
