// Copyright 2018 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/helper.h"

#include "src/ui/lib/escher/util/type_utils.h"
#include "src/ui/scenic/lib/gfx/resources/compositor/layer.h"
#include "src/ui/scenic/lib/gfx/resources/compositor/layer_stack.h"

namespace scenic_impl {
namespace input {

using PointerEventPhase = fuchsia::ui::input::PointerEventPhase;
using GfxPointerEvent = fuchsia::ui::input::PointerEvent;
using InjectorEventPhase = fuchsia::ui::pointerinjector::EventPhase;

GfxPointerEvent ClonePointerWithCoords(const GfxPointerEvent& event, const glm::vec2& coords) {
  GfxPointerEvent clone;
  fidl::Clone(event, &clone);
  clone.x = coords.x;
  clone.y = coords.y;
  return clone;
}

glm::vec2 PointerCoords(const GfxPointerEvent& event) { return {event.x, event.y}; }

glm::vec2 TransformPointerCoords(const glm::vec2& pointer, const glm::mat4 transform) {
  const glm::vec4 homogenous_pointer{pointer.x, pointer.y, 0, 1};
  const glm::vec4 transformed_pointer = transform * homogenous_pointer;
  const glm::vec2 homogenized_transformed_pointer{escher::homogenize(transformed_pointer)};

  FX_VLOGS(2) << "Coordinate transform (device->view): (" << pointer.x << ", " << pointer.y
              << ")->(" << homogenized_transformed_pointer.x << ", "
              << homogenized_transformed_pointer.y << ")";

  return homogenized_transformed_pointer;
}

trace_flow_id_t PointerTraceHACK(float fa, float fb) {
  uint32_t ia, ib;
  memcpy(&ia, &fa, sizeof(uint32_t));
  memcpy(&ib, &fb, sizeof(uint32_t));
  return (((uint64_t)ia) << 32) | ib;
}

std::pair<float, float> ReversePointerTraceHACK(trace_flow_id_t trace_id) {
  float fhigh, flow;
  const uint32_t ihigh = (uint32_t)(trace_id >> 32);
  const uint32_t ilow = (uint32_t)trace_id;
  memcpy(&fhigh, &ihigh, sizeof(uint32_t));
  memcpy(&flow, &ilow, sizeof(uint32_t));
  return {fhigh, flow};
}

Phase GfxPhaseToInternalPhase(PointerEventPhase phase) {
  switch (phase) {
    case PointerEventPhase::ADD:
      return Phase::kAdd;
    case PointerEventPhase::UP:
      return Phase::kUp;
    case PointerEventPhase::MOVE:
      return Phase::kChange;
    case PointerEventPhase::DOWN:
      return Phase::kDown;
    case PointerEventPhase::REMOVE:
      return Phase::kRemove;
    case PointerEventPhase::CANCEL:
      return Phase::kCancel;
    default:
      FX_CHECK(false) << "Should never be reached";
      return Phase::kInvalid;
  }
}

PointerEventPhase InternalPhaseToGfxPhase(Phase phase) {
  switch (phase) {
    case Phase::kAdd:
      return PointerEventPhase::ADD;
    case Phase::kUp:
      return PointerEventPhase::UP;
    case Phase::kChange:
      return PointerEventPhase::MOVE;
    case Phase::kDown:
      return PointerEventPhase::DOWN;
    case Phase::kRemove:
      return PointerEventPhase::REMOVE;
    case Phase::kCancel:
      return PointerEventPhase::CANCEL;
    case Phase::kInvalid:
      FX_CHECK(false) << "Should never be reached.";
      return static_cast<PointerEventPhase>(0);
  };
}

std::vector<InternalPointerEvent> PointerInjectorEventToInternalPointerEvent(
    const fuchsia::ui::pointerinjector::Event& event, uint32_t device_id, const Viewport& viewport,
    zx_koid_t context, zx_koid_t target) {
  InternalPointerEvent internal_event;
  internal_event.timestamp = event.timestamp();
  internal_event.device_id = device_id;

  const fuchsia::ui::pointerinjector::PointerSample& pointer_sample = event.data().pointer_sample();
  internal_event.pointer_id = pointer_sample.pointer_id();
  internal_event.viewport = viewport;
  internal_event.position_in_viewport = {pointer_sample.position_in_viewport()[0],
                                         pointer_sample.position_in_viewport()[1]};
  internal_event.context = context;
  internal_event.target = target;

  std::vector<InternalPointerEvent> events;
  switch (pointer_sample.phase()) {
    case InjectorEventPhase::ADD: {
      // Insert extra event.
      InternalPointerEvent add_clone = internal_event;
      add_clone.phase = Phase::kAdd;
      events.emplace_back(std::move(add_clone));
      internal_event.phase = Phase::kDown;
      events.emplace_back(std::move(internal_event));
      break;
    }
    case InjectorEventPhase::CHANGE: {
      internal_event.phase = Phase::kChange;
      events.emplace_back(std::move(internal_event));
      break;
    }
    case InjectorEventPhase::REMOVE: {
      // Insert extra event.
      InternalPointerEvent up_clone = internal_event;
      up_clone.phase = Phase::kUp;
      events.emplace_back(std::move(up_clone));
      internal_event.phase = Phase::kRemove;
      events.emplace_back(std::move(internal_event));
      break;
    }
    case InjectorEventPhase::CANCEL: {
      internal_event.phase = Phase::kCancel;
      events.emplace_back(std::move(internal_event));
      break;
    }
    default: {
      FX_CHECK(false) << "unsupported phase: " << static_cast<uint32_t>(pointer_sample.phase());
      break;
    }
  }

  return events;
}

InternalPointerEvent GfxPointerEventToInternalEvent(
    const fuchsia::ui::input::PointerEvent& event, zx_koid_t scene_koid, float screen_width,
    float screen_height, const glm::mat4& context_from_screen_transform) {
  InternalPointerEvent internal_event;
  internal_event.timestamp = event.event_time;
  internal_event.device_id = event.device_id;
  internal_event.pointer_id = event.pointer_id;
  // Define the viewport to match screen dimensions and location.
  internal_event.viewport.extents =
      Extents({{/*min*/ {0.f, 0.f}, /*max*/ {screen_width, screen_height}}});
  internal_event.viewport.context_from_viewport_transform = context_from_screen_transform;
  internal_event.position_in_viewport = {event.x, event.y};
  // Using scene_koid as both context and target, since it's guaranteed to be the root and thus
  // to deliver events to any client in the scene graph.
  internal_event.context = scene_koid;
  internal_event.target = scene_koid;
  internal_event.phase = GfxPhaseToInternalPhase(event.phase);
  internal_event.buttons = event.buttons;

  return internal_event;
}

GfxPointerEvent InternalPointerEventToGfxPointerEvent(const InternalPointerEvent& internal_event,
                                                      const glm::mat4& view_from_context_transform,
                                                      fuchsia::ui::input::PointerEventType type,
                                                      uint64_t trace_id) {
  GfxPointerEvent event;
  event.event_time = internal_event.timestamp;
  event.device_id = internal_event.device_id;
  event.pointer_id = internal_event.pointer_id;
  event.type = type;
  event.buttons = internal_event.buttons;

  // Convert to view-local coordinates.
  const glm::mat4 view_from_viewport_transform =
      view_from_context_transform * internal_event.viewport.context_from_viewport_transform;
  const glm::vec2 local_position =
      TransformPointerCoords(internal_event.position_in_viewport, view_from_viewport_transform);
  event.x = local_position.x;
  event.y = local_position.y;

  const auto [high, low] = ReversePointerTraceHACK(trace_id);
  event.radius_minor = low;   // Lower 32 bits.
  event.radius_major = high;  // Upper 32 bits.

  event.phase = InternalPhaseToGfxPhase(internal_event.phase);

  return event;
}

glm::mat4 ColumnMajorMat3VectorToMat4(const std::array<float, 9>& matrix_array) {
  // clang-format off
  return glm::mat4(matrix_array[0], matrix_array[1], 0.f, matrix_array[2],  // first column
                   matrix_array[3], matrix_array[4], 0.f, matrix_array[5],  // second column
                               0.f,             0.f, 1.f,             0.f,  // third column
                   matrix_array[6], matrix_array[7], 0.f,             1.f); // fourth column
  // clang-format on
}

}  // namespace input
}  // namespace scenic_impl
