// 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 "src/ui/scenic/lib/input/pointerinjector_registry.h"

#include <lib/syslog/cpp/macros.h>

#include "src/ui/scenic/lib/utils/helpers.h"

namespace scenic_impl::input {

namespace {

bool IsValidConfig(const fuchsia::ui::pointerinjector::Config& config) {
  if (!config.has_device_id() || !config.has_device_type() || !config.has_context() ||
      !config.has_target() || !config.has_viewport() || !config.has_dispatch_policy()) {
    FX_LOGS(ERROR) << "InjectorRegistry::Register : Argument |config| is incomplete.";
    return false;
  }

  if (config.dispatch_policy() != fuchsia::ui::pointerinjector::DispatchPolicy::EXCLUSIVE_TARGET &&
      config.dispatch_policy() !=
          fuchsia::ui::pointerinjector::DispatchPolicy::TOP_HIT_AND_ANCESTORS_IN_TARGET) {
    FX_LOGS(ERROR) << "InjectorRegistry::Register : Only EXCLUSIVE_TARGET and "
                      "TOP_HIT_AND_ANCESTORS_IN_TARGET DispatchPolicy is supported.";
    return false;
  }

  if (config.device_type() != fuchsia::ui::pointerinjector::DeviceType::TOUCH) {
    FX_LOGS(ERROR) << "InjectorRegistry::Register : Only DeviceType TOUCH is supported.";
    return false;
  }

  if (!config.context().is_view() || !config.target().is_view()) {
    FX_LOGS(ERROR) << "InjectorRegistry::Register : Argument |config.context| or |config.target| "
                      "is not a view. Only views are supported.";
    return false;
  }

  if (Injector::IsValidViewport(config.viewport()) != ZX_OK) {
    // Errors printed in IsValidViewport. Just return result here.
    return false;
  }

  return true;
}

}  // namespace

PointerinjectorRegistry::PointerinjectorRegistry(sys::ComponentContext* context,
                                                 InjectFunc inject_touch_exclusive,
                                                 InjectFunc inject_touch_hit_tested,
                                                 inspect::Node inspect_node)
    : inject_touch_exclusive_(std::move(inject_touch_exclusive)),
      inject_touch_hit_tested_(std::move(inject_touch_hit_tested)),
      inspect_node_(std::move(inspect_node)) {
  if (context) {
    // Adding the service here is safe since the PointerinjectorRegistry instance in InputSystem is
    // created at construction time..
    context->outgoing()->AddPublicService(injector_registry_.GetHandler(this));
  }
}

void PointerinjectorRegistry::Register(
    fuchsia::ui::pointerinjector::Config config,
    fidl::InterfaceRequest<fuchsia::ui::pointerinjector::Device> injector,
    RegisterCallback callback) {
  if (!IsValidConfig(config)) {
    // Errors printed inside IsValidConfig. Just return here.
    return;
  }

  // Check connectivity here, since injector doesn't have access to it.
  const zx_koid_t context_koid = utils::ExtractKoid(config.context().view());
  const zx_koid_t target_koid = utils::ExtractKoid(config.target().view());
  if (context_koid == ZX_KOID_INVALID || target_koid == ZX_KOID_INVALID) {
    FX_LOGS(ERROR) << "InjectorRegistry::Register : Argument |config.context| or |config.target| "
                      "was invalid.";
    return;
  }
  if (!view_tree_snapshot_->IsDescendant(target_koid, context_koid)) {
    FX_LOGS(ERROR) << "InjectorRegistry::Register : Argument |config.context| must be connected to "
                      "the Scene, and |config.target| must be a descendant of |config.context|";
    return;
  }

  // TODO(fxbug.dev/50348): Add a callback to kill the channel immediately if connectivity breaks.

  const InjectorId id = ++last_injector_id_;
  InjectorSettings settings{.dispatch_policy = config.dispatch_policy(),
                            .device_id = config.device_id(),
                            .device_type = config.device_type(),
                            .context_koid = context_koid,
                            .target_koid = target_koid};
  Viewport viewport{
      .extents = {config.viewport().extents()},
      .context_from_viewport_transform =
          ColumnMajorMat3VectorToMat4(config.viewport().viewport_to_context_transform()),
  };

  fit::function<void(const InternalPointerEvent&, StreamId)> inject_func;
  switch (settings.dispatch_policy) {
    case fuchsia::ui::pointerinjector::DispatchPolicy::EXCLUSIVE_TARGET:
      inject_func = [this](const InternalPointerEvent& event, StreamId stream_id) {
        inject_touch_exclusive_(event, stream_id);
      };
      break;
    case fuchsia::ui::pointerinjector::DispatchPolicy::TOP_HIT_AND_ANCESTORS_IN_TARGET:
      inject_func = [this](const InternalPointerEvent& event, StreamId stream_id) {
        inject_touch_hit_tested_(event, stream_id);
      };
      break;
    default:
      FX_CHECK(false) << "Should never be reached.";
      break;
  }

  const auto [it, success] = injectors_.try_emplace(
      id, inspect_node_.CreateChild(inspect_node_.UniqueName("injector-")), std::move(settings),
      std::move(viewport), std::move(injector),
      /*is_descendant_and_connected*/
      [this](zx_koid_t descendant, zx_koid_t ancestor) {
        return view_tree_snapshot_->IsDescendant(descendant, ancestor);
      },
      std::move(inject_func),
      /*on_channel_closed*/
      [this, id] { injectors_.erase(id); });
  FX_CHECK(success) << "Injector already exists.";

  callback();
}

}  // namespace scenic_impl::input
