// 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 "ppapi/tests/test_ime_input_event.h"

#include "ppapi/c/pp_errors.h"
#include "ppapi/c/ppb_input_event.h"
#include "ppapi/cpp/input_event.h"
#include "ppapi/cpp/module.h"
#include "ppapi/tests/test_utils.h"
#include "ppapi/tests/testing_instance.h"

REGISTER_TEST_CASE(ImeInputEvent);

namespace {

// Japanese Kanji letters
const char* kCompositionChar[] = {
    "\xE6\x96\x87",  // An example character of normal unicode.
    "\xF0\xA0\xAE\x9F", // An example character of surrogate pair.
    "\xF0\x9F\x98\x81"  // An example character of surrogate pair(emoji).
};

const char kCompositionText[] = "\xE6\x96\x87\xF0\xA0\xAE\x9F\xF0\x9F\x98\x81";

#define FINISHED_WAITING_MESSAGE "TEST_IME_INPUT_EVENT_FINISHED_WAITING"

}  // namespace

TestImeInputEvent::TestImeInputEvent(TestingInstance* instance)
    : TestCase(instance),
      input_event_interface_(NULL),
      keyboard_input_event_interface_(NULL),
      ime_input_event_interface_(NULL),
      received_unexpected_event_(true),
      received_finish_message_(false) {
}

TestImeInputEvent::~TestImeInputEvent() {
  // Remove the special listener that only responds to a
  // FINISHED_WAITING_MESSAGE string. See Init for where it gets added.
  std::string js_code;
  js_code = "var plugin = document.getElementById('plugin');"
            "plugin.removeEventListener('message',"
            "                           plugin.wait_for_messages_handler);"
            "delete plugin.wait_for_messages_handler;";
  instance_->EvalScript(js_code);
}

void TestImeInputEvent::RunTests(const std::string& filter) {
  RUN_TEST(ImeCommit, filter);
  RUN_TEST(ImeCancel, filter);
  RUN_TEST(ImeUnawareCommit, filter);
  RUN_TEST(ImeUnawareCancel, filter);
}

bool TestImeInputEvent::Init() {
  input_event_interface_ = static_cast<const PPB_InputEvent*>(
      pp::Module::Get()->GetBrowserInterface(PPB_INPUT_EVENT_INTERFACE));
  keyboard_input_event_interface_ =
      static_cast<const PPB_KeyboardInputEvent*>(
          pp::Module::Get()->GetBrowserInterface(
              PPB_KEYBOARD_INPUT_EVENT_INTERFACE));
  ime_input_event_interface_ = static_cast<const PPB_IMEInputEvent*>(
      pp::Module::Get()->GetBrowserInterface(
          PPB_IME_INPUT_EVENT_INTERFACE));

  bool success =
      input_event_interface_ &&
      keyboard_input_event_interface_ &&
      ime_input_event_interface_ &&
      CheckTestingInterface();

  // Set up a listener for our message that signals that all input events have
  // been received.
  // Note the following code is dependent on some features of test_case.html.
  // E.g., it is assumed that the DOM element where the plugin is embedded has
  // an id of 'plugin', and there is a function 'IsTestingMessage' that allows
  // us to ignore the messages that are intended for use by the testing
  // framework itself.
  std::string js_code =
      "var plugin = document.getElementById('plugin');"
      "var wait_for_messages_handler = function(message_event) {"
      "  if (!IsTestingMessage(message_event.data) &&"
      "      message_event.data === '" FINISHED_WAITING_MESSAGE "') {"
      "    plugin.postMessage('" FINISHED_WAITING_MESSAGE "');"
      "  }"
      "};"
      "plugin.addEventListener('message', wait_for_messages_handler);"
      // Stash it on the plugin so we can remove it in the destructor.
      "plugin.wait_for_messages_handler = wait_for_messages_handler;";
  instance_->EvalScript(js_code);

  return success;
}

bool TestImeInputEvent::HandleInputEvent(const pp::InputEvent& input_event) {
  // Check whether the IME related events comes in the expected order.
  switch (input_event.GetType()) {
    case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START:
    case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE:
    case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END:
    case PP_INPUTEVENT_TYPE_IME_TEXT:
    case PP_INPUTEVENT_TYPE_CHAR:
      if (expected_events_.empty()) {
        received_unexpected_event_ = true;
      } else {
        received_unexpected_event_ =
          !AreEquivalentEvents(input_event.pp_resource(),
                               expected_events_.front().pp_resource());
        expected_events_.erase(expected_events_.begin());
      }
      break;

    default:
      // Don't care for any other input event types for this test.
      break;
  }

  // Handle all input events.
  return true;
}

void TestImeInputEvent::HandleMessage(const pp::Var& message_data) {
  if (message_data.is_string() &&
      (message_data.AsString() == FINISHED_WAITING_MESSAGE)) {
    testing_interface_->QuitMessageLoop(instance_->pp_instance());
    received_finish_message_ = true;
  }
}

void TestImeInputEvent::DidChangeView(const pp::View& view) {
  view_rect_ = view.GetRect();
}

pp::InputEvent TestImeInputEvent::CreateImeCompositionStartEvent() {
  return pp::IMEInputEvent(
      instance_,
      PP_INPUTEVENT_TYPE_IME_COMPOSITION_START,
      100, // time_stamp
      pp::Var(""),
      std::vector<uint32_t>(),
      -1, // target_segment
      std::make_pair(0U, 0U) // selection
  );
}

pp::InputEvent TestImeInputEvent::CreateImeCompositionUpdateEvent(
    const std::string& text,
    const std::vector<uint32_t>& segments,
    int32_t target_segment,
    const std::pair<uint32_t, uint32_t>& selection) {
  return pp::IMEInputEvent(
      instance_,
      PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE,
      100, // time_stamp
      text,
      segments,
      target_segment,
      selection
  );
}

pp::InputEvent TestImeInputEvent::CreateImeCompositionEndEvent(
    const std::string& text) {
  return pp::IMEInputEvent(
      instance_,
      PP_INPUTEVENT_TYPE_IME_COMPOSITION_END,
      100, // time_stamp
      pp::Var(text),
      std::vector<uint32_t>(),
      -1, // target_segment
      std::make_pair(0U, 0U) // selection
  );
}

pp::InputEvent TestImeInputEvent::CreateImeTextEvent(const std::string& text) {
  return pp::IMEInputEvent(
      instance_,
      PP_INPUTEVENT_TYPE_IME_TEXT,
      100, // time_stamp
      pp::Var(text),
      std::vector<uint32_t>(),
      -1, // target_segment
      std::make_pair(0U, 0U) // selection
  );
}

pp::InputEvent TestImeInputEvent::CreateCharEvent(const std::string& text) {
  return pp::KeyboardInputEvent(
      instance_,
      PP_INPUTEVENT_TYPE_CHAR,
      100,  // time_stamp
      0,  // modifiers
      0,  // keycode
      pp::Var(text),
      pp::Var());
}

void TestImeInputEvent::GetFocusBySimulatingMouseClick() {
  // For receiving IME events, the plugin DOM node needs to be focused.
  // The following code is for achieving that by simulating a mouse click event.
  input_event_interface_->RequestInputEvents(instance_->pp_instance(),
                                             PP_INPUTEVENT_CLASS_MOUSE);
  SimulateInputEvent(pp::MouseInputEvent(
      instance_,
      PP_INPUTEVENT_TYPE_MOUSEDOWN,
      100,  // time_stamp
      0,  // modifiers
      PP_INPUTEVENT_MOUSEBUTTON_LEFT,
      pp::Point(
          view_rect_.x() + view_rect_.width() / 2,
          view_rect_.y() + view_rect_.height() / 2),
      1,  // click count
      pp::Point()));  // movement
}

// Simulates the input event and calls PostMessage to let us know when
// we have received all resulting events from the browser.
bool TestImeInputEvent::SimulateInputEvent(const pp::InputEvent& input_event) {
  received_unexpected_event_ = false;
  received_finish_message_ = false;
  testing_interface_->SimulateInputEvent(instance_->pp_instance(),
                                         input_event.pp_resource());
  instance_->PostMessage(pp::Var(FINISHED_WAITING_MESSAGE));
  testing_interface_->RunMessageLoop(instance_->pp_instance());
  return received_finish_message_ && !received_unexpected_event_;
}

bool TestImeInputEvent::AreEquivalentEvents(PP_Resource received,
                                            PP_Resource expected) {
  if (!input_event_interface_->IsInputEvent(received) ||
      !input_event_interface_->IsInputEvent(expected)) {
    return false;
  }

  // Test common fields, except modifiers and time stamp, which may be changed
  // by the browser.
  int32_t received_type = input_event_interface_->GetType(received);
  int32_t expected_type = input_event_interface_->GetType(expected);
  if (received_type != expected_type)
    return false;

  // Test event type-specific fields.
  switch (received_type) {
    case PP_INPUTEVENT_TYPE_IME_COMPOSITION_START:
      // COMPOSITION_START does not convey further information.
      break;

    case PP_INPUTEVENT_TYPE_IME_COMPOSITION_END:
    case PP_INPUTEVENT_TYPE_IME_TEXT:
      // For COMPOSITION_END and TEXT, GetText() has meaning.
      return pp::Var(pp::PASS_REF,
                     ime_input_event_interface_->GetText(received)) ==
             pp::Var(pp::PASS_REF,
                     ime_input_event_interface_->GetText(expected));

    case PP_INPUTEVENT_TYPE_IME_COMPOSITION_UPDATE:
      // For COMPOSITION_UPDATE, all fields must be checked.
      {
        uint32_t received_segment_number =
            ime_input_event_interface_->GetSegmentNumber(received);
        uint32_t expected_segment_number =
            ime_input_event_interface_->GetSegmentNumber(expected);
        if (received_segment_number != expected_segment_number)
          return false;

        // The "<=" is not a bug. i-th segment is represented as the pair of
        // i-th and (i+1)-th offsets in Pepper IME API.
        for (uint32_t i = 0; i <= received_segment_number; ++i) {
          if (ime_input_event_interface_->GetSegmentOffset(received, i) !=
              ime_input_event_interface_->GetSegmentOffset(expected, i))
            return false;
        }

        uint32_t received_selection_start = 0;
        uint32_t received_selection_end = 0;
        uint32_t expected_selection_start = 0;
        uint32_t expected_selection_end = 0;
        ime_input_event_interface_->GetSelection(
            received, &received_selection_start, &received_selection_end);
        ime_input_event_interface_->GetSelection(
            expected, &expected_selection_start, &expected_selection_end);
        if (received_selection_start != expected_selection_start ||
            received_selection_end != expected_selection_end) {
          return true;
        }

        return pp::Var(pp::PASS_REF,
                       ime_input_event_interface_->GetText(received)) ==
               pp::Var(pp::PASS_REF,
                       ime_input_event_interface_->GetText(expected)) &&
               ime_input_event_interface_->GetTargetSegment(received) ==
               ime_input_event_interface_->GetTargetSegment(expected);
      }

    case PP_INPUTEVENT_TYPE_CHAR:
      return
          keyboard_input_event_interface_->GetKeyCode(received) ==
          keyboard_input_event_interface_->GetKeyCode(expected) &&
          pp::Var(pp::PASS_REF,
              keyboard_input_event_interface_->GetCharacterText(received)) ==
          pp::Var(pp::PASS_REF,
              keyboard_input_event_interface_->GetCharacterText(expected));

    default:
      break;
  }
  return true;
}

std::string TestImeInputEvent::TestImeCommit() {
  GetFocusBySimulatingMouseClick();

  input_event_interface_->RequestInputEvents(instance_->pp_instance(),
                                             PP_INPUTEVENT_CLASS_KEYBOARD |
                                             PP_INPUTEVENT_CLASS_IME);

  std::vector<uint32_t> segments;
  segments.push_back(0U);
  segments.push_back(3U);
  segments.push_back(7U);
  segments.push_back(11U);
  pp::InputEvent update_event = CreateImeCompositionUpdateEvent(
      kCompositionText, segments, 1, std::make_pair(3U, 7U));

  expected_events_.clear();
  expected_events_.push_back(CreateImeCompositionStartEvent());
  expected_events_.push_back(update_event);
  expected_events_.push_back(CreateImeCompositionEndEvent(kCompositionText));
  expected_events_.push_back(CreateImeTextEvent(kCompositionText));

  // Simulate the case when IME successfully committed some text.
  ASSERT_TRUE(SimulateInputEvent(update_event));
  ASSERT_TRUE(SimulateInputEvent(CreateImeTextEvent(kCompositionText)));

  ASSERT_TRUE(expected_events_.empty());
  PASS();
}

std::string TestImeInputEvent::TestImeCancel() {
  GetFocusBySimulatingMouseClick();

  input_event_interface_->RequestInputEvents(instance_->pp_instance(),
                                             PP_INPUTEVENT_CLASS_KEYBOARD |
                                             PP_INPUTEVENT_CLASS_IME);

  std::vector<uint32_t> segments;
  segments.push_back(0U);
  segments.push_back(3U);
  segments.push_back(7U);
  segments.push_back(11U);
  pp::InputEvent update_event = CreateImeCompositionUpdateEvent(
      kCompositionText, segments, 1, std::make_pair(3U, 7U));

  expected_events_.clear();
  expected_events_.push_back(CreateImeCompositionStartEvent());
  expected_events_.push_back(update_event);
  expected_events_.push_back(CreateImeCompositionEndEvent(std::string()));

  // Simulate the case when IME canceled composition.
  ASSERT_TRUE(SimulateInputEvent(update_event));
  ASSERT_TRUE(SimulateInputEvent(CreateImeCompositionEndEvent(std::string())));

  ASSERT_TRUE(expected_events_.empty());
  PASS();
}

std::string TestImeInputEvent::TestImeUnawareCommit() {
  GetFocusBySimulatingMouseClick();

  input_event_interface_->ClearInputEventRequest(instance_->pp_instance(),
                                                 PP_INPUTEVENT_CLASS_IME);
  input_event_interface_->RequestInputEvents(instance_->pp_instance(),
                                             PP_INPUTEVENT_CLASS_KEYBOARD);

  std::vector<uint32_t> segments;
  segments.push_back(0U);
  segments.push_back(3U);
  segments.push_back(7U);
  segments.push_back(11U);
  pp::InputEvent update_event = CreateImeCompositionUpdateEvent(
      kCompositionText, segments, 1, std::make_pair(3U, 7U));

  expected_events_.clear();
  expected_events_.push_back(CreateCharEvent(kCompositionChar[0]));
  expected_events_.push_back(CreateCharEvent(kCompositionChar[1]));
  expected_events_.push_back(CreateCharEvent(kCompositionChar[2]));

  // Test for IME-unaware plugins. Commit event is translated to char events.
  ASSERT_TRUE(SimulateInputEvent(update_event));
  ASSERT_TRUE(SimulateInputEvent(CreateImeTextEvent(kCompositionText)));

  ASSERT_TRUE(expected_events_.empty());
  PASS();
}


std::string TestImeInputEvent::TestImeUnawareCancel() {
  GetFocusBySimulatingMouseClick();

  input_event_interface_->ClearInputEventRequest(instance_->pp_instance(),
                                                 PP_INPUTEVENT_CLASS_IME);
  input_event_interface_->RequestInputEvents(instance_->pp_instance(),
                                             PP_INPUTEVENT_CLASS_KEYBOARD);

  std::vector<uint32_t> segments;
  segments.push_back(0U);
  segments.push_back(3U);
  segments.push_back(7U);
  segments.push_back(11U);
  pp::InputEvent update_event = CreateImeCompositionUpdateEvent(
      kCompositionText, segments, 1, std::make_pair(3U, 7U));

  expected_events_.clear();

  // Test for IME-unaware plugins. Cancel won't issue any events.
  ASSERT_TRUE(SimulateInputEvent(update_event));
  ASSERT_TRUE(SimulateInputEvent(CreateImeCompositionEndEvent(std::string())));

  ASSERT_TRUE(expected_events_.empty());
  PASS();
}
