// Copyright 2013 The Flutter 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 "impeller/renderer/backend/vulkan/fence_waiter_vk.h"

#include <chrono>

#include "flutter/fml/thread.h"
#include "flutter/fml/trace_event.h"

namespace impeller {

FenceWaiterVK::FenceWaiterVK(vk::Device device) : device_(device) {
  waiter_thread_ = std::make_unique<std::thread>([&]() { Main(); });
  is_valid_ = true;
}

FenceWaiterVK::~FenceWaiterVK() {
  Terminate();
  if (waiter_thread_) {
    waiter_thread_->join();
  }
}

bool FenceWaiterVK::IsValid() const {
  return is_valid_;
}

bool FenceWaiterVK::AddFence(vk::UniqueFence fence,
                             const fml::closure& callback) {
  if (!IsValid() || !fence || !callback) {
    return false;
  }
  {
    std::scoped_lock lock(wait_set_mutex_);
    wait_set_[MakeSharedVK(std::move(fence))] = callback;
  }
  wait_set_cv_.notify_one();
  return true;
}

void FenceWaiterVK::Main() {
  fml::Thread::SetCurrentThreadName(
      fml::Thread::ThreadConfig{"io.flutter.impeller.fence_waiter"});

  using namespace std::literals::chrono_literals;

  while (true) {
    std::unique_lock lock(wait_set_mutex_);

    wait_set_cv_.wait(lock, [&]() { return !wait_set_.empty() || terminate_; });

    auto wait_set = TrimAndCreateWaitSetLocked();

    lock.unlock();

    if (!wait_set.has_value()) {
      break;
    }
    if (wait_set->empty()) {
      continue;
    }

    auto result = device_.waitForFences(
        wait_set->size(),                        // fences count
        wait_set->data(),                        // fences
        false,                                   // wait for all
        std::chrono::nanoseconds{100ms}.count()  // timeout (ns)
    );
    if (!(result == vk::Result::eSuccess || result == vk::Result::eTimeout)) {
      break;
    }
  }
}

std::optional<std::vector<vk::Fence>>
FenceWaiterVK::TrimAndCreateWaitSetLocked() {
  if (terminate_) {
    return std::nullopt;
  }
  TRACE_EVENT0("impeller", "TrimFences");
  std::vector<vk::Fence> fences;
  fences.reserve(wait_set_.size());
  for (auto it = wait_set_.begin(); it != wait_set_.end();) {
    switch (device_.getFenceStatus(it->first->Get())) {
      case vk::Result::eSuccess:  // Signalled.
        it->second();
        it = wait_set_.erase(it);
        break;
      case vk::Result::eNotReady:  // Un-signalled.
        fences.push_back(it->first->Get());
        it++;
        break;
      default:
        return std::nullopt;
    }
  }
  return fences;
}

void FenceWaiterVK::Terminate() {
  {
    std::scoped_lock lock(wait_set_mutex_);
    terminate_ = true;
  }
  wait_set_cv_.notify_one();
}

}  // namespace impeller
