// Copyright 2021 The Fuchsia 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/accessibility/semantics/cpp/fidl.h>
#include <fuchsia/buildinfo/cpp/fidl.h>
#include <fuchsia/cobalt/cpp/fidl.h>
#include <fuchsia/fonts/cpp/fidl.h>
#include <fuchsia/input/injection/cpp/fidl.h>
#include <fuchsia/input/virtualkeyboard/cpp/fidl.h>
#include <fuchsia/intl/cpp/fidl.h>
#include <fuchsia/logger/cpp/fidl.h>
#include <fuchsia/memorypressure/cpp/fidl.h>
#include <fuchsia/net/interfaces/cpp/fidl.h>
#include <fuchsia/netstack/cpp/fidl.h>
#include <fuchsia/posix/socket/cpp/fidl.h>
#include <fuchsia/scheduler/cpp/fidl.h>
#include <fuchsia/sysmem/cpp/fidl.h>
#include <fuchsia/tracing/provider/cpp/fidl.h>
#include <fuchsia/ui/app/cpp/fidl.h>
#include <fuchsia/ui/input/cpp/fidl.h>
#include <fuchsia/ui/scenic/cpp/fidl.h>
#include <fuchsia/web/cpp/fidl.h>
#include <lib/async/cpp/task.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/sys/component/cpp/testing/realm_builder.h>
#include <lib/sys/component/cpp/testing/realm_builder_types.h>
#include <lib/syslog/cpp/macros.h>
#include <zircon/errors.h>
#include <zircon/types.h>
#include <zircon/utc.h>

#include <iostream>
#include <type_traits>

#include <gtest/gtest.h>
#include <src/lib/fostr/fidl/fuchsia/ui/gfx/formatting.h>
#include <test/virtualkeyboard/cpp/fidl.h>

#include "src/lib/testing/loop_fixture/real_loop_fixture.h"
#include "src/ui/input/testing/fake_input_report_device/fake.h"
#include "src/ui/input/testing/fake_input_report_device/reports_reader.h"
#include "src/ui/testing/ui_test_manager/ui_test_manager.h"

// This test exercises the virtual keyboard visibility interactions between Chromium and Root
// Presenter. It is a multi-component test, and carefully avoids sleeping or polling for component
// coordination.
// - It runs real Root Presenter, Input Pipeline and Scenic components.
// - It uses a fake display controller; the physical device is unused.
//
// Components involved
// - This test program
// - Root Presenter (serves virtual keyboard)
// - Input Pipeline (serves touch input)
// - Scenic
// - WebEngine (built from Chromium)
//
// Setup sequence
// - The test sets up a view hierarchy with two views:
//   - Top level scene, owned by Root Presenter.
//   - Bottom view, owned by Chromium.

namespace {

using test::virtualkeyboard::InputPositionListener;
using ScenicEvent = fuchsia::ui::scenic::Event;
using GfxEvent = fuchsia::ui::gfx::Event;

// Types imported for the realm_builder library.
using component_testing::ChildRef;
using component_testing::LocalComponent;
using component_testing::LocalComponentHandles;
using component_testing::ParentRef;
using component_testing::Protocol;
using component_testing::Realm;
using component_testing::Route;

// Alias for Component child name as provided to Realm Builder.
using ChildName = std::string;

// Alias for Component Legacy URL as provided to Realm Builder.
using LegacyUrl = std::string;

constexpr auto kResponseListener = "response_listener";

// The type used to measure UTC time. The integer value here does not matter so
// long as it differs from the ZX_CLOCK_MONOTONIC=0 defined by Zircon.
using time_utc = zx::basic_time<1>;

// Combines all vectors in `vecs` into one.
template <typename T>
std::vector<T> merge(std::initializer_list<std::vector<T>> vecs) {
  std::vector<T> result;
  for (auto v : vecs) {
    result.insert(result.end(), v.begin(), v.end());
  }
  return result;
}

// This component implements the interface for a RealmBuilder
// LocalComponent and the test.virtualkeyboard.InputPositionListener
// protocol.
class InputPositionListenerServer : public InputPositionListener, public LocalComponent {
 public:
  explicit InputPositionListenerServer(async_dispatcher_t* dispatcher) : dispatcher_(dispatcher) {}

  // |test::virtualkeyboard::InputPositionListener|
  void Notify(test::virtualkeyboard::BoundingBox bounding_box) override {
    input_position_ = std::move(bounding_box);
  }

  // |LocalComponent::Start|
  void Start(std::unique_ptr<LocalComponentHandles> local_handles) override {
    // When this component starts, add a binding to the test.touch.ResponseListener
    // protocol to this component's outgoing directory.
    FX_CHECK(local_handles->outgoing()->AddPublicService(
                 fidl::InterfaceRequestHandler<InputPositionListener>([this](auto request) {
                   bindings_.AddBinding(this, std::move(request), dispatcher_);
                 })) == ZX_OK);
    local_handle_ = std::move(local_handles);
  }

  const std::optional<test::virtualkeyboard::BoundingBox>& input_position() const {
    return input_position_;
  }

 private:
  async_dispatcher_t* dispatcher_ = nullptr;
  std::unique_ptr<LocalComponentHandles> local_handle_;
  std::optional<test::virtualkeyboard::BoundingBox> input_position_;
  fidl::BindingSet<InputPositionListener> bindings_;
};

class VirtualKeyboardBase : public gtest::RealLoopFixture {
 protected:
  VirtualKeyboardBase() = default;

  ~VirtualKeyboardBase() override {
    FX_CHECK(injection_count_ > 0) << "injection expected but didn't happen.";
  }

  void SetUp() override {
    FX_LOGS(INFO) << "Setting up test case";
    ui_testing::UITestManager::Config config;
    config.accessibility_owner = ui_testing::UITestManager::AccessibilityOwnerType::FAKE;
    config.use_input = true;
    config.scene_owner = ui_testing::UITestManager::SceneOwnerType::ROOT_PRESENTER;
    config.ui_to_client_services = {fuchsia::ui::scenic::Scenic::Name_,
                                    fuchsia::accessibility::semantics::SemanticsManager::Name_,
                                    fuchsia::ui::input3::Keyboard::Name_,
                                    fuchsia::ui::input::ImeService::Name_,
                                    fuchsia::input::virtualkeyboard::Manager::Name_,
                                    fuchsia::input::virtualkeyboard::ControllerCreator::Name_};
    ui_test_manager_ = std::make_unique<ui_testing::UITestManager>(std::move(config));

    // Build realm.
    FX_LOGS(INFO) << "Building realm";
    realm_ = std::make_unique<Realm>(ui_test_manager_->AddSubrealm());
    BuildRealm(this->GetTestComponents(), this->GetTestRoutes(), this->GetTestV2Components());

    // Get the display dimensions
    scenic_ = realm_exposed_services()->Connect<fuchsia::ui::scenic::Scenic>();
    scenic_->GetDisplayInfo([this](fuchsia::ui::gfx::DisplayInfo display_info) {
      display_width_ = display_info.width_in_px;
      display_height_ = display_info.height_in_px;
      FX_LOGS(INFO) << "Got display_width = " << *display_width_
                    << " and display_height = " << *display_height_;
    });
    RunLoopUntil([this] { return display_width_.has_value() && display_height_.has_value(); });

    RegisterInjectionDevice();
  }

  // Subclass should implement this method to add components to the test realm
  // next to the base ones added.
  virtual std::vector<std::pair<ChildName, LegacyUrl>> GetTestComponents() { return {}; }

  // Subclass should implement this method to add capability routes to the test
  // realm next to the base ones added.
  virtual std::vector<Route> GetTestRoutes() { return {}; }

  // Subclass should implement this method to add components to the test realm
  // next to the base ones added.
  virtual std::vector<std::pair<ChildName, std::string>> GetTestV2Components() { return {}; }

  void RegisterInjectionDevice() {
    registry_ = realm_exposed_services()->Connect<fuchsia::input::injection::InputDeviceRegistry>();
    registry_.set_error_handler([](zx_status_t status) {
      FX_LOGS(ERROR) << "Input device registry error: " << zx_status_get_string(status);
    });
    // Create a FakeInputDevice
    fake_input_device_ = std::make_unique<fake_input_report_device::FakeInputDevice>(
        input_device_ptr_.NewRequest(), dispatcher());

    // Set descriptor
    auto device_descriptor = std::make_unique<fuchsia::input::report::DeviceDescriptor>();
    auto touch = device_descriptor->mutable_touch()->mutable_input();
    touch->set_touch_type(fuchsia::input::report::TouchType::TOUCHSCREEN);
    touch->set_max_contacts(10);

    fuchsia::input::report::Axis x_axis;
    x_axis.unit.type = fuchsia::input::report::UnitType::NONE;
    x_axis.unit.exponent = 0;
    x_axis.range.min = 0;
    x_axis.range.max = display_width();

    fuchsia::input::report::Axis y_axis;
    y_axis.unit.type = fuchsia::input::report::UnitType::NONE;
    y_axis.unit.exponent = 0;
    y_axis.range.min = 0;
    y_axis.range.max = display_height();

    fuchsia::input::report::ContactInputDescriptor contact;
    contact.set_position_x(x_axis);
    contact.set_position_y(y_axis);
    contact.set_pressure(x_axis);

    touch->mutable_contacts()->push_back(std::move(contact));

    fake_input_device_->SetDescriptor(std::move(device_descriptor));

    // Register the FakeInputDevice
    registry_->Register(std::move(input_device_ptr_));
    FX_LOGS(INFO) << "Registered touchscreen with x touch range = (" << x_axis.range.min << ", "
                  << x_axis.range.max << ") "
                  << "and y touch range = (" << y_axis.range.min << ", " << y_axis.range.max
                  << ").";
  }

  // Inject directly into Input Pipeline, using fuchsia.input.injection FIDLs.
  void InjectInput(int32_t x, int32_t y) {
    fuchsia::input::report::ContactInputReport contact_input_report;
    contact_input_report.set_contact_id(1);
    contact_input_report.set_position_x(x);
    contact_input_report.set_position_y(y);

    fuchsia::input::report::TouchInputReport touch_input_report;
    auto contacts = touch_input_report.mutable_contacts();
    contacts->push_back(std::move(contact_input_report));

    fuchsia::input::report::InputReport input_report;
    input_report.set_touch(std::move(touch_input_report));

    std::vector<fuchsia::input::report::InputReport> input_reports;
    input_reports.push_back(std::move(input_report));

    fuchsia::input::report::TouchInputReport remove_touch_input_report;
    fuchsia::input::report::InputReport remove_input_report;
    remove_input_report.set_touch(std::move(remove_touch_input_report));
    input_reports.push_back(std::move(remove_input_report));
    fake_input_device_->SetReports(std::move(input_reports));

    ++injection_count_;
    FX_LOGS(INFO) << "*** Tap injected, count: " << injection_count_;
  }

  InputPositionListenerServer* response_listener() { return response_listener_.get(); }

  // Guaranteed to be initialized after SetUp().
  uint32_t display_width() const { return *display_width_; }
  uint32_t display_height() const { return *display_height_; }

  ui_testing::UITestManager* ui_test_manager() { return ui_test_manager_.get(); }
  sys::ServiceDirectory* realm_exposed_services() { return realm_exposed_services_.get(); }

 private:
  void BuildRealm(const std::vector<std::pair<ChildName, LegacyUrl>>& components,
                  const std::vector<Route>& routes,
                  const std::vector<std::pair<ChildName, std::string>>& v2_components) {
    // Key part of service setup: have this test component vend the
    // |ResponseListener| service in the constructed realm.
    response_listener_ = std::make_unique<InputPositionListenerServer>(dispatcher());
    realm_->AddLocalChild(kResponseListener, response_listener_.get());

    // Add components specific for this test case to the realm.
    for (const auto& [name, component] : components) {
      realm_->AddLegacyChild(name, component);
    }

    for (const auto& [name, component] : v2_components) {
      realm_->AddChild(name, component);
    }

    // Add the necessary routing for each of the extra components added above.
    for (const auto& route : routes) {
      realm_->AddRoute(route);
    }

    ui_test_manager_->BuildRealm();
    realm_exposed_services_ = ui_test_manager_->TakeExposedServicesDirectory();
  }

  // Configures a RealmBuilder realm and manages scene on behalf of the test
  // fixture.
  std::unique_ptr<ui_testing::UITestManager> ui_test_manager_;

  // Exposed services directory for the realm owned by `ui_test_manager_`.
  std::unique_ptr<sys::ServiceDirectory> realm_exposed_services_;

  // Configured by the test fixture, and attached as a subrealm to ui test
  // manager's realm.
  std::unique_ptr<Realm> realm_;

  std::unique_ptr<InputPositionListenerServer> response_listener_;

  int injection_count_ = 0;

  fuchsia::ui::scenic::ScenicPtr scenic_;

  std::optional<uint32_t> display_width_;
  std::optional<uint32_t> display_height_;

  fuchsia::input::injection::InputDeviceRegistryPtr registry_;
  std::unique_ptr<fake_input_report_device::FakeInputDevice> fake_input_device_;
  fuchsia::input::report::InputDevicePtr input_device_ptr_;
};

class WebEngineTest : public VirtualKeyboardBase {
 protected:
  std::vector<std::pair<ChildName, LegacyUrl>> GetTestComponents() override {
    return {
        std::make_pair(kFontsProvider, kFontsProviderUrl),
        std::make_pair(kWebContextProvider, kWebContextProviderUrl),
    };
  }

  std::vector<std::pair<ChildName, LegacyUrl>> GetTestV2Components() override {
    return {
        std::make_pair(kWebVirtualKeyboardClient, kWebVirtualKeyboardUrl),
        std::make_pair(kBuildInfoProvider, kBuildInfoProviderUrl),
        std::make_pair(kIntl, kIntlUrl),
        std::make_pair(kMemoryPressureProvider, kMemoryPressureProviderUrl),
        std::make_pair(kMockCobalt, kMockCobaltUrl),
        std::make_pair(kNetstack, kNetstackUrl),
    };
  }

  std::vector<Route> GetTestRoutes() override {
    return merge({
        GetWebEngineRoutes(ChildRef{kWebVirtualKeyboardClient}),
        {
            {
                .capabilities = {Protocol{fuchsia::ui::app::ViewProvider::Name_}},
                .source = ChildRef{kWebVirtualKeyboardClient},
                .targets = {ParentRef()},
            },
            {
                .capabilities = {Protocol{fuchsia::logger::LogSink::Name_}},
                .source = ParentRef(),
                .targets = {ChildRef{kWebVirtualKeyboardClient}},
            },
        },
    });
  }

  // Injects an input event, and posts a task to retry after `kTapRetryInterval`.
  //
  // We post the retry task because the first input event we send to WebEngine may be lost.
  // There is no guarantee that, just because the web app has returned the location of the
  // input box, that Chromium is actually ready to receive events from Scenic.
  void TryInject(int32_t x, int32_t y) {
    InjectInput(x, y);
    inject_retry_task_.emplace(
        [this, x, y](auto dispatcher, auto task, auto status) { TryInject(x, y); });
    FX_CHECK(inject_retry_task_->PostDelayed(dispatcher(), kTapRetryInterval) == ZX_OK);
  }

  void CancelInject() { inject_retry_task_.reset(); }

  // Routes needed to setup Chromium client.
  static std::vector<Route> GetWebEngineRoutes(ChildRef target) {
    return {
        {.capabilities = {Protocol{test::virtualkeyboard::InputPositionListener::Name_}},
         .source = ChildRef{kResponseListener},
         .targets = {target}},
        {.capabilities = {Protocol{fuchsia::fonts::Provider::Name_}},
         .source = ChildRef{kFontsProvider},
         .targets = {target}},
        {.capabilities = {Protocol{fuchsia::ui::input3::Keyboard::Name_},
                          Protocol{fuchsia::ui::input::ImeService::Name_}},
         .source = ParentRef(),
         .targets = {target}},
        {.capabilities = {Protocol{fuchsia::intl::PropertyProvider::Name_}},
         .source = ChildRef{kIntl},
         .targets = {target}},
        {.capabilities = {Protocol{fuchsia::input::virtualkeyboard::Manager::Name_},
                          Protocol{fuchsia::input::virtualkeyboard::ControllerCreator::Name_}},
         .source = ParentRef(),
         .targets = {ChildRef{kWebVirtualKeyboardClient}, ChildRef{kWebContextProvider}}},
        {.capabilities = {Protocol{fuchsia::memorypressure::Provider::Name_}},
         .source = ChildRef{kMemoryPressureProvider},
         .targets = {target}},
        {.capabilities = {Protocol{fuchsia::posix::socket::Provider::Name_},
                          Protocol{fuchsia::netstack::Netstack::Name_},
                          Protocol{fuchsia::net::interfaces::State::Name_}},
         .source = ChildRef{kNetstack},
         .targets = {target}},
        {.capabilities = {Protocol{fuchsia::accessibility::semantics::SemanticsManager::Name_}},
         .source = ParentRef(),
         .targets = {target}},
        {.capabilities = {Protocol{fuchsia::web::ContextProvider::Name_}},
         .source = ChildRef{kWebContextProvider},
         .targets = {target}},
        {.capabilities = {Protocol{fuchsia::cobalt::LoggerFactory::Name_}},
         .source = ChildRef{kMockCobalt},
         .targets = {ChildRef{kMemoryPressureProvider}}},
        {.capabilities = {Protocol{fuchsia::sysmem::Allocator::Name_}},
         .source = ParentRef(),
         .targets = {ChildRef{kMemoryPressureProvider}, ChildRef{kWebVirtualKeyboardClient}}},
        {.capabilities = {Protocol{fuchsia::tracing::provider::Registry::Name_},
                          Protocol{fuchsia::scheduler::ProfileProvider::Name_}},
         .source = ParentRef(),
         .targets = {ChildRef{kMemoryPressureProvider}}},
        {.capabilities = {Protocol{fuchsia::ui::scenic::Scenic::Name_}},
         .source = ParentRef(),
         .targets = {target}},
        {.capabilities = {Protocol{fuchsia::buildinfo::Provider::Name_}},
         .source = ChildRef{kBuildInfoProvider},
         .targets = {target, ChildRef{kWebContextProvider}}},
        {
            .capabilities = {Protocol{fuchsia::logger::LogSink::Name_}},
            .source = ParentRef(),
            .targets = {ChildRef{kWebContextProvider}},
        },
    };
  }

 private:
  static constexpr auto kMockCobalt = "cobalt";
  static constexpr auto kMockCobaltUrl = "#meta/mock_cobalt.cm";

  static constexpr auto kWebVirtualKeyboardClient = "web_virtual_keyboard_client";
  static constexpr auto kWebVirtualKeyboardUrl = "#meta/web-virtual-keyboard-client.cm";

  static constexpr auto kFontsProvider = "fonts_provider";
  static constexpr auto kFontsProviderUrl = "fuchsia-pkg://fuchsia.com/fonts#meta/fonts.cmx";

  static constexpr auto kIntl = "intl";
  static constexpr auto kIntlUrl = "#meta/intl_property_manager.cm";

  static constexpr auto kMemoryPressureProvider = "memory_pressure_provider";
  static constexpr auto kMemoryPressureProviderUrl = "#meta/memory_monitor.cm";

  static constexpr auto kNetstack = "netstack";
  static constexpr auto kNetstackUrl = "#meta/netstack.cm";

  static constexpr auto kWebContextProvider = "web_context_provider";
  static constexpr auto kWebContextProviderUrl =
      "fuchsia-pkg://fuchsia.com/web_engine#meta/context_provider.cmx";

  static constexpr auto kBuildInfoProvider = "build_info_provider";
  static constexpr auto kBuildInfoProviderUrl = "#meta/fake_build_info.cm";

  // The typical latency on devices we've tested is ~60 msec. The retry interval is chosen to be
  // a) Long enough that it's unlikely that we send a new tap while a previous tap is still being
  //    processed. That is, it should be far more likely that a new tap is sent because the first
  //    tap was lost, than because the system is just running slowly.
  // b) Short enough that we don't slow down tryjobs.
  //
  // The first property is important to avoid skewing the latency metrics that we collect.
  // For an explanation of why a tap might be lost, see the documentation for TryInject().
  static constexpr auto kTapRetryInterval = zx::sec(1);

  std::optional<async::Task> inject_retry_task_;
};

TEST_F(WebEngineTest, ShowAndHideKeyboard) {
  // Launch the chromium view.
  ui_test_manager()->InitializeScene();
  FX_LOGS(INFO) << "Waiting for client view to render";
  RunLoopUntil([this] { return ui_test_manager()->ClientViewIsRendering(); });

  FX_LOGS(INFO) << "Waiting for client view to be focused";
  RunLoopUntil([this] { return ui_test_manager()->ClientViewIsFocused(); });

  FX_LOGS(INFO) << "Getting initial keyboard state";
  std::optional<bool> is_keyboard_visible;
  auto virtualkeyboard_manager =
      realm_exposed_services()->Connect<fuchsia::input::virtualkeyboard::Manager>();
  virtualkeyboard_manager->WatchTypeAndVisibility(
      [&is_keyboard_visible](auto text_type, auto is_visible) {
        is_keyboard_visible = is_visible;
      });
  RunLoopUntil([&]() { return is_keyboard_visible.has_value(); });
  ASSERT_FALSE(is_keyboard_visible.value());
  is_keyboard_visible.reset();

  FX_LOGS(INFO) << "Getting input box position";
  RunLoopUntil([this]() { return response_listener()->input_position().has_value(); });

  FX_LOGS(INFO) << "Tapping _inside_ input box";
  auto input_pos = *response_listener()->input_position();
  int32_t input_center_x_local = (input_pos.x0 + input_pos.x1) / 2;
  int32_t input_center_y_local = (input_pos.y0 + input_pos.y1) / 2;
  TryInject(input_center_x_local, input_center_y_local);

  FX_LOGS(INFO) << "Waiting for keyboard to be visible";
  virtualkeyboard_manager->WatchTypeAndVisibility(
      [&is_keyboard_visible](auto text_type, auto is_visible) {
        is_keyboard_visible = is_visible;
      });
  RunLoopUntil([&]() { return is_keyboard_visible.has_value(); });
  ASSERT_TRUE(is_keyboard_visible.value());
  CancelInject();
  is_keyboard_visible.reset();

  FX_LOGS(INFO) << "Tapping _outside_ input box";
  TryInject(input_pos.x1 + 1, input_pos.y1 + 1);

  FX_LOGS(INFO) << "Waiting for keyboard to be hidden";
  virtualkeyboard_manager->WatchTypeAndVisibility(
      [&is_keyboard_visible](auto text_type, auto is_visible) {
        is_keyboard_visible = is_visible;
      });
  RunLoopUntil([&]() { return is_keyboard_visible.has_value(); });
  ASSERT_FALSE(is_keyboard_visible.value());
  CancelInject();
}

}  // namespace
