// 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/runtime/dart_vm_lifecycle.h"

#include <mutex>

namespace flutter {

// We need to explicitly put the constructor and destructor of the DartVM in the
// critical section. All accesses (not just const members) to the global VM
// object weak pointer are behind this mutex.
static std::mutex gVMMutex;
static std::weak_ptr<DartVM> gVM;
static std::shared_ptr<DartVM>* gVMLeak;

// We are going to be modifying more than just the control blocks of the
// following weak pointers (in the |Create| case where an old VM could not be
// reused). Ideally, we would use |std::atomic<std::weak_ptr<T>>| specialization
// but that is only available since C++20. We don't expect contention on these
// locks so we just use one mutex for all.
static std::mutex gVMDependentsMutex;
static std::weak_ptr<const DartVMData> gVMData;
static std::weak_ptr<ServiceProtocol> gVMServiceProtocol;
static std::weak_ptr<IsolateNameServer> gVMIsolateNameServer;

DartVMRef::DartVMRef(std::shared_ptr<DartVM> vm) : vm_(vm) {}

DartVMRef::DartVMRef(DartVMRef&& other) = default;

DartVMRef::~DartVMRef() {
  if (!vm_) {
    // If there is no valid VM (possible via a move), there is no way that the
    // decrement on the shared pointer can cause a collection. Avoid acquiring
    // the lifecycle lock in this case. This is just working around a
    // pessimization and not required for correctness.
    return;
  }
  std::scoped_lock lifecycle_lock(gVMMutex);
  vm_.reset();
}

DartVMRef DartVMRef::Create(Settings settings,
                            fml::RefPtr<DartSnapshot> vm_snapshot,
                            fml::RefPtr<DartSnapshot> isolate_snapshot) {
  std::scoped_lock lifecycle_lock(gVMMutex);

  if (!settings.leak_vm) {
    FML_CHECK(!gVMLeak)
        << "Launch settings indicated that the VM should shut down in the "
           "process when done but a previous launch asked the VM to leak in "
           "the same process. For proper VM shutdown, all VM launches must "
           "indicate that they should shut down when done.";
  }

  // If there is already a running VM in the process, grab a strong reference to
  // it.
  if (auto vm = gVM.lock()) {
    FML_DLOG(WARNING) << "Attempted to create a VM in a process where one was "
                         "already running. Ignoring arguments for current VM "
                         "create call and reusing the old VM.";
    // There was already a running VM in the process,
    return DartVMRef{std::move(vm)};
  }

  std::scoped_lock dependents_lock(gVMDependentsMutex);

  gVMData.reset();
  gVMServiceProtocol.reset();
  gVMIsolateNameServer.reset();
  gVM.reset();

  // If there is no VM in the process. Initialize one, hold the weak reference
  // and pass a strong reference to the caller.
  auto isolate_name_server = std::make_shared<IsolateNameServer>();
  auto vm = DartVM::Create(std::move(settings),          //
                           std::move(vm_snapshot),       //
                           std::move(isolate_snapshot),  //
                           isolate_name_server           //
  );

  if (!vm) {
    FML_LOG(ERROR) << "Could not create Dart VM instance.";
    return {nullptr};
  }

  gVMData = vm->GetVMData();
  gVMServiceProtocol = vm->GetServiceProtocol();
  gVMIsolateNameServer = isolate_name_server;
  gVM = vm;

  if (settings.leak_vm) {
    gVMLeak = new std::shared_ptr<DartVM>(vm);
  }

  return DartVMRef{std::move(vm)};
}

bool DartVMRef::IsInstanceRunning() {
  std::scoped_lock lock(gVMMutex);
  return !gVM.expired();
}

std::shared_ptr<const DartVMData> DartVMRef::GetVMData() {
  std::scoped_lock lock(gVMDependentsMutex);
  return gVMData.lock();
}

std::shared_ptr<ServiceProtocol> DartVMRef::GetServiceProtocol() {
  std::scoped_lock lock(gVMDependentsMutex);
  return gVMServiceProtocol.lock();
}

std::shared_ptr<IsolateNameServer> DartVMRef::GetIsolateNameServer() {
  std::scoped_lock lock(gVMDependentsMutex);
  return gVMIsolateNameServer.lock();
}

DartVM* DartVMRef::GetRunningVM() {
  std::scoped_lock lock(gVMMutex);
  auto vm = gVM.lock().get();
  FML_CHECK(vm) << "Caller assumed VM would be running when it wasn't";
  return vm;
}

}  // namespace flutter
