// 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/linux/fl_task_runner.h"
#include "flutter/shell/platform/linux/fl_engine_private.h"

static constexpr int kMicrosecondsPerNanosecond = 1000;
static constexpr int kMillisecondsPerMicrosecond = 1000;

struct _FlTaskRunner {
  GObject parent_instance;

  FlEngine* engine;

  GMutex mutex;
  GCond cond;

  guint timeout_source_id;
  GList /*<FlTaskRunnerTask>*/* pending_tasks;
  gboolean blocking_main_thread;
};

typedef struct _FlTaskRunnerTask {
  // absolute time of task (based on g_get_monotonic_time)
  gint64 task_time_micros;
  FlutterTask task;
} FlTaskRunnerTask;

G_DEFINE_TYPE(FlTaskRunner, fl_task_runner, G_TYPE_OBJECT)

// Removes expired tasks from the task queue and executes them.
// The execution is performed with mutex unlocked.
static void fl_task_runner_process_expired_tasks_locked(FlTaskRunner* self) {
  GList* expired_tasks = nullptr;

  gint64 current_time = g_get_monotonic_time();

  GList* l = self->pending_tasks;
  while (l != nullptr) {
    FlTaskRunnerTask* task = static_cast<FlTaskRunnerTask*>(l->data);
    if (task->task_time_micros <= current_time) {
      GList* link = l;
      l = l->next;
      self->pending_tasks = g_list_remove_link(self->pending_tasks, link);
      expired_tasks = g_list_concat(expired_tasks, link);
    } else {
      l = l->next;
    }
  }

  g_mutex_unlock(&self->mutex);

  l = expired_tasks;
  while (l != nullptr && self->engine) {
    FlTaskRunnerTask* task = static_cast<FlTaskRunnerTask*>(l->data);
    fl_engine_execute_task(self->engine, &task->task);
    l = l->next;
  }

  g_list_free_full(expired_tasks, g_free);

  g_mutex_lock(&self->mutex);
}

static void fl_task_runner_tasks_did_change_locked(FlTaskRunner* self);

// Invoked from a timeout source. Removes and executes expired tasks
// and reschedules timeout if needed.
static gboolean fl_task_runner_on_expired_timeout(gpointer data) {
  FlTaskRunner* self = FL_TASK_RUNNER(data);

  g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex);
  (void)locker;  // unused variable

  g_object_ref(self);

  self->timeout_source_id = 0;
  fl_task_runner_process_expired_tasks_locked(self);

  // reschedule timeout
  fl_task_runner_tasks_did_change_locked(self);

  g_object_unref(self);

  return FALSE;
}

// Returns the absolute time of next expired task (in microseconds, based on
// g_get_monotonic_time). If no task is scheduled returns G_MAXINT64.
static gint64 fl_task_runner_next_task_expiration_time_locked(
    FlTaskRunner* self) {
  gint64 min_time = G_MAXINT64;
  GList* l = self->pending_tasks;
  while (l != nullptr) {
    FlTaskRunnerTask* task = static_cast<FlTaskRunnerTask*>(l->data);
    min_time = MIN(min_time, task->task_time_micros);
    l = l->next;
  }
  return min_time;
}

static void fl_task_runner_tasks_did_change_locked(FlTaskRunner* self) {
  if (self->blocking_main_thread) {
    // Wake up blocked thread
    g_cond_signal(&self->cond);
  } else {
    // Reschedule timeout
    if (self->timeout_source_id != 0) {
      g_source_remove(self->timeout_source_id);
      self->timeout_source_id = 0;
    }
    gint64 min_time = fl_task_runner_next_task_expiration_time_locked(self);
    if (min_time != G_MAXINT64) {
      gint64 remaining = MAX(min_time - g_get_monotonic_time(), 0);
      self->timeout_source_id =
          g_timeout_add(remaining / kMillisecondsPerMicrosecond + 1,
                        fl_task_runner_on_expired_timeout, self);
    }
  }
}

static void engine_weak_notify_cb(gpointer user_data,
                                  GObject* where_the_object_was) {
  FlTaskRunner* self = FL_TASK_RUNNER(user_data);
  self->engine = nullptr;
}

void fl_task_runner_dispose(GObject* object) {
  FlTaskRunner* self = FL_TASK_RUNNER(object);

  // this should never happen because the task runner is retained while blocking
  // main thread
  g_assert(!self->blocking_main_thread);

  if (self->engine != nullptr) {
    g_object_weak_unref(G_OBJECT(self->engine), engine_weak_notify_cb, self);
    self->engine = nullptr;
  }

  g_mutex_clear(&self->mutex);
  g_cond_clear(&self->cond);

  g_list_free_full(self->pending_tasks, g_free);
  if (self->timeout_source_id != 0) {
    g_source_remove(self->timeout_source_id);
  }

  G_OBJECT_CLASS(fl_task_runner_parent_class)->dispose(object);
}

static void fl_task_runner_class_init(FlTaskRunnerClass* klass) {
  G_OBJECT_CLASS(klass)->dispose = fl_task_runner_dispose;
}

static void fl_task_runner_init(FlTaskRunner* self) {
  g_mutex_init(&self->mutex);
  g_cond_init(&self->cond);
}

FlTaskRunner* fl_task_runner_new(FlEngine* engine) {
  FlTaskRunner* res =
      FL_TASK_RUNNER(g_object_new(fl_task_runner_get_type(), nullptr));
  res->engine = engine;
  g_object_weak_ref(G_OBJECT(engine), engine_weak_notify_cb, res);
  return res;
}

void fl_task_runner_post_task(FlTaskRunner* self,
                              FlutterTask task,
                              uint64_t target_time_nanos) {
  g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex);
  (void)locker;  // unused variable

  FlTaskRunnerTask* runner_task = g_new0(FlTaskRunnerTask, 1);
  runner_task->task = task;
  runner_task->task_time_micros =
      target_time_nanos / kMicrosecondsPerNanosecond;

  self->pending_tasks = g_list_append(self->pending_tasks, runner_task);
  fl_task_runner_tasks_did_change_locked(self);
}

void fl_task_runner_block_main_thread(FlTaskRunner* self) {
  g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex);
  (void)locker;  // unused variable

  g_return_if_fail(self->blocking_main_thread == FALSE);

  g_object_ref(self);

  self->blocking_main_thread = true;
  while (self->blocking_main_thread) {
    g_cond_wait_until(&self->cond, &self->mutex,
                      fl_task_runner_next_task_expiration_time_locked(self));
    fl_task_runner_process_expired_tasks_locked(self);
  }

  // Tasks might have changed in the meanwhile, reschedule timeout
  fl_task_runner_tasks_did_change_locked(self);

  g_object_unref(self);
}

void fl_task_runner_release_main_thread(FlTaskRunner* self) {
  g_autoptr(GMutexLocker) locker = g_mutex_locker_new(&self->mutex);
  (void)locker;  // unused variable

  g_return_if_fail(self->blocking_main_thread == TRUE);

  self->blocking_main_thread = FALSE;
  g_cond_signal(&self->cond);
}
