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

#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_TEST_KEYBOARD_H_
#define FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_TEST_KEYBOARD_H_

#include <windows.h>

#include <functional>
#include <string>

#include "flutter/shell/platform/embedder/embedder.h"
#include "flutter/shell/platform/windows/testing/engine_modifier.h"
#include "flutter/shell/platform/windows/testing/wm_builders.h"

#include "gtest/gtest.h"

struct _FlutterPlatformMessageResponseHandle {
  FlutterDesktopBinaryReply callback;
  void* user_data;
};

namespace flutter {
namespace testing {
::testing::AssertionResult _EventEquals(const char* expr_event,
                                        const char* expr_expected,
                                        const FlutterKeyEvent& event,
                                        const FlutterKeyEvent& expected);

// Clone string onto the heap.
//
// If #string is nullptr, returns nullptr. Otherwise, the returned pointer must
// be freed with delete[].
char* clone_string(const char* string);

// Creates a valid Windows LPARAM for WM_KEYDOWN and WM_CHAR from parameters
// given.
//
// While |CreateKeyEventLparam| is flexible, it's recommended to use dedicated
// functions in wm_builders.h, such as |WmKeyDownInfo|.
LPARAM CreateKeyEventLparam(USHORT scancode,
                            bool extended,
                            bool was_down,
                            USHORT repeat_count = 1,
                            bool context_code = 0,
                            bool transition_state = 1);

class MockKeyResponseController {
 public:
  using ResponseCallback = std::function<void(bool)>;
  using EmbedderCallbackHandler =
      std::function<void(const FlutterKeyEvent*, ResponseCallback)>;
  using ChannelCallbackHandler = std::function<void(ResponseCallback)>;
  using TextInputCallbackHandler =
      std::function<void(std::unique_ptr<rapidjson::Document>)>;

  MockKeyResponseController()
      : channel_response_(ChannelRespondFalse),
        embedder_response_(EmbedderRespondFalse),
        text_input_response_(
            [](std::unique_ptr<rapidjson::Document> document) {}) {}

  void SetChannelResponse(ChannelCallbackHandler handler) {
    channel_response_ = std::move(handler);
  }

  void SetEmbedderResponse(EmbedderCallbackHandler handler) {
    embedder_response_ = std::move(handler);
  }

  void SetTextInputResponse(TextInputCallbackHandler handler) {
    text_input_response_ = std::move(handler);
  }

  void HandleChannelMessage(ResponseCallback callback) {
    channel_response_(callback);
  }

  void HandleEmbedderMessage(const FlutterKeyEvent* event,
                             ResponseCallback callback) {
    embedder_response_(event, std::move(callback));
  }

  void HandleTextInputMessage(std::unique_ptr<rapidjson::Document> document) {
    text_input_response_(std::move(document));
  }

 private:
  EmbedderCallbackHandler embedder_response_;
  ChannelCallbackHandler channel_response_;
  TextInputCallbackHandler text_input_response_;

  static void ChannelRespondFalse(ResponseCallback callback) {
    callback(false);
  }

  static void EmbedderRespondFalse(const FlutterKeyEvent* event,
                                   ResponseCallback callback) {
    callback(false);
  }
};

void MockEmbedderApiForKeyboard(
    EngineModifier& modifier,
    std::shared_ptr<MockKeyResponseController> response_controller);

// Simulate a message queue for WM messages.
//
// Subclasses must implement |Win32SendMessage| for how dispatched messages are
// processed.
class MockMessageQueue {
 protected:
  // Push a message to the message queue without dispatching it.
  void PushBack(const Win32Message* message);

  // Dispatch the first message of the message queue and return its result.
  //
  // This method asserts that the queue is not empty.
  LRESULT DispatchFront();

  // Peak the next message in the message queue.
  //
  // See Win32's |PeekMessage| for documentation.
  BOOL Win32PeekMessage(LPMSG lpMsg,
                        UINT wMsgFilterMin,
                        UINT wMsgFilterMax,
                        UINT wRemoveMsg);

  // Simulate dispatching a message to the system.
  virtual LRESULT Win32SendMessage(UINT const message,
                                   WPARAM const wparam,
                                   LPARAM const lparam) = 0;

  std::list<Win32Message> _pending_messages;
  std::list<Win32Message> _sent_messages;
};

}  // namespace testing
}  // namespace flutter

// Expect the |_target| FlutterKeyEvent has the required properties.
#define EXPECT_EVENT_EQUALS(_target, _type, _physical, _logical, _character, \
                            _synthesized)                                    \
  EXPECT_PRED_FORMAT2(_EventEquals, _target,                                 \
                      (FlutterKeyEvent{                                      \
                          .type = _type,                                     \
                          .physical = _physical,                             \
                          .logical = _logical,                               \
                          .character = _character,                           \
                          .synthesized = _synthesized,                       \
                      }));

#endif  // FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_TEST_KEYBOARD_H_
