// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#pragma once
#include "Logging.h"

#include <IRedBoxHandler.h>
#include <functional>
#include <map>
#include <memory>
#include <string>
#include <vector>

#define STRING_(s) #s
#define STRING(s) STRING_(s)

namespace Microsoft::JSI {
struct RuntimeHolderLazyInit;
} // namespace Microsoft::JSI

namespace facebook {
namespace react {

namespace jsinspector_modern {
class HostTarget;
} // namespace jsinspector_modern

enum class JSIEngineOverride : int32_t {
  Default = 3, // Now defaults to Hermes (New Architecture)

  Hermes = 3, // Use the JSIExecutorFactory with Hermes
  V8 = 4, // Use the JSIExecutorFactory with V8
  V8Lite = 5, // Use the JSIExecutorFactory with V8Lite
  V8NodeApi = 6, // Use the JSIExecutorFactory with V8 via ABI-safe NAPI

  Last = V8NodeApi
};

struct DevSettings {
  bool useJITCompilation{true};
  uint16_t sourceBundlePort{0};
  std::string sourceBundleHost;
  std::string debugBundlePath;
  std::string platformName{STRING(RN_PLATFORM)};
  std::string bundleAppId;
  std::function<void()> liveReloadCallback;
  std::function<void(std::string)> errorCallback;
  std::function<void()> waitingForDebuggerCallback;
  NativeLoggingHook loggingCallback;
  std::shared_ptr<Mso::React::IRedBoxHandler> redboxHandler;

  /// Enables the user to set a custom root path for bundle resolution
  std::string bundleRootPath;

  /// Enables debugging directly in the JavaScript engine.
  bool useDirectDebugger{false};

  /// For direct debugging, break on the next line of JavaScript executed
  bool debuggerBreakOnNextLine{false};

  /// For direct debugging, the port number to use, or zero for the default
  uint16_t debuggerPort{0};

  /// For direct debugging, name of runtime instance, or empty for default.
  std::string debuggerRuntimeName;

  bool useFastRefresh{false};

  /// A factory and holder of jsi::Runtime instance to be used for this react
  /// instance. This object should in general be used only from the JS engine
  /// thread, unless the specific runtime implementation explicitly guarantees
  /// reentrancy.
  std::shared_ptr<Microsoft::JSI::RuntimeHolderLazyInit> jsiRuntimeHolder;

  // Until the ABI story is addressed we'll use this instead of the above for
  // the purposes of selecting a JSI Runtime to use.
  JSIEngineOverride jsiEngineOverride{JSIEngineOverride::Default};

  /// Callback to show the devmenu
  std::function<void()> showDevMenuCallback;

  bool inlineSourceMap{true};

  // When querying the bundle server for a bundle, should it request the dev bundle or release bundle
  bool devBundle{true};

  bool enableDefaultCrashHandler{false};

  // Enable concurrent mode by installing runtimeScheduler
  bool useRuntimeScheduler{false};

  // The HostTarget instance for Fusebox
  facebook::react::jsinspector_modern::HostTarget *inspectorHostTarget;
};

} // namespace react
} // namespace facebook
