// 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 observatory is ready. The argument
  /// indicates the observatory URI.
  ///
  using ObservatoryServerStateCallback =
      std::function<void(const std::string& observatory_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(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 observatory
  ///             starts up. If the observatory 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 observatory.
  ///
  /// @return     A handle for the callback that can be used later in
  ///             `RemoveServerStatusCallback`.
  ///
  [[nodiscard]] static CallbackHandle AddServerStatusCallback(
      const ObservatoryServerStateCallback& 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<ObservatoryServerStateCallback>> callbacks_;
};

}  // namespace flutter

#endif  // FLUTTER_RUNTIME_DART_SERVICE_ISOLATE_H_
