// Copyright 2022 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/embedder/flatland_connection.h"

#include <lib/fit/function.h>
#include <lib/syslog/global.h>
#include <zircon/status.h>

#include "src/embedder/logging.h"

namespace embedder {

FlatlandConnection::FlatlandConnection(std::string debug_name,
                                       fuchsia::ui::composition::FlatlandHandle flatland,
                                       std::function<void()> on_error_callback,
                                       OnFramePresentedCallback on_frame_presented_callback)
    : flatland_(flatland.Bind()),
      on_error_callback_(on_error_callback),
      on_frame_presented_callback_(std::move(on_frame_presented_callback)) {
  flatland_.set_error_handler([callback = on_error_callback_](zx_status_t status) {
    FX_LOGF(ERROR, kLogTag, "Flatland disconnected: %s", zx_status_get_string(status));
    callback();
  });
  flatland_->SetDebugName(debug_name);
  flatland_.events().OnError = fit::bind_member(this, &FlatlandConnection::OnError);
  flatland_.events().OnFramePresented =
      fit::bind_member(this, &FlatlandConnection::OnFramePresented);
  flatland_.events().OnNextFrameBegin =
      fit::bind_member(this, &FlatlandConnection::OnNextFrameBegin);
}

FlatlandConnection::~FlatlandConnection() = default;

// This method is called from the raster thread.
void FlatlandConnection::Present() {
  if (present_credits_ > 0) {
    DoPresent();
  } else {
    present_pending_ = true;
  }
}

// This method is called from the raster thread.
void FlatlandConnection::DoPresent() {
  if (present_credits_ == 0) {
    FX_LOG(FATAL, kLogTag, "Tried to DoPresent() with 0 present credits.");
    return;
  }

  --present_credits_;

  fuchsia::ui::composition::PresentArgs present_args;
  // TODO(http://fxbug.dev/94000): Compute a better presentation time.
  present_args.set_requested_presentation_time(0);
  present_args.set_acquire_fences(std::move(acquire_fences_));
  present_args.set_release_fences(std::move(previous_present_release_fences_));
  present_args.set_unsquashable(false);
  flatland_->Present(std::move(present_args));

  // In Flatland, release fences apply to the content of the previous present.
  // Keeping track of the old frame's release fences and swapping ensure we set
  // the correct ones for VulkanSurface's interpretation.
  previous_present_release_fences_.clear();
  previous_present_release_fences_.swap(current_present_release_fences_);
  acquire_fences_.clear();
}

void FlatlandConnection::OnError(fuchsia::ui::composition::FlatlandError error) {
  FX_LOGF(ERROR, kLogTag, "Flatland error: %d", static_cast<int>(error));
  on_error_callback_();
}

// This method is called from the raster thread.
void FlatlandConnection::OnNextFrameBegin(fuchsia::ui::composition::OnNextFrameBeginValues values) {
  present_credits_ += values.additional_present_credits();

  if (present_pending_ && present_credits_ > 0) {
    DoPresent();
    present_pending_ = false;
  }

  // TODO(akbiggs): Implement vsyncing logic from
  // https://github.com/flutter/engine/blob/83db012e3ff4e51588772067b59d499bfd44ad2e/shell/platform/fuchsia/flutter/flatland_connection.cc#L120.
}

// This method is called from the raster thread.
void FlatlandConnection::OnFramePresented(fuchsia::scenic::scheduling::FramePresentedInfo info) {
  on_frame_presented_callback_(std::move(info));
}

// This method is called from the raster thread.
void FlatlandConnection::EnqueueAcquireFence(zx::event fence) {
  acquire_fences_.push_back(std::move(fence));
}

// This method is called from the raster thread.
void FlatlandConnection::EnqueueReleaseFence(zx::event fence) {
  current_present_release_fences_.push_back(std::move(fence));
}

}  // namespace embedder
