// 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.

#ifndef FLUTTER_RUNTIME_DART_SERVICE_ISOLATE_H_
#define FLUTTER_RUNTIME_DART_SERVICE_ISOLATE_H_

#include <functional>
#include <mutex>
#include <set>
#include <string>

#include "flutter/fml/compiler_specific.h"
#include "third_party/dart/runtime/include/dart_api.h"

namespace flutter {

//------------------------------------------------------------------------------
/// @brief      Utility methods for interacting with the DartVM managed service
///             isolate present in debug and profile runtime modes.
///
class DartServiceIsolate {
 public:
  //----------------------------------------------------------------------------
  /// The handle used to refer to callbacks registered with the service isolate.
  ///
  using CallbackHandle = ptrdiff_t;

  //----------------------------------------------------------------------------
  /// A callback made by the Dart VM when the VM Service is ready. The argument
  /// indicates the VM Service URI.
  ///
  using DartVMServiceServerStateCallback =
      std::function<void(const std::string& vm_service_uri)>;

  //----------------------------------------------------------------------------
  /// @brief      Start the service isolate. This call may only be made in the
  ///             Dart VM initiated isolate creation callback. It is only valid
  ///             to make this call when the VM explicitly requests the creation
  ///             of the service isolate. The VM does this by specifying the
  ///             script URI to be `DART_VM_SERVICE_ISOLATE_NAME`. The isolate
  ///             to be designated as the service isolate must already be
  ///             created (but not running) when this call is made.
  ///
  /// @param[in]  server_ip                     The service protocol IP address.
  /// @param[in]  server_port                   The service protocol port.
  /// @param[in]  embedder_tag_handler          The library tag handler.
  /// @param[in]  disable_origin_check          If websocket origin checks must
  ///                                           be enabled.
  /// @param[in]  disable_service_auth_codes    If service auth codes must be
  ///                                           enabled.
  /// @param[in]  enable_service_port_fallback  If fallback to port 0 must be
  ///                                           enabled when the bind fails.
  /// @param      error                         The error when this method
  ///                                           returns false. This string must
  ///                                           be freed by the caller using
  ///                                           `free`.
  ///
  /// @return     If the startup was successful. Refer to the `error` for
  ///             details on failure.
  ///
  static bool Startup(const std::string& server_ip,
                      intptr_t server_port,
                      Dart_LibraryTagHandler embedder_tag_handler,
                      bool disable_origin_check,
                      bool disable_service_auth_codes,
                      bool enable_service_port_fallback,
                      char** error);

  //----------------------------------------------------------------------------
  /// @brief      Add a callback that will get invoked when the VM Service
  ///             starts up. If the VM Service has already started before this
  ///             call is made, the callback is invoked immediately.
  ///
  ///             This method is thread safe.
  ///
  /// @param[in]  callback  The callback with information about the VM Service.
  ///
  /// @return     A handle for the callback that can be used later in
  ///             `RemoveServerStatusCallback`.
  ///
  [[nodiscard]] static CallbackHandle AddServerStatusCallback(
      const DartVMServiceServerStateCallback& callback);

  //----------------------------------------------------------------------------
  /// @brief      Removed a callback previously registered via
  ///             `AddServiceStatusCallback`.
  ///
  ///             This method is thread safe.
  ///
  /// @param[in]  handle  The handle
  ///
  /// @return     If the callback was unregistered. This may fail if there was
  ///             no such callback with that handle.
  ///
  static bool RemoveServerStatusCallback(CallbackHandle handle);

 private:
  // Native entries.
  static void NotifyServerState(Dart_NativeArguments args);
  static void Shutdown(Dart_NativeArguments args);

  static std::mutex callbacks_mutex_;
  static std::set<std::unique_ptr<DartVMServiceServerStateCallback>> callbacks_;
};

}  // namespace flutter

#endif  // FLUTTER_RUNTIME_DART_SERVICE_ISOLATE_H_
