// 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 "portable_ui_test.h"

#include <fuchsia/inspect/cpp/fidl.h>
#include <fuchsia/logger/cpp/fidl.h>
#include <fuchsia/tracing/provider/cpp/fidl.h>
#include <fuchsia/ui/app/cpp/fidl.h>
#include <lib/async/cpp/task.h>
#include <lib/sys/component/cpp/testing/realm_builder.h>
#include <lib/sys/component/cpp/testing/realm_builder_types.h>

#include "check_view.h"
#include "flutter/fml/logging.h"

namespace fuchsia_test_utils {
namespace {

// Types imported for the realm_builder library.
using component_testing::ChildOptions;
using component_testing::ChildRef;
using component_testing::ParentRef;
using component_testing::Protocol;
using component_testing::RealmRoot;
using component_testing::Route;

using fuchsia_test_utils::CheckViewExistsInSnapshot;

}  // namespace

void PortableUITest::SetUp(bool build_realm) {
  SetUpRealmBase();
  ExtendRealm();

  if (build_realm) {
    BuildRealm();
  }
}

void PortableUITest::BuildRealm() {
  realm_ = std::make_unique<RealmRoot>(realm_builder_.Build());
}

void PortableUITest::SetUpRealmBase() {
  FML_LOG(INFO) << "Setting up realm base";

  // Add Flutter JIT runner as a child of the RealmBuilder
  realm_builder_.AddChild(kFlutterJitRunner, kFlutterJitRunnerUrl);

  // Add environment providing the Flutter JIT runner
  fuchsia::component::decl::Environment flutter_runner_environment;
  flutter_runner_environment.set_name(kFlutterRunnerEnvironment);
  flutter_runner_environment.set_extends(
      fuchsia::component::decl::EnvironmentExtends::REALM);
  flutter_runner_environment.set_runners({});
  auto environment_runners = flutter_runner_environment.mutable_runners();

  // Add Flutter JIT runner to the environment
  fuchsia::component::decl::RunnerRegistration flutter_jit_runner_reg;
  flutter_jit_runner_reg.set_source(fuchsia::component::decl::Ref::WithChild(
      fuchsia::component::decl::ChildRef{.name = kFlutterJitRunner}));
  flutter_jit_runner_reg.set_source_name(kFlutterJitRunner);
  flutter_jit_runner_reg.set_target_name(kFlutterJitRunner);
  environment_runners->push_back(std::move(flutter_jit_runner_reg));
  auto realm_decl = realm_builder_.GetRealmDecl();
  if (!realm_decl.has_environments()) {
    realm_decl.set_environments({});
  }
  auto realm_environments = realm_decl.mutable_environments();
  realm_environments->push_back(std::move(flutter_runner_environment));
  realm_builder_.ReplaceRealmDecl(std::move(realm_decl));

  // Add test UI stack component.
  realm_builder_.AddChild(kTestUIStack, GetTestUIStackUrl());

  // // Route base system services to flutter and the test UI stack.
  realm_builder_.AddRoute(Route{
      .capabilities = {Protocol{fuchsia::logger::LogSink::Name_},
                       Protocol{fuchsia::inspect::InspectSink::Name_},
                       Protocol{fuchsia::sysmem::Allocator::Name_},
                       Protocol{fuchsia::tracing::provider::Registry::Name_},
                       Protocol{fuchsia::ui::input::ImeService::Name_},
                       Protocol{kPosixSocketProviderName},
                       Protocol{kVulkanLoaderServiceName},
                       component_testing::Directory{"config-data"}},
      .source = ParentRef(),
      .targets = {kFlutterJitRunnerRef, kTestUIStackRef}});

  // Route UI capabilities to test driver and Flutter runner
  realm_builder_.AddRoute(Route{
      .capabilities = {Protocol{fuchsia::ui::composition::Allocator::Name_},
                       Protocol{fuchsia::ui::composition::Flatland::Name_},
                       Protocol{fuchsia::ui::test::input::Registry::Name_},
                       Protocol{fuchsia::ui::test::scene::Controller::Name_},
                       Protocol{fuchsia::ui::display::singleton::Info::Name_},
                       Protocol{kPointerInjectorRegistryName}},
      .source = kTestUIStackRef,
      .targets = {ParentRef(), kFlutterJitRunnerRef}});
}

void PortableUITest::ProcessViewGeometryResponse(
    fuchsia::ui::observation::geometry::WatchResponse response) {
  // Process update if no error
  if (!response.has_error()) {
    std::vector<fuchsia::ui::observation::geometry::ViewTreeSnapshot>* updates =
        response.mutable_updates();
    if (updates && !updates->empty()) {
      last_view_tree_snapshot_ = std::move(updates->back());
    }
  } else {
    // Otherwise process error
    const auto& error = response.error();
    if (error | fuchsia::ui::observation::geometry::Error::CHANNEL_OVERFLOW) {
      FML_LOG(INFO) << "View Tree watcher channel overflowed";
    } else if (error |
               fuchsia::ui::observation::geometry::Error::BUFFER_OVERFLOW) {
      FML_LOG(INFO) << "View Tree watcher buffer overflowed";
    } else if (error |
               fuchsia::ui::observation::geometry::Error::VIEWS_OVERFLOW) {
      // This one indicates some possible data loss, so we log with a high
      // severity
      FML_LOG(WARNING)
          << "View Tree watcher attempted to report too many views";
    }
  }
}

void PortableUITest::WatchViewGeometry() {
  FML_CHECK(view_tree_watcher_)
      << "View Tree watcher must be registered before calling Watch()";

  view_tree_watcher_->Watch([this](auto response) {
    ProcessViewGeometryResponse(std::move(response));
    WatchViewGeometry();
  });
}

bool PortableUITest::HasViewConnected(zx_koid_t view_ref_koid) {
  return last_view_tree_snapshot_.has_value() &&
         CheckViewExistsInSnapshot(*last_view_tree_snapshot_, view_ref_koid);
}

void PortableUITest::LaunchClient() {
  scene_provider_ =
      realm_->component().Connect<fuchsia::ui::test::scene::Controller>();
  scene_provider_.set_error_handler([](auto) {
    FML_LOG(ERROR) << "Error from test scene provider: "
                   << &zx_status_get_string;
  });

  fuchsia::ui::test::scene::ControllerAttachClientViewRequest request;
  request.set_view_provider(
      realm_->component().Connect<fuchsia::ui::app::ViewProvider>());
  scene_provider_->RegisterViewTreeWatcher(view_tree_watcher_.NewRequest(),
                                           []() {});
  scene_provider_->AttachClientView(
      std::move(request), [this](auto client_view_ref_koid) {
        client_root_view_ref_koid_ = client_view_ref_koid;
      });

  FML_LOG(INFO) << "Waiting for client view ref koid";
  RunLoopUntil([this] { return client_root_view_ref_koid_.has_value(); });

  WatchViewGeometry();

  FML_LOG(INFO) << "Waiting for client view to connect";
  // Wait for the client view to get attached to the view tree.
  RunLoopUntil(
      [this] { return HasViewConnected(*client_root_view_ref_koid_); });
  FML_LOG(INFO) << "Client view has rendered";
}

void PortableUITest::LaunchClientWithEmbeddedView() {
  LaunchClient();
  // At this point, the parent view must have rendered, so we just need to wait
  // for the embedded view.
  RunLoopUntil([this] {
    if (!last_view_tree_snapshot_.has_value() ||
        !last_view_tree_snapshot_->has_views()) {
      return false;
    }

    if (!client_root_view_ref_koid_.has_value()) {
      return false;
    }

    for (const auto& view : last_view_tree_snapshot_->views()) {
      if (!view.has_view_ref_koid() ||
          view.view_ref_koid() != *client_root_view_ref_koid_) {
        continue;
      }

      if (view.children().empty()) {
        return false;
      }

      // NOTE: We can't rely on the presence of the child view in
      // `view.children()` to guarantee that it has rendered. The child view
      // also needs to be present in `last_view_tree_snapshot_->views`.
      return std::count_if(
                 last_view_tree_snapshot_->views().begin(),
                 last_view_tree_snapshot_->views().end(),
                 [view_to_find =
                      view.children().back()](const auto& view_to_check) {
                   return view_to_check.has_view_ref_koid() &&
                          view_to_check.view_ref_koid() == view_to_find;
                 }) > 0;
    }

    return false;
  });

  FML_LOG(INFO) << "Embedded view has rendered";
}

void PortableUITest::RegisterTouchScreen() {
  FML_LOG(INFO) << "Registering fake touch screen";
  input_registry_ =
      realm_->component().Connect<fuchsia::ui::test::input::Registry>();
  input_registry_.set_error_handler([](auto) {
    FML_LOG(ERROR) << "Error from input helper: " << &zx_status_get_string;
  });

  bool touchscreen_registered = false;
  fuchsia::ui::test::input::RegistryRegisterTouchScreenRequest request;
  request.set_device(fake_touchscreen_.NewRequest());
  input_registry_->RegisterTouchScreen(
      std::move(request),
      [&touchscreen_registered]() { touchscreen_registered = true; });

  RunLoopUntil([&touchscreen_registered] { return touchscreen_registered; });
  FML_LOG(INFO) << "Touchscreen registered";
}

void PortableUITest::RegisterMouse() {
  FML_LOG(INFO) << "Registering fake mouse";
  input_registry_ =
      realm_->component().Connect<fuchsia::ui::test::input::Registry>();
  input_registry_.set_error_handler([](auto) {
    FML_LOG(ERROR) << "Error from input helper: " << &zx_status_get_string;
  });

  bool mouse_registered = false;
  fuchsia::ui::test::input::RegistryRegisterMouseRequest request;
  request.set_device(fake_mouse_.NewRequest());
  input_registry_->RegisterMouse(
      std::move(request), [&mouse_registered]() { mouse_registered = true; });

  RunLoopUntil([&mouse_registered] { return mouse_registered; });
  FML_LOG(INFO) << "Mouse registered";
}

void PortableUITest::RegisterKeyboard() {
  FML_LOG(INFO) << "Registering fake keyboard";
  input_registry_ =
      realm_->component().Connect<fuchsia::ui::test::input::Registry>();
  input_registry_.set_error_handler([](auto) {
    FML_LOG(ERROR) << "Error from input helper: " << &zx_status_get_string;
  });

  bool keyboard_registered = false;
  fuchsia::ui::test::input::RegistryRegisterKeyboardRequest request;
  request.set_device(fake_keyboard_.NewRequest());
  input_registry_->RegisterKeyboard(
      std::move(request),
      [&keyboard_registered]() { keyboard_registered = true; });

  RunLoopUntil([&keyboard_registered] { return keyboard_registered; });
  FML_LOG(INFO) << "Keyboard registered";
}

void PortableUITest::InjectTap(int32_t x, int32_t y) {
  fuchsia::ui::test::input::TouchScreenSimulateTapRequest tap_request;
  tap_request.mutable_tap_location()->x = x;
  tap_request.mutable_tap_location()->y = y;

  FML_LOG(INFO) << "Injecting tap at (" << tap_request.tap_location().x << ", "
                << tap_request.tap_location().y << ")";
  fake_touchscreen_->SimulateTap(std::move(tap_request), [this]() {
    ++touch_injection_request_count_;
    FML_LOG(INFO) << "*** Tap injected, count: "
                  << touch_injection_request_count_;
  });
}

void PortableUITest::SimulateMouseEvent(
    std::vector<fuchsia::ui::test::input::MouseButton> pressed_buttons,
    int movement_x,
    int movement_y) {
  fuchsia::ui::test::input::MouseSimulateMouseEventRequest request;
  request.set_pressed_buttons(std::move(pressed_buttons));
  request.set_movement_x(movement_x);
  request.set_movement_y(movement_y);

  FML_LOG(INFO) << "Injecting mouse input";

  fake_mouse_->SimulateMouseEvent(
      std::move(request), [] { FML_LOG(INFO) << "Mouse event injected"; });
}

void PortableUITest::SimulateMouseScroll(
    std::vector<fuchsia::ui::test::input::MouseButton> pressed_buttons,
    int scroll_x,
    int scroll_y,
    bool use_physical_units) {
  FML_LOG(INFO) << "Requesting mouse scroll";
  fuchsia::ui::test::input::MouseSimulateMouseEventRequest request;
  request.set_pressed_buttons(std::move(pressed_buttons));
  if (use_physical_units) {
    request.set_scroll_h_physical_pixel(scroll_x);
    request.set_scroll_v_physical_pixel(scroll_y);
  } else {
    request.set_scroll_h_detent(scroll_x);
    request.set_scroll_v_detent(scroll_y);
  }

  fake_mouse_->SimulateMouseEvent(std::move(request), [] {
    FML_LOG(INFO) << "Mouse scroll event injected";
  });
}

void PortableUITest::SimulateTextEntry(std::string text) {
  FML_LOG(INFO) << "Sending text request";
  bool done = false;

  fuchsia::ui::test::input::KeyboardSimulateUsAsciiTextEntryRequest request;
  request.set_text(text);
  fake_keyboard_->SimulateUsAsciiTextEntry(std::move(request),
                                           [&done]() { done = true; });

  RunLoopUntil([&] { return done; });
  FML_LOG(INFO) << "Text request sent";
}

}  // namespace fuchsia_test_utils
