// 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/gles/reactor_gles.h"

#include <algorithm>

#include "flutter/fml/trace_event.h"
#include "impeller/base/validation.h"

namespace impeller {

ReactorGLES::ReactorGLES(std::unique_ptr<ProcTableGLES> gl)
    : proc_table_(std::move(gl)) {
  if (!proc_table_ || !proc_table_->IsValid()) {
    VALIDATION_LOG << "Proc table was invalid.";
    return;
  }
  can_set_debug_labels_ = proc_table_->GetDescription()->HasDebugExtension();
  is_valid_ = true;
}

ReactorGLES::~ReactorGLES() = default;

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

ReactorGLES::WorkerID ReactorGLES::AddWorker(std::weak_ptr<Worker> worker) {
  Lock lock(workers_mutex_);
  auto id = WorkerID{};
  workers_[id] = std::move(worker);
  return id;
}

bool ReactorGLES::RemoveWorker(WorkerID worker) {
  Lock lock(workers_mutex_);
  return workers_.erase(worker) == 1;
}

bool ReactorGLES::HasPendingOperations() const {
  Lock ops_lock(ops_mutex_);
  return !ops_.empty();
}

const ProcTableGLES& ReactorGLES::GetProcTable() const {
  FML_DCHECK(IsValid());
  return *proc_table_;
}

std::optional<GLuint> ReactorGLES::GetGLHandle(const HandleGLES& handle) const {
  ReaderLock handles_lock(handles_mutex_);
  if (auto found = handles_.find(handle); found != handles_.end()) {
    if (found->second.pending_collection) {
      VALIDATION_LOG
          << "Attempted to acquire a handle that was pending collection.";
      return std::nullopt;
    }
    if (!found->second.name.has_value()) {
      VALIDATION_LOG << "Attempt to acquire a handle outside of an operation.";
      return std::nullopt;
    }
    return found->second.name;
  }
  VALIDATION_LOG << "Attempted to acquire an invalid GL handle.";
  return std::nullopt;
}

bool ReactorGLES::AddOperation(Operation operation) {
  if (!operation) {
    return false;
  }
  {
    Lock ops_lock(ops_mutex_);
    ops_.emplace_back(std::move(operation));
  }
  // Attempt a reaction if able but it is not an error if this isn't possible.
  [[maybe_unused]] auto result = React();
  return true;
}

static std::optional<GLuint> CreateGLHandle(const ProcTableGLES& gl,
                                            HandleType type) {
  GLuint handle = GL_NONE;
  switch (type) {
    case HandleType::kUnknown:
      return std::nullopt;
    case HandleType::kTexture:
      gl.GenTextures(1u, &handle);
      return handle;
    case HandleType::kBuffer:
      gl.GenBuffers(1u, &handle);
      return handle;
    case HandleType::kProgram:
      return gl.CreateProgram();
    case HandleType::kRenderBuffer:
      gl.GenRenderbuffers(1u, &handle);
      return handle;
    case HandleType::kFrameBuffer:
      gl.GenFramebuffers(1u, &handle);
      return handle;
  }
  return std::nullopt;
}

static bool CollectGLHandle(const ProcTableGLES& gl,
                            HandleType type,
                            GLuint handle) {
  switch (type) {
    case HandleType::kUnknown:
      return false;
    case HandleType::kTexture:
      gl.DeleteTextures(1u, &handle);
      return true;
    case HandleType::kBuffer:
      gl.DeleteBuffers(1u, &handle);
      return true;
    case HandleType::kProgram:
      gl.DeleteProgram(handle);
      return true;
    case HandleType::kRenderBuffer:
      gl.DeleteRenderbuffers(1u, &handle);
      return true;
    case HandleType::kFrameBuffer:
      gl.DeleteFramebuffers(1u, &handle);
      return true;
  }
  return false;
}

HandleGLES ReactorGLES::CreateHandle(HandleType type) {
  if (type == HandleType::kUnknown) {
    return HandleGLES::DeadHandle();
  }
  auto new_handle = HandleGLES::Create(type);
  if (new_handle.IsDead()) {
    return HandleGLES::DeadHandle();
  }
  WriterLock handles_lock(handles_mutex_);
  auto gl_handle = CanReactOnCurrentThread()
                       ? CreateGLHandle(GetProcTable(), type)
                       : std::nullopt;
  handles_[new_handle] = LiveHandle{std::move(gl_handle)};
  return new_handle;
}

void ReactorGLES::CollectHandle(HandleGLES handle) {
  WriterLock handles_lock(handles_mutex_);
  if (auto found = handles_.find(handle); found != handles_.end()) {
    found->second.pending_collection = true;
  }
}

bool ReactorGLES::React() {
  if (!CanReactOnCurrentThread()) {
    return false;
  }
  TRACE_EVENT0("impeller", "ReactorGLES::React");
  while (HasPendingOperations()) {
    if (!ReactOnce()) {
      return false;
    }
  }
  return true;
}

static DebugResourceType ToDebugResourceType(HandleType type) {
  switch (type) {
    case HandleType::kUnknown:
      FML_UNREACHABLE();
    case HandleType::kTexture:
      return DebugResourceType::kTexture;
    case HandleType::kBuffer:
      return DebugResourceType::kBuffer;
    case HandleType::kProgram:
      return DebugResourceType::kProgram;
    case HandleType::kRenderBuffer:
      return DebugResourceType::kRenderBuffer;
    case HandleType::kFrameBuffer:
      return DebugResourceType::kFrameBuffer;
  }
  FML_UNREACHABLE();
}

bool ReactorGLES::ReactOnce() {
  if (!IsValid()) {
    return false;
  }
  TRACE_EVENT0("impeller", __FUNCTION__);
  return ConsolidateHandles() && FlushOps();
}

bool ReactorGLES::ConsolidateHandles() {
  TRACE_EVENT0("impeller", __FUNCTION__);
  const auto& gl = GetProcTable();
  WriterLock handles_lock(handles_mutex_);
  std::vector<HandleGLES> handles_to_delete;
  for (auto& handle : handles_) {
    // Collect dead handles.
    if (handle.second.pending_collection) {
      // This could be false if the handle was created and collected without
      // use. We still need to get rid of map entry.
      if (handle.second.name.has_value()) {
        CollectGLHandle(gl, handle.first.type, handle.second.name.value());
      }
      handles_to_delete.push_back(handle.first);
      continue;
    }
    // Create live handles.
    if (!handle.second.name.has_value()) {
      auto gl_handle = CreateGLHandle(gl, handle.first.type);
      if (!gl_handle) {
        VALIDATION_LOG << "Could not create GL handle.";
        return false;
      }
      handle.second.name = std::move(gl_handle);
    }
    // Set pending debug labels.
    if (handle.second.pending_debug_label.has_value()) {
      if (gl.SetDebugLabel(ToDebugResourceType(handle.first.type),
                           handle.second.name.value(),
                           handle.second.pending_debug_label.value())) {
        handle.second.pending_debug_label = std::nullopt;
      }
    }
  }
  for (const auto& handle_to_delete : handles_to_delete) {
    handles_.erase(handle_to_delete);
  }
  return true;
}

bool ReactorGLES::FlushOps() {
  TRACE_EVENT0("impeller", __FUNCTION__);
  // Do NOT hold the ops or handles locks while performing operations in case
  // the ops enqueue more ops.
  decltype(ops_) ops;
  {
    Lock ops_lock(ops_mutex_);
    std::swap(ops_, ops);
  }
  for (const auto& op : ops) {
    TRACE_EVENT0("impeller", "ReactorGLES::Operation");
    op(*this);
  }
  return true;
}

void ReactorGLES::SetDebugLabel(const HandleGLES& handle, std::string label) {
  if (!can_set_debug_labels_) {
    return;
  }
  if (handle.IsDead()) {
    return;
  }
  WriterLock handles_lock(handles_mutex_);
  if (auto found = handles_.find(handle); found != handles_.end()) {
    found->second.pending_debug_label = std::move(label);
  }
}

bool ReactorGLES::CanReactOnCurrentThread() const {
  std::vector<WorkerID> dead_workers;
  Lock lock(workers_mutex_);
  for (const auto& worker : workers_) {
    auto worker_ptr = worker.second.lock();
    if (!worker_ptr) {
      dead_workers.push_back(worker.first);
      continue;
    }
    if (worker_ptr->CanReactorReactOnCurrentThreadNow(*this)) {
      return true;
    }
  }
  for (const auto& worker_id : dead_workers) {
    workers_.erase(worker_id);
  }
  return false;
}

}  // namespace impeller
