// 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/dart_api_impl.h"
#include "vm/ffi_callback_metadata.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)) {
  if (!FLAG_experimental_shared_data) {
    FATAL(
        "Encountered shared data api when functionality is disabled. "
        "Pass --experimental-shared-data");
  }
  Thread* current_thread = Thread::Current();
  ASSERT(current_thread->execution_state() == Thread::kThreadInNative);

  {
    DARTSCOPE(current_thread);
    FfiCallbackMetadata::EnsureOnlyTriviallyImmutableValuesInClosure(
        current_thread->zone(), Closure::RawCast(Api::UnwrapHandle(closure)));
  }

  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->set_execution_state(Thread::kThreadInNative);
  T->EnterSafepoint();

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

}  // namespace dart
