// Copyright 2013 The Flutter 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 "flutter/shell/platform/windows/keyboard_key_channel_handler.h"

#include <memory>

#include "flutter/shell/platform/common/json_message_codec.h"
#include "flutter/shell/platform/windows/flutter_windows_view.h"
#include "flutter/shell/platform/windows/testing/test_binary_messenger.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"

namespace flutter {
namespace testing {

namespace {
static constexpr char kScanCodeKey[] = "scanCode";
static constexpr char kCharacterCodePointKey[] = "characterCodePoint";
static constexpr int kHandledScanCode = 0x14;
static constexpr int kUnhandledScanCode = 0x15;
static constexpr int kUnhandledScanCodeExtended = 0xe015;

static std::unique_ptr<std::vector<uint8_t>> CreateResponse(bool handled) {
  auto response_doc =
      std::make_unique<rapidjson::Document>(rapidjson::kObjectType);
  auto& allocator = response_doc->GetAllocator();
  response_doc->AddMember("handled", handled, allocator);
  return JsonMessageCodec::GetInstance().EncodeMessage(*response_doc);
}
}  // namespace

TEST(KeyboardKeyChannelHandlerTest, KeyboardHookHandling) {
  auto handled_message = CreateResponse(true);
  auto unhandled_message = CreateResponse(false);
  int received_scancode = 0;

  TestBinaryMessenger messenger(
      [&received_scancode, &handled_message, &unhandled_message](
          const std::string& channel, const uint8_t* message,
          size_t message_size, BinaryReply reply) {
        if (channel == "flutter/keyevent") {
          auto message_doc = JsonMessageCodec::GetInstance().DecodeMessage(
              message, message_size);
          received_scancode = (*message_doc)[kScanCodeKey].GetInt();
          if (received_scancode == kHandledScanCode) {
            reply(handled_message->data(), handled_message->size());
          } else {
            reply(unhandled_message->data(), unhandled_message->size());
          }
        }
      });

  KeyboardKeyChannelHandler handler(&messenger);
  bool last_handled = false;

  handler.KeyboardHook(
      64, kHandledScanCode, WM_KEYDOWN, L'a', false, false,
      [&last_handled](bool handled) { last_handled = handled; });
  EXPECT_EQ(received_scancode, kHandledScanCode);
  EXPECT_EQ(last_handled, true);

  received_scancode = 0;

  handler.KeyboardHook(
      64, kUnhandledScanCode, WM_KEYDOWN, L'b', false, false,
      [&last_handled](bool handled) { last_handled = handled; });
  EXPECT_EQ(received_scancode, kUnhandledScanCode);
  EXPECT_EQ(last_handled, false);
}

TEST(KeyboardKeyChannelHandlerTest, ExtendedKeysAreSentToRedispatch) {
  auto handled_message = CreateResponse(true);
  auto unhandled_message = CreateResponse(false);
  int received_scancode = 0;

  TestBinaryMessenger messenger(
      [&received_scancode, &handled_message, &unhandled_message](
          const std::string& channel, const uint8_t* message,
          size_t message_size, BinaryReply reply) {
        if (channel == "flutter/keyevent") {
          auto message_doc = JsonMessageCodec::GetInstance().DecodeMessage(
              message, message_size);
          received_scancode = (*message_doc)[kScanCodeKey].GetInt();
          if (received_scancode == kHandledScanCode) {
            reply(handled_message->data(), handled_message->size());
          } else {
            reply(unhandled_message->data(), unhandled_message->size());
          }
        }
      });

  KeyboardKeyChannelHandler handler(&messenger);
  bool last_handled = true;

  // Extended key flag is passed to redispatched events if set.
  handler.KeyboardHook(
      64, kUnhandledScanCode, WM_KEYDOWN, L'b', true, false,
      [&last_handled](bool handled) { last_handled = handled; });
  EXPECT_EQ(last_handled, false);
  EXPECT_EQ(received_scancode, kUnhandledScanCodeExtended);

  last_handled = true;
  // Extended key flag is not passed to redispatched events if not set.
  handler.KeyboardHook(
      64, kUnhandledScanCode, WM_KEYDOWN, L'b', false, false,
      [&last_handled](bool handled) { last_handled = handled; });
  EXPECT_EQ(last_handled, false);
  EXPECT_EQ(received_scancode, kUnhandledScanCode);
}

TEST(KeyboardKeyChannelHandlerTest, DeadKeysDoNotCrash) {
  auto handled_message = CreateResponse(true);
  auto unhandled_message = CreateResponse(false);
  int received_scancode = 0;

  TestBinaryMessenger messenger(
      [&received_scancode, &handled_message, &unhandled_message](
          const std::string& channel, const uint8_t* message,
          size_t message_size, BinaryReply reply) {
        if (channel == "flutter/keyevent") {
          auto message_doc = JsonMessageCodec::GetInstance().DecodeMessage(
              message, message_size);
          uint32_t character = (*message_doc)[kCharacterCodePointKey].GetUint();
          EXPECT_EQ(character, (uint32_t)'^');
        }
        return true;
      });

  KeyboardKeyChannelHandler handler(&messenger);
  // Extended key flag is passed to redispatched events if set.
  handler.KeyboardHook(0xDD, 0x1a, WM_KEYDOWN, 0x8000005E, false, false,
                       [](bool handled) {});

  // EXPECT is done during the callback above.
}

}  // namespace testing
}  // namespace flutter
