// Copyright 2020 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/injector.h"

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

#include <src/lib/fostr/fidl/fuchsia/ui/pointerinjector/formatting.h>

#include "lib/async/cpp/time.h"
#include "lib/async/default.h"
#include "src/ui/scenic/lib/input/constants.h"
#include "src/ui/scenic/lib/utils/math.h"

#include <glm/glm.hpp>

namespace scenic_impl::input {

using fuchsia::ui::pointerinjector::EventPhase;

namespace {

// A histogram that ranges from 1ms to ~8s.
constexpr zx::duration kLatencyHistogramFloor = zx::msec(1);
constexpr zx::duration kLatencyHistogramInitialStep = zx::msec(1);
constexpr uint64_t kLatencyHistogramStepMultiplier = 2;
constexpr size_t kLatencyHistogramBuckets = 14;

// Retain this many touch event buckets.  This ensures we see at most this
// many of them even if there isn't 10 minutes of consistent touch activity.
constexpr size_t kNumRetainedTouchEventBuckets = 10;

uint64_t GetCurrentMinute(const zx::time timestamp) { return timestamp.get() / zx::min(1).get(); }

}  // namespace

InjectorInspector::InjectorInspector(inspect::Node node)
    : node_(std::move(node)),
      history_stats_node_(node_.CreateLazyValues("Injection history",
                                                 [this] {
                                                   inspect::Inspector insp;
                                                   ReportStats(insp);
                                                   return fpromise::make_ok_promise(
                                                       std::move(insp));
                                                 })),
      viewport_event_latency_(node_.CreateExponentialUintHistogram(
          "viewport_event_latency_usecs", kLatencyHistogramFloor.to_usecs(),
          kLatencyHistogramInitialStep.to_usecs(), kLatencyHistogramStepMultiplier,
          kLatencyHistogramBuckets)),
      pointer_event_latency_(node_.CreateExponentialUintHistogram(
          "pointer_event_latency_usecs", kLatencyHistogramFloor.to_usecs(),
          kLatencyHistogramInitialStep.to_usecs(), kLatencyHistogramStepMultiplier,
          kLatencyHistogramBuckets)) {}

void InjectorInspector::OnPointerInjectorEvent(const fuchsia::ui::pointerinjector::Event& event) {
  FX_DCHECK(event.has_data() && event.has_timestamp());
  FX_DCHECK(async_get_default_dispatcher());

  const zx::time now = async::Now(async_get_default_dispatcher());
  const zx::duration latency = now - zx::time(event.timestamp());
  if (event.data().is_viewport()) {
    viewport_event_latency_.Insert(latency.to_usecs());
  } else if (event.data().is_pointer_sample()) {
    UpdateHistory(now);
    pointer_event_latency_.Insert(latency.to_usecs());
  } else {
    FX_LOGS(ERROR) << "pointerinjector::Event dropped from inspect metrics. Unexpected data type.";
  }
}

void InjectorInspector::UpdateHistory(const zx::time now) {
  const uint64_t current_minute = GetCurrentMinute(now);

  // Add elements to the front and pop from the back so that the newest element will be read out
  // first when we later iterate over the deque.
  if (history_.empty() || history_.front().minute_key != current_minute) {
    history_.push_front({
        .minute_key = current_minute,
    });
  }
  history_.front().num_injected_events++;

  // Pop off everything older than |kNumMinutesOfHistory|.
  while (history_.size() > kNumRetainedTouchEventBuckets &&
         (current_minute - history_.back().minute_key) >= kNumMinutesOfHistory) {
    history_.pop_back();
  }
}

void InjectorInspector::ReportStats(inspect::Inspector& inspector) const {
  inspect::Node node = inspector.GetRoot().CreateChild(
      "Last " + std::to_string(kNumMinutesOfHistory) + " minutes of injected events");

  uint64_t total = 0;
  const uint64_t current_minute = GetCurrentMinute(async::Now(async_get_default_dispatcher()));
  for (const auto& [minute, num_injected_events] : history_) {
    if (minute + kNumMinutesOfHistory <= current_minute) {
      break;
    }

    node.CreateUint("Events at minute " + std::to_string(minute), num_injected_events, &inspector);

    total += num_injected_events;
  }
  node.CreateUint("Total", total, &inspector);
  inspector.emplace(std::move(node));
}

namespace {

bool HasRequiredFields(const fuchsia::ui::pointerinjector::PointerSample& pointer) {
  return pointer.has_pointer_id() && pointer.has_phase() && pointer.has_position_in_viewport();
}

bool AreValidExtents(const std::array<std::array<float, 2>, 2>& extents) {
  for (auto& point : extents) {
    for (float f : point) {
      if (!std::isfinite(f)) {
        return false;
      }
    }
  }

  const float min_x = extents[0][0];
  const float min_y = extents[0][1];
  const float max_x = extents[1][0];
  const float max_y = extents[1][1];
  return std::isless(min_x, max_x) && std::isless(min_y, max_y);
}

}  // namespace

Injector::Injector(inspect::Node inspect_node, InjectorSettings settings, Viewport viewport,
                   fidl::InterfaceRequest<fuchsia::ui::pointerinjector::Device> device,
                   fit::function<bool(/*descendant*/ zx_koid_t, /*ancestor*/ zx_koid_t)>
                       is_descendant_and_connected,
                   fit::function<void()> on_channel_closed)
    : settings_(std::move(settings)),
      viewport_(std::move(viewport)),
      binding_(this, std::move(device)),
      is_descendant_and_connected_(std::move(is_descendant_and_connected)),
      on_channel_closed_(std::move(on_channel_closed)),
      inspector_(std::move(inspect_node)) {
  FX_DCHECK(is_descendant_and_connected_);
  FX_LOGS(INFO) << "Injector : Registered new injector with "
                << " Device Id: " << settings_.device_id
                << " Device Type: " << static_cast<uint32_t>(settings_.device_type)
                << " Dispatch Policy: " << static_cast<uint32_t>(settings_.dispatch_policy)
                << " Context koid: " << settings_.context_koid
                << " and Target koid: " << settings_.target_koid;

  binding_.set_error_handler([this](zx_status_t) {
    // Clean up ongoing streams before calling the supplied error handler.
    CancelOngoingStreams();
    // NOTE: Triggers destruction of this object.
    on_channel_closed_();
  });
}

void Injector::Inject(std::vector<fuchsia::ui::pointerinjector::Event> events,
                      InjectCallback callback) {
  TRACE_DURATION("input", "Injector::Inject");
  if (!is_descendant_and_connected_(settings_.target_koid, settings_.context_koid)) {
    FX_LOGS(ERROR) << "Inject() called with Context (koid: " << settings_.context_koid
                   << ") and Target (koid: " << settings_.target_koid
                   << ") making an invalid hierarchy.";
    CloseChannel(ZX_ERR_BAD_STATE);
    return;
  }

  if (events.empty()) {
    FX_LOGS(ERROR) << "Inject() called without any events";
    CloseChannel(ZX_ERR_INVALID_ARGS);
    return;
  }

  for (const auto& event : events) {
    if (!event.has_timestamp() || !event.has_data()) {
      FX_LOGS(ERROR) << "Inject() called with an incomplete event";
      CloseChannel(ZX_ERR_INVALID_ARGS);
      return;
    }

    inspector_.OnPointerInjectorEvent(event);

    if (event.data().is_viewport()) {
      const auto& new_viewport = event.data().viewport();

      {
        const zx_status_t result = IsValidViewport(new_viewport);
        if (result != ZX_OK) {
          // Errors printed inside IsValidViewport. Just close channel here.
          CloseChannel(result);
          return;
        }
      }
      viewport_ = {.extents = {new_viewport.extents()},
                   .context_from_viewport_transform = utils::ColumnMajorMat3ArrayToMat4(
                       new_viewport.viewport_to_context_transform())};
      continue;
    } else if (event.data().is_pointer_sample()) {
      const auto& pointer_sample = event.data().pointer_sample();

      const auto [result, stream_id] = ValidatePointerSample(pointer_sample);
      if (result != ZX_OK) {
        CloseChannel(result);
        return;
      }

      if (event.has_trace_flow_id()) {
        TRACE_FLOW_END("input", "dispatch_event_to_scenic", event.trace_flow_id());
      }
      ForwardEvent(event, stream_id);
      continue;
    } else {
      // Should be unreachable.
      FX_LOGS(WARNING) << "Unknown fuchsia::ui::pointerinjector::Data received";
    }
  }

  callback();
}

std::pair<zx_status_t, StreamId> Injector::ValidatePointerSample(
    const fuchsia::ui::pointerinjector::PointerSample& pointer_sample) {
  if (!HasRequiredFields(pointer_sample)) {
    FX_LOGS(ERROR)
        << "Injected fuchsia::ui::pointerinjector::PointerSample was missing required fields";
    return {ZX_ERR_INVALID_ARGS, kInvalidStreamId};
  }

  const auto [x, y] = pointer_sample.position_in_viewport();
  if (!std::isfinite(x) || !std::isfinite(y)) {
    FX_LOGS(ERROR) << "fuchsia::ui::pointerinjector::PointerSample contained a NaN or inf value";
    return {ZX_ERR_INVALID_ARGS, kInvalidStreamId};
  }

  // Enforce event stream ordering rules. It keeps the event stream clean for downstream clients.
  const auto stream_id = ValidateEventStream(pointer_sample.pointer_id(), pointer_sample.phase());
  if (stream_id == kInvalidStreamId) {
    return {ZX_ERR_BAD_STATE, kInvalidStreamId};
  }

  return {ZX_OK, stream_id};
}

StreamId Injector::ValidateEventStream(uint32_t pointer_id, EventPhase phase) {
  const bool stream_is_ongoing = ongoing_streams_.count(pointer_id) > 0;
  const bool double_add = stream_is_ongoing && phase == EventPhase::ADD;
  const bool invalid_start = !stream_is_ongoing && phase != EventPhase::ADD;
  if (double_add) {
    FX_LOGS(ERROR) << "Inject() called with invalid event stream: double-add, ptr-id: "
                   << pointer_id << ", stream-event-count: " << ongoing_streams_.count(pointer_id)
                   << ", phase: " << (int)phase;
    return kInvalidStreamId;
  }
  if (invalid_start) {
    FX_LOGS(ERROR) << "Inject() called with invalid event stream: invalid-start, ptr-id: "
                   << pointer_id << ", stream-event-count: " << ongoing_streams_.count(pointer_id)
                   << ", phase: " << (int)phase;
    return kInvalidStreamId;
  }

  // Update stream state.
  StreamId stream_id = kInvalidStreamId;
  if (phase == EventPhase::ADD) {
    ongoing_streams_.emplace(pointer_id, NewStreamId());
    stream_id = ongoing_streams_.at(pointer_id);
  } else if (phase == EventPhase::REMOVE || phase == EventPhase::CANCEL) {
    stream_id = ongoing_streams_.at(pointer_id);
    ongoing_streams_.erase(pointer_id);
  } else {
    stream_id = ongoing_streams_.at(pointer_id);
  }

  FX_DCHECK(stream_id != kInvalidStreamId);
  return stream_id;
}

void Injector::CancelOngoingStreams() {
  // Inject CANCEL event for each ongoing stream.
  for (const auto [pointer_id, stream_id] : ongoing_streams_) {
    CancelStream(pointer_id, stream_id);
  }
  ongoing_streams_.clear();
}

void Injector::CloseChannel(zx_status_t epitaph) {
  CancelOngoingStreams();
  binding_.Close(epitaph);
  // NOTE: Triggers destruction of this object.
  on_channel_closed_();
}

zx_status_t Injector::IsValidViewport(const fuchsia::ui::pointerinjector::Viewport& viewport) {
  if (!viewport.has_extents() || !viewport.has_viewport_to_context_transform()) {
    FX_LOGS(ERROR) << "Provided fuchsia::ui::pointerinjector::Viewport had missing fields";
    return ZX_ERR_INVALID_ARGS;
  }

  if (!AreValidExtents(viewport.extents())) {
    FX_LOGS(ERROR)
        << "Provided fuchsia::ui::pointerinjector::Viewport had invalid extents. Extents min: {"
        << viewport.extents()[0][0] << ", " << viewport.extents()[0][1] << "} max: {"
        << viewport.extents()[1][0] << ", " << viewport.extents()[1][1] << "}";
    return ZX_ERR_INVALID_ARGS;
  }

  if (std::any_of(viewport.viewport_to_context_transform().begin(),
                  viewport.viewport_to_context_transform().end(),
                  [](float f) { return !std::isfinite(f); })) {
    FX_LOGS(ERROR) << "Provided fuchsia::ui::pointerinjector::Viewport "
                      "viewport_to_context_transform contained a NaN or infinity";
    return ZX_ERR_INVALID_ARGS;
  }

  // Must be invertible, i.e. determinant must be non-zero.
  const glm::mat4 viewport_to_context_transform =
      utils::ColumnMajorMat3ArrayToMat4(viewport.viewport_to_context_transform());
  if (fabs(glm::determinant(viewport_to_context_transform)) <=
      std::numeric_limits<float>::epsilon()) {
    FX_LOGS(ERROR) << "Provided fuchsia::ui::pointerinjector::Viewport had a non-invertible matrix";
    return ZX_ERR_INVALID_ARGS;
  }

  return ZX_OK;
}

}  // namespace scenic_impl::input
