// Copyright 2022 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 <fuchsia/ui/input/cpp/fidl.h>
#include <fuchsia/ui/input3/cpp/fidl.h>
#include <fuchsia/ui/views/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fidl/cpp/binding.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/ui/scenic/cpp/view_ref_pair.h>

#include <memory>

#include <gtest/gtest.h>

#include "src/embedder/engine/embedder.h"
#include "src/embedder/fuchsia_logger.h"
#include "src/embedder/platform_message_channels.h"
#include "src/embedder/text_delegate.h"

namespace embedder_testing {

// Convert a |FlutterPlatformMessage| to string for ease of testing.
static std::string MessageToString(FlutterPlatformMessage* message) {
  const char* data = reinterpret_cast<const char*>(message->message);
  return std::string(data, message->message_size);
}

// Fake |KeyboardService| implementation. Only responsibility is to remember
// what it was called with.
class FakeKeyboardService : public fuchsia::ui::input3::Keyboard {
 public:
  // |fuchsia.ui.input3/Keyboard.AddListener|
  virtual void AddListener(fuchsia::ui::views::ViewRef,
                           fidl::InterfaceHandle<fuchsia::ui::input3::KeyboardListener> listener,
                           fuchsia::ui::input3::Keyboard::AddListenerCallback callback) {
    listener_ = listener.Bind();
    callback();
  }

  fidl::InterfacePtr<fuchsia::ui::input3::KeyboardListener> listener_;
};

// Fake ImeService implementation. Only responsibility is to remember what
// it was called with.
class FakeImeService : public fuchsia::ui::input::ImeService {
 public:
  virtual void GetInputMethodEditor(
      fuchsia::ui::input::KeyboardType keyboard_type, fuchsia::ui::input::InputMethodAction action,
      fuchsia::ui::input::TextInputState input_state,
      fidl::InterfaceHandle<fuchsia::ui::input::InputMethodEditorClient> client,
      fidl::InterfaceRequest<fuchsia::ui::input::InputMethodEditor> ime) {
    keyboard_type_ = std::move(keyboard_type);
    action_ = std::move(action);
    input_state_ = std::move(input_state);
    client_ = client.Bind();
    ime_ = std::move(ime);
  }

  virtual void ShowKeyboard() { keyboard_shown_ = true; }

  virtual void HideKeyboard() { keyboard_shown_ = false; }

  bool IsKeyboardShown() { return keyboard_shown_; }

  bool keyboard_shown_ = false;

  fuchsia::ui::input::KeyboardType keyboard_type_;
  fuchsia::ui::input::InputMethodAction action_;
  fuchsia::ui::input::TextInputState input_state_;
  fidl::InterfacePtr<fuchsia::ui::input::InputMethodEditorClient> client_;
  fidl::InterfaceRequest<fuchsia::ui::input::InputMethodEditor> ime_;
};

class TextDelegateTest : public ::testing::Test {
 protected:
  TextDelegateTest()
      : loop_(&kAsyncLoopConfigAttachToCurrentThread),
        keyboard_service_binding_(&keyboard_service_),
        ime_service_binding_(&ime_service_) {
    auto fake_view_ref_pair = scenic::ViewRefPair::New();

    fidl::InterfaceHandle<fuchsia::ui::input::ImeService> ime_service;
    ime_service_binding_.Bind(ime_service.NewRequest().TakeChannel());

    fidl::InterfaceHandle<fuchsia::ui::input3::Keyboard> keyboard;
    auto keyboard_request = keyboard.NewRequest();
    keyboard_service_binding_.Bind(keyboard_request.TakeChannel());

    text_delegate_ = std::make_unique<embedder::TextDelegate>(
        std::move(fake_view_ref_pair.view_ref), std::move(ime_service), std::move(keyboard),
        /* key_event_dispatch_callback: [flutter/keydata] */
        [](const FlutterKeyEvent* event) {
          FX_LOG(INFO, embedder_testing::kLogUnittestTag,
                 "TextDelegateTest - key_event_dispatch_callback");
        },
        /*platform_dispatch_callback: [flutter/keyevent, flutter/textinput] */
        [this](const FlutterPlatformMessage* message) {
          FX_LOG(INFO, embedder_testing::kLogUnittestTag,
                 "TextDelegateTest - platform_dispatch_callback");
          memcpy(&last_message_, &message, sizeof(FlutterPlatformMessage));
        },
        nullptr);

    // TextDelegate has some async initialization that needs to happen.
    RunLoopUntilIdle();
  }

  // Runs the event loop until all scheduled events are spent.
  void RunLoopUntilIdle() { loop_.RunUntilIdle(); }

  void TearDown() override {
    loop_.Quit();
    ASSERT_EQ(loop_.ResetQuit(), 0);
  }

  async::Loop loop_;

  FakeKeyboardService keyboard_service_;
  fidl::Binding<fuchsia::ui::input3::Keyboard> keyboard_service_binding_;

  FakeImeService ime_service_;
  fidl::Binding<fuchsia::ui::input::ImeService> ime_service_binding_;

  // Unit under test.
  std::unique_ptr<embedder::TextDelegate> text_delegate_;

  FlutterPlatformMessage* last_message_;
};

// Goes through several steps of a text edit protocol. These are hard to test
// in isolation because the text edit protocol depends on the correct method
// invocation sequence. The text editor is initialized with the editing
// parameters, and we verify that the correct input action is parsed out. We
// then exercise showing and hiding the keyboard, as well as a text state
// update.
TEST_F(TextDelegateTest, ActivateIme) {
  // auto fake_platform_message_response = FakePlatformMessageResponse::Create();
  {
    // Initialize the editor. Without this initialization, the protocol code
    // will crash.
    const auto set_client_msg = R"(
      {
        "method": "TextInput.setClient",
        "args": [
           7,
           {
             "inputType": {
               "name": "TextInputType.multiline",
               "signed":null,
               "decimal":null
             },
             "readOnly": false,
             "obscureText": false,
             "autocorrect":true,
             "smartDashesType":"1",
             "smartQuotesType":"1",
             "enableSuggestions":true,
             "enableInteractiveSelection":true,
             "actionLabel":null,
             "inputAction":"TextInputAction.newline",
             "textCapitalization":"TextCapitalization.none",
             "keyboardAppearance":"Brightness.dark",
             "enableIMEPersonalizedLearning":true,
             "enableDeltaModel":false
          }
       ]
      }
    )";
    FlutterPlatformMessage flutter_platform_message = {
        .struct_size = sizeof(FlutterPlatformMessage),
        .channel = embedder::kTextInputChannel,
        .message = reinterpret_cast<const uint8_t*>(set_client_msg),
        .message_size = strlen(set_client_msg),
        .response_handle = nullptr};

    text_delegate_->HandleFlutterTextInputChannelPlatformMessage(&flutter_platform_message);
    RunLoopUntilIdle();
    EXPECT_EQ(ime_service_.action_, fuchsia::ui::input::InputMethodAction::NEWLINE);
    EXPECT_FALSE(ime_service_.IsKeyboardShown());
  }

  {
    // Verify that showing keyboard results in the correct platform effect.
    const auto set_client_msg = R"(
        {
          "method": "TextInput.show"
        }
      )";
    FlutterPlatformMessage flutter_platform_message = {
        .struct_size = sizeof(FlutterPlatformMessage),
        .channel = embedder::kTextInputChannel,
        .message = reinterpret_cast<const uint8_t*>(set_client_msg),
        .message_size = strlen(set_client_msg),
        .response_handle = nullptr};
    text_delegate_->HandleFlutterTextInputChannelPlatformMessage(&flutter_platform_message);
    RunLoopUntilIdle();
    EXPECT_TRUE(ime_service_.IsKeyboardShown());
  }

  {
    // Verify that hiding keyboard results in the correct platform effect.
    const auto set_client_msg = R"(
        {
          "method": "TextInput.hide"
        }
      )";
    FlutterPlatformMessage flutter_platform_message = {
        .struct_size = sizeof(FlutterPlatformMessage),
        .channel = embedder::kTextInputChannel,
        .message = reinterpret_cast<const uint8_t*>(set_client_msg),
        .message_size = strlen(set_client_msg),
        .response_handle = nullptr};
    text_delegate_->HandleFlutterTextInputChannelPlatformMessage(&flutter_platform_message);
    RunLoopUntilIdle();
    EXPECT_FALSE(ime_service_.IsKeyboardShown());
  }

  {
    // Update the editing state from the Fuchsia platform side.
    fuchsia::ui::input::TextInputState state = {
        .revision = 42,
        .text = "Foo",
        .selection = fuchsia::ui::input::TextSelection{},
        .composing = fuchsia::ui::input::TextRange{},
    };
    auto input_event = std::make_unique<fuchsia::ui::input::InputEvent>();
    ime_service_.client_->DidUpdateState(std::move(state), std::move(input_event));
    RunLoopUntilIdle();
    EXPECT_EQ(
        R"({"method":"TextInputClient.updateEditingState","args":[7,{"text":"Foo","selectionBase":0,"selectionExtent":0,"selectionAffinity":"TextAffinity.upstream","selectionIsDirectional":true,"composingBase":-1,"composingExtent":-1}]})",
        MessageToString(last_message_));
  }

  {
    // Notify Flutter that the action key has been pressed.
    ime_service_.client_->OnAction(fuchsia::ui::input::InputMethodAction::DONE);
    RunLoopUntilIdle();
    EXPECT_EQ(R"({"method":"TextInputClient.performAction","args":[7,"TextInputAction.done"]})",
              MessageToString(last_message_));
  }
}

// Hands a few typical |KeyEvent|s to the text delegate. Regular key events are
// handled, "odd" key events are rejected (not handled).  "Handling" a key event
// means converting it to an appropriate |FlutterPlatformMessage| and forwarding it.
TEST_F(TextDelegateTest, OnAction) {
  {
    // A sensible key event is converted into a platform message.
    fuchsia::ui::input3::KeyEvent key_event;
    *key_event.mutable_type() = fuchsia::ui::input3::KeyEventType::PRESSED;
    *key_event.mutable_key() = fuchsia::input::Key::A;
    key_event.mutable_key_meaning()->set_codepoint('a');

    fuchsia::ui::input3::KeyEventStatus status;
    keyboard_service_.listener_->OnKeyEvent(
        std::move(key_event),
        [&status](fuchsia::ui::input3::KeyEventStatus s) { status = std::move(s); });
    RunLoopUntilIdle();
    EXPECT_EQ(fuchsia::ui::input3::KeyEventStatus::HANDLED, status);
    EXPECT_EQ(
        R"({"type":"keydown","keymap":"fuchsia","hidUsage":458756,"codePoint":97,"modifiers":0})",
        MessageToString(last_message_));
  }

  {
    // SYNC event is not handled.
    // This is currently expected, though we may need to change that behavior.
    fuchsia::ui::input3::KeyEvent key_event;
    *key_event.mutable_type() = fuchsia::ui::input3::KeyEventType::SYNC;

    fuchsia::ui::input3::KeyEventStatus status;
    keyboard_service_.listener_->OnKeyEvent(
        std::move(key_event),
        [&status](fuchsia::ui::input3::KeyEventStatus s) { status = std::move(s); });
    RunLoopUntilIdle();
    EXPECT_EQ(fuchsia::ui::input3::KeyEventStatus::NOT_HANDLED, status);
  }

  {
    // CANCEL event is not handled.
    // This is currently expected, though we may need to change that behavior.
    fuchsia::ui::input3::KeyEvent key_event;
    *key_event.mutable_type() = fuchsia::ui::input3::KeyEventType::CANCEL;

    fuchsia::ui::input3::KeyEventStatus status;
    keyboard_service_.listener_->OnKeyEvent(
        std::move(key_event),
        [&status](fuchsia::ui::input3::KeyEventStatus s) { status = std::move(s); });
    RunLoopUntilIdle();
    EXPECT_EQ(fuchsia::ui::input3::KeyEventStatus::NOT_HANDLED, status);
  }
}

}  // namespace embedder_testing
