// 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 "flutter/shell/platform/windows/task_runner_win32.h"

#include <atomic>
#include <iostream>
#include <utility>

namespace flutter {

// static
std::unique_ptr<TaskRunner> TaskRunner::Create(
    DWORD main_thread_id,
    CurrentTimeProc get_current_time,
    const TaskExpiredCallback& on_task_expired) {
  return std::make_unique<TaskRunnerWin32>(main_thread_id, get_current_time,
                                           on_task_expired);
}

TaskRunnerWin32::TaskRunnerWin32(DWORD main_thread_id,
                                 CurrentTimeProc get_current_time,
                                 const TaskExpiredCallback& on_task_expired)
    : main_thread_id_(main_thread_id),
      get_current_time_(get_current_time),
      on_task_expired_(std::move(on_task_expired)) {
  task_runner_window_ = TaskRunnerWin32Window::GetSharedInstance();
  task_runner_window_->AddDelegate(this);
}

TaskRunnerWin32::~TaskRunnerWin32() {
  task_runner_window_->RemoveDelegate(this);
}

bool TaskRunnerWin32::RunsTasksOnCurrentThread() const {
  return GetCurrentThreadId() == main_thread_id_;
}

std::chrono::nanoseconds TaskRunnerWin32::ProcessTasks() {
  const TaskTimePoint now = TaskTimePoint::clock::now();

  std::vector<Task> expired_tasks;

  // Process expired tasks.
  {
    std::lock_guard<std::mutex> lock(task_queue_mutex_);
    while (!task_queue_.empty()) {
      const auto& top = task_queue_.top();
      // If this task (and all tasks after this) has not yet expired, there is
      // nothing more to do. Quit iterating.
      if (top.fire_time > now) {
        break;
      }

      // Make a record of the expired task. Do NOT service the task here
      // because we are still holding onto the task queue mutex. We don't want
      // other threads to block on posting tasks onto this thread till we are
      // done processing expired tasks.
      expired_tasks.push_back(task_queue_.top());

      // Remove the tasks from the delayed tasks queue.
      task_queue_.pop();
    }
  }

  // Fire expired tasks.
  {
    // Flushing tasks here without holing onto the task queue mutex.
    for (const auto& task : expired_tasks) {
      if (auto flutter_task = std::get_if<FlutterTask>(&task.variant)) {
        on_task_expired_(flutter_task);
      } else if (auto closure = std::get_if<TaskClosure>(&task.variant))
        (*closure)();
    }
  }

  // Calculate duration to sleep for on next iteration.
  {
    std::lock_guard<std::mutex> lock(task_queue_mutex_);
    const auto next_wake = task_queue_.empty() ? TaskTimePoint::max()
                                               : task_queue_.top().fire_time;

    return std::min(next_wake - now, std::chrono::nanoseconds::max());
  }
}

TaskRunnerWin32::TaskTimePoint TaskRunnerWin32::TimePointFromFlutterTime(
    uint64_t flutter_target_time_nanos) const {
  const auto now = TaskTimePoint::clock::now();
  const auto flutter_duration = flutter_target_time_nanos - get_current_time_();
  return now + std::chrono::nanoseconds(flutter_duration);
}

void TaskRunnerWin32::PostFlutterTask(FlutterTask flutter_task,
                                      uint64_t flutter_target_time_nanos) {
  Task task;
  task.fire_time = TimePointFromFlutterTime(flutter_target_time_nanos);
  task.variant = flutter_task;
  EnqueueTask(std::move(task));
}

void TaskRunnerWin32::PostTask(TaskClosure closure) {
  Task task;
  task.fire_time = TaskTimePoint::clock::now();
  task.variant = std::move(closure);
  EnqueueTask(std::move(task));
}

void TaskRunnerWin32::EnqueueTask(Task task) {
  static std::atomic_uint64_t sGlobalTaskOrder(0);

  task.order = ++sGlobalTaskOrder;
  {
    std::lock_guard<std::mutex> lock(task_queue_mutex_);
    task_queue_.push(task);

    // Make sure the queue mutex is unlocked before waking up the loop. In case
    // the wake causes this thread to be descheduled for the primary thread to
    // process tasks, the acquisition of the lock on that thread while holding
    // the lock here momentarily till the end of the scope is a pessimization.
  }

  task_runner_window_->WakeUp();
}

}  // namespace flutter
