// Copyright 2017 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 "garnet/lib/ui/gfx/engine/session.h"

#include <memory>
#include <utility>

#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <trace/event.h>

#include "garnet/lib/ui/gfx/engine/gfx_command_applier.h"
#include "garnet/lib/ui/gfx/engine/hit_tester.h"
#include "garnet/lib/ui/gfx/engine/session_handler.h"
#include "garnet/lib/ui/gfx/resources/compositor/layer_stack.h"
#include "garnet/lib/ui/gfx/resources/image_pipe.h"
#include "garnet/lib/ui/gfx/swapchain/swapchain_factory.h"
#include "garnet/lib/ui/gfx/util/time.h"
#include "garnet/lib/ui/gfx/util/unwrap.h"
#include "garnet/lib/ui/gfx/util/wrap.h"
#include "garnet/lib/ui/scenic/util/print_command.h"
#include "lib/escher/hmd/pose_buffer.h"
#include "lib/escher/renderer/batch_gpu_uploader.h"
#include "lib/escher/shape/mesh.h"
#include "lib/escher/shape/rounded_rect_factory.h"
#include "lib/escher/util/type_utils.h"

namespace scenic_impl {
namespace gfx {

namespace {

// Converts the provided vector of Hits into a fidl array of HitPtrs.
fidl::VectorPtr<::fuchsia::ui::gfx::Hit> WrapHits(
    const std::vector<Hit>& hits) {
  fidl::VectorPtr<::fuchsia::ui::gfx::Hit> wrapped_hits;
  wrapped_hits.resize(hits.size());
  for (size_t i = 0; i < hits.size(); ++i) {
    const Hit& hit = hits[i];
    ::fuchsia::ui::gfx::Hit wrapped_hit;
    wrapped_hit.tag_value = hit.tag_value;
    wrapped_hit.ray_origin = Wrap(hit.ray.origin);
    wrapped_hit.ray_direction = Wrap(hit.ray.direction);
    wrapped_hit.inverse_transform = Wrap(hit.inverse_transform);
    wrapped_hit.distance = hit.distance;
    wrapped_hits->at(i) = std::move(wrapped_hit);
  }
  return wrapped_hits;
}
}  // anonymous namespace

Session::Session(SessionId id, SessionContext session_context,
                 EventReporter* event_reporter, ErrorReporter* error_reporter)
    : id_(id),
      error_reporter_(error_reporter),
      event_reporter_(event_reporter),
      session_context_(std::move(session_context)),
      resource_context_({session_context_.vk_device,
                         session_context_.escher != nullptr
                             ? session_context_.escher->device()->caps()
                             : escher::VulkanDeviceQueues::Caps(),
                         session_context_.imported_memory_type_index,
                         session_context_.escher_resource_recycler,
                         session_context_.escher_image_factory}),
      resources_(error_reporter),
      weak_factory_(this) {
  FXL_DCHECK(error_reporter);
}

Session::~Session() {
  resources_.Clear();
  scheduled_image_pipe_updates_ = {};

  // We assume the channel for the associated gfx::Session is closed by
  // SessionHandler before this point, since |scheduled_updates_| contains
  // pending callbacks to gfx::Session::Present(). If the channel was not closed
  // we would have to invoke those callbacks before destroying them.
  scheduled_updates_ = {};
  fences_to_release_on_next_update_.clear();

  if (resource_count_ != 0) {
    auto exported_count =
        session_context_.resource_linker->NumExportsForSession(this);
    FXL_CHECK(resource_count_ == 0)
        << "Session::~Session(): Not all resources have been collected. "
           "Exported resources: "
        << exported_count
        << ", total outstanding resources: " << resource_count_;
  }
  error_reporter_ = nullptr;

  weak_factory_.InvalidateWeakPtrs();
}

ErrorReporter* Session::error_reporter() const {
  return error_reporter_ ? error_reporter_ : ErrorReporter::Default();
}

EventReporter* Session::event_reporter() const { return event_reporter_; }

bool Session::ScheduleUpdate(
    uint64_t requested_presentation_time,
    std::vector<::fuchsia::ui::gfx::Command> commands,
    ::std::vector<zx::event> acquire_fences,
    ::std::vector<zx::event> release_events,
    fuchsia::ui::scenic::Session::PresentCallback callback) {
  uint64_t last_scheduled_presentation_time =
      last_applied_update_presentation_time_;
  if (!scheduled_updates_.empty()) {
    last_scheduled_presentation_time =
        std::max(last_scheduled_presentation_time,
                 scheduled_updates_.back().presentation_time);
  }

  if (requested_presentation_time < last_scheduled_presentation_time) {
    error_reporter_->ERROR()
        << "scenic_impl::gfx::Session: Present called with out-of-order "
           "presentation time. "
        << "requested presentation time=" << requested_presentation_time
        << ", last scheduled presentation time="
        << last_scheduled_presentation_time << ".";
    return false;
  }

  // If we're not running headless, warn if the requested presesentation time
  // is not reasonable.
  if (session_context_.frame_scheduler &&
      session_context_.display_manager->default_display()) {
    std::pair<zx_time_t, zx_time_t> target_times =
        session_context_.frame_scheduler
            ->ComputeTargetPresentationAndWakeupTimes(
                requested_presentation_time);
    uint64_t target_presentation_time = target_times.first;
    zx_time_t vsync_interval =
        session_context_.display_manager->default_display()->GetVsyncInterval();
    // TODO(SCN-723): Re-enable warning when requested_presentation_time == 0
    // after Flutter engine is fixed.
    if (requested_presentation_time != 0 &&
        target_presentation_time - vsync_interval >
            requested_presentation_time) {
      // Present called with too early of a presentation time.
      TRACE_INSTANT("gfx", "Session requested too early presentation time",
                    TRACE_SCOPE_PROCESS, "session_id", id(),
                    "requested presentation time", requested_presentation_time,
                    "target presentation time", target_presentation_time);
    }
  }

  auto acquire_fence_set =
      std::make_unique<escher::FenceSetListener>(std::move(acquire_fences));
  // TODO(SCN-1201): Consider calling ScheduleUpdateForSession immediately if
  // acquire_fence_set is already ready (which is the case if there are
  // zero acquire fences).

  acquire_fence_set->WaitReadyAsync(
      [weak = GetWeakPtr(), requested_presentation_time] {
        if (weak) {
          weak->session_context_.session_manager->ScheduleUpdateForSession(
              weak->session_context_.update_scheduler,
              requested_presentation_time, std::move(weak));
        }
      });

  scheduled_updates_.push(
      Update{requested_presentation_time, std::move(commands),
             std::move(acquire_fence_set), std::move(release_events),
             std::move(callback)});

  return true;
}

void Session::ScheduleImagePipeUpdate(uint64_t presentation_time,
                                      ImagePipePtr image_pipe) {
  FXL_DCHECK(image_pipe);
  scheduled_image_pipe_updates_.push(
      {presentation_time, std::move(image_pipe)});

  session_context_.session_manager->ScheduleUpdateForSession(
      session_context_.update_scheduler, presentation_time, GetWeakPtr());
}

Session::ApplyUpdateResult Session::ApplyScheduledUpdates(
    CommandContext* command_context, uint64_t presentation_time,
    uint64_t presentation_interval) {
  TRACE_DURATION("gfx", "Session::ApplyScheduledUpdates", "session_id", id_,
                 "session_debug_name", debug_name_, "time", presentation_time,
                 "interval", presentation_interval);

  ApplyUpdateResult update_results{false, false};

  if (presentation_time < last_presentation_time_) {
    error_reporter_->ERROR()
        << "scenic_impl::gfx::Session: ApplyScheduledUpdates called with "
           "presentation_time="
        << presentation_time << ", which is less than last_presentation_time_="
        << last_presentation_time_ << ".";
    update_results.success = false;
    return update_results;
  }

  while (!scheduled_updates_.empty() &&
         scheduled_updates_.front().presentation_time <= presentation_time) {
    if (!scheduled_updates_.front().acquire_fences->ready()) {
      TRACE_INSTANT("gfx", "Session missed frame", TRACE_SCOPE_PROCESS,
                    "session_id", id(), "session_debug_name", debug_name_,
                    "target presentation time (usecs)",
                    presentation_time / 1000,
                    "session target presentation time (usecs)",
                    scheduled_updates_.front().presentation_time / 1000);
      break;
    }
    if (ApplyUpdate(command_context,
                    std::move(scheduled_updates_.front().commands))) {
      update_results.needs_render = true;
      auto info = fuchsia::images::PresentationInfo();
      info.presentation_time = presentation_time;
      info.presentation_interval = presentation_interval;
      scheduled_updates_.front().present_callback(std::move(info));

      FXL_DCHECK(last_applied_update_presentation_time_ <=
                 scheduled_updates_.front().presentation_time);
      last_applied_update_presentation_time_ =
          scheduled_updates_.front().presentation_time;

      for (size_t i = 0; i < fences_to_release_on_next_update_.size(); ++i) {
        session_context_.release_fence_signaller->AddCPUReleaseFence(
            std::move(fences_to_release_on_next_update_.at(i)));
      }
      fences_to_release_on_next_update_ =
          std::move(scheduled_updates_.front().release_fences);

      scheduled_updates_.pop();

      // TODO(SCN-1202): gather statistics about how close the actual
      // presentation_time was to the requested time.
    } else {
      // An error was encountered while applying the update.
      FXL_LOG(WARNING) << "scenic_impl::gfx::Session::ApplyScheduledUpdates(): "
                          "An error was encountered while applying the update. "
                          "Initiating teardown.";
      update_results.success = false;
      scheduled_updates_ = {};

      // Tearing down a session will very probably result in changes to
      // the global scene-graph.
      update_results.needs_render = true;
      return update_results;
    }
  }

  // TODO(SCN-1219): Unify with other session updates.
  std::unordered_map<ResourceId, ImagePipePtr> image_pipe_updates_to_upload;
  while (!scheduled_image_pipe_updates_.empty() &&
         scheduled_image_pipe_updates_.top().presentation_time <=
             presentation_time) {
    if (scheduled_image_pipe_updates_.top().image_pipe) {
      bool image_updated =
          scheduled_image_pipe_updates_.top().image_pipe->Update(
              session_context_.release_fence_signaller, presentation_time,
              presentation_interval);
      // Only upload images that were updated and are currently dirty, and only
      // do one upload per ImagePipe.
      if (image_updated) {
        image_pipe_updates_to_upload.try_emplace(
            scheduled_image_pipe_updates_.top().image_pipe->id(),
            std::move(scheduled_image_pipe_updates_.top().image_pipe));
      }
    }
    scheduled_image_pipe_updates_.pop();
  }

  // Stage GPU uploads for the latest dirty image on each updated ImagePipe.
  for (const auto& entry : image_pipe_updates_to_upload) {
    ImagePipePtr image_pipe = entry.second;
    image_pipe->UpdateEscherImage(command_context->batch_gpu_uploader());
    // Image was updated so the image in the scene is dirty.
    update_results.needs_render = true;
  }
  image_pipe_updates_to_upload.clear();

  update_results.success = true;
  return update_results;
}

void Session::EnqueueEvent(::fuchsia::ui::gfx::Event event) {
  event_reporter_->EnqueueEvent(std::move(event));
}

void Session::EnqueueEvent(::fuchsia::ui::input::InputEvent event) {
  event_reporter_->EnqueueEvent(std::move(event));
}

bool Session::ApplyUpdate(CommandContext* command_context,
                          std::vector<::fuchsia::ui::gfx::Command> commands) {
  TRACE_DURATION("gfx", "Session::ApplyUpdate");
  for (auto& command : commands) {
    if (!ApplyCommand(command_context, std::move(command))) {
      using ::operator<<;  // From print_commands.h
      error_reporter_->ERROR() << "scenic_impl::gfx::Session::ApplyCommand() "
                                  "failed to apply Command: "
                               << command;
      return false;
    }
  }
  return true;
  // TODO: acquire_fences and release_fences should be added to a list that is
  // consumed by the FrameScheduler.
}

void Session::HitTest(uint32_t node_id, ::fuchsia::ui::gfx::vec3 ray_origin,
                      ::fuchsia::ui::gfx::vec3 ray_direction,
                      fuchsia::ui::scenic::Session::HitTestCallback callback) {
  if (auto node = resources_.FindResource<Node>(node_id)) {
    SessionHitTester hit_tester(node->session());
    std::vector<Hit> hits = hit_tester.HitTest(
        node.get(), escher::ray4{escher::vec4(Unwrap(ray_origin), 1.f),
                                 escher::vec4(Unwrap(ray_direction), 0.f)});
    callback(WrapHits(hits));
  } else {
    // TODO(SCN-162): Currently the test fails if the node isn't presented yet.
    // Perhaps we should given clients more control over which state of
    // the scene graph will be consulted for hit testing purposes.
    error_reporter_->WARN()
        << "Cannot perform hit test because node " << node_id
        << " does not exist in the currently presented content.";
    callback(nullptr);
  }
}

void Session::HitTestDeviceRay(
    ::fuchsia::ui::gfx::vec3 ray_origin, ::fuchsia::ui::gfx::vec3 ray_direction,
    fuchsia::ui::scenic::Session::HitTestCallback callback) {
  escher::ray4 ray =
      escher::ray4{{Unwrap(ray_origin), 1.f}, {Unwrap(ray_direction), 0.f}};

  // The layer stack expects the input to the hit test to be in unscaled device
  // coordinates.
  SessionHitTester hit_tester(this);
  // TODO(SCN-1170): get rid of SceneGraph::first_compositor().
  std::vector<Hit> layer_stack_hits =
      session_context_.scene_graph->first_compositor()->layer_stack()->HitTest(
          ray, &hit_tester);

  callback(WrapHits(layer_stack_hits));
}

}  // namespace gfx
}  // namespace scenic_impl
