// Copyright (c) 2024, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "include/dart_api.h"
#include "vm/bootstrap_natives.h"
#include "vm/heap/safepoint.h"
#include "vm/os_thread.h"

namespace dart {

static void DeleteMutex(void* isolate_data, void* mutex_pointer) {
  delete reinterpret_cast<Mutex*>(mutex_pointer);
}

static constexpr int kMutexNativeField = 0;

DEFINE_FFI_NATIVE_ENTRY(Mutex_Initialize, void, (Dart_Handle mutex_handle)) {
  Mutex* mutex = new Mutex();
  Dart_Handle err = Dart_SetNativeInstanceField(
      mutex_handle, kMutexNativeField, reinterpret_cast<intptr_t>(mutex));
  if (Dart_IsError(err)) {
    delete mutex;
    Dart_PropagateError(err);
  }
  Dart_NewFinalizableHandle(mutex_handle, mutex, sizeof(Mutex), DeleteMutex);
};

DEFINE_FFI_NATIVE_ENTRY(Mutex_RunLocked,
                        Dart_Handle,
                        (Dart_Handle mutex_handle,
                         Dart_Handle closure_handle)) {
  Mutex* mutex;
  Dart_Handle result = Dart_GetNativeInstanceField(
      mutex_handle, kMutexNativeField, reinterpret_cast<intptr_t*>(&mutex));
  if (Dart_IsError(result)) {
    Dart_PropagateError(result);
  }
  mutex->Lock();
  result = Dart_InvokeClosure(closure_handle, 0, nullptr);
  mutex->Unlock();
  if (Dart_IsError(result)) {
    Dart_PropagateError(result);
  }
  return result;
}

static void DeleteConditionVariable(void* isolate_data, void* condvar_pointer) {
  delete reinterpret_cast<ConditionVariable*>(condvar_pointer);
}

static constexpr int kCondVarNativeField = 0;

DEFINE_FFI_NATIVE_ENTRY(ConditionVariable_Initialize,
                        void,
                        (Dart_Handle condvar_handle)) {
  ConditionVariable* condvar = new ConditionVariable();
  Dart_Handle err = Dart_SetNativeInstanceField(
      condvar_handle, kCondVarNativeField, reinterpret_cast<intptr_t>(condvar));
  if (Dart_IsError(err)) {
    delete condvar;
    Dart_PropagateError(err);
  }
  Dart_NewFinalizableHandle(condvar_handle, condvar, sizeof(ConditionVariable),
                            DeleteConditionVariable);
}

DEFINE_FFI_NATIVE_ENTRY(ConditionVariable_Wait,
                        void,
                        (Dart_Handle condvar_handle,
                         Dart_Handle mutex_handle,
                         intptr_t timeout)) {
  Mutex* mutex;
  Dart_Handle result_mutex = Dart_GetNativeInstanceField(
      mutex_handle, kCondVarNativeField, reinterpret_cast<intptr_t*>(&mutex));
  if (Dart_IsError(result_mutex)) {
    Dart_PropagateError(result_mutex);
  }
  ConditionVariable* condvar;
  Dart_Handle result_condvar =
      Dart_GetNativeInstanceField(condvar_handle, kCondVarNativeField,
                                  reinterpret_cast<intptr_t*>(&condvar));
  if (Dart_IsError(result_condvar)) {
    Dart_PropagateError(result_condvar);
  }
  condvar->Wait(mutex, timeout);
}

DEFINE_FFI_NATIVE_ENTRY(ConditionVariable_Notify,
                        void,
                        (Dart_Handle condvar_handle)) {
  ConditionVariable* condvar;
  Dart_Handle result_condvar =
      Dart_GetNativeInstanceField(condvar_handle, kCondVarNativeField,
                                  reinterpret_cast<intptr_t*>(&condvar));
  if (Dart_IsError(result_condvar)) {
    Dart_PropagateError(result_condvar);
  }
  condvar->Notify();
}

DEFINE_FFI_NATIVE_ENTRY(ConditionVariable_NotifyAll,
                        void,
                        (Dart_Handle condvar_handle)) {
  ConditionVariable* condvar;
  Dart_Handle result_condvar =
      Dart_GetNativeInstanceField(condvar_handle, kCondVarNativeField,
                                  reinterpret_cast<intptr_t*>(&condvar));
  if (Dart_IsError(result_condvar)) {
    Dart_PropagateError(result_condvar);
  }
  condvar->NotifyAll();
}

DEFINE_FFI_NATIVE_ENTRY(IsolateGroup_runSync,
                        Dart_Handle,
                        (Dart_Handle closure)) {
  Thread* current_thread = Thread::Current();
  ASSERT(current_thread->execution_state() == Thread::kThreadInNative);
  Isolate* saved_isolate = current_thread->isolate();
  current_thread->ExitSafepointFromNative();
  current_thread->set_execution_state(Thread::kThreadInVM);
  Thread::ExitIsolate(/*isolate_shutdown=*/false);

  Thread::EnterIsolateGroupAsMutator(current_thread->isolate_group(),
                                     /*bypass_safepoint=*/false);

  auto mutator_thread = Thread::Current();

  ApiState* state = mutator_thread->isolate_group()->api_state();
  ASSERT(state != nullptr);
  mutator_thread->EnterApiScope();
  ASSERT(mutator_thread->execution_state() == Thread::kThreadInVM);

  Dart_PersistentHandle persistent_result;
  {
    TransitionVMToNative transition(mutator_thread);
    Dart_Handle result = Dart_InvokeClosure(closure, 0, nullptr);
    persistent_result = Dart_NewPersistentHandle(result);
  }

  mutator_thread->ExitApiScope();

  Thread::ExitIsolateGroupAsMutator(/*bypass_safepoint=*/false);
  Thread::EnterIsolate(saved_isolate);

  Thread* T = Thread::Current();
  T->EnterSafepointToNative();
  T->set_execution_state(Thread::kThreadInNative);

  Dart_Handle local_handle = Dart_HandleFromPersistent(persistent_result);
  Dart_DeletePersistentHandle(persistent_result);
  return local_handle;
}

}  // namespace dart
