/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#pragma once

#ifdef __APPLE__
#include <functional>
#endif

namespace facebook {
namespace react {
namespace ReactMarker {

enum ReactMarkerId {
  NATIVE_REQUIRE_START,
  NATIVE_REQUIRE_STOP,
  RUN_JS_BUNDLE_START,
  RUN_JS_BUNDLE_STOP,
  CREATE_REACT_CONTEXT_STOP,
  JS_BUNDLE_STRING_CONVERT_START,
  JS_BUNDLE_STRING_CONVERT_STOP,
  NATIVE_MODULE_SETUP_START,
  NATIVE_MODULE_SETUP_STOP,
  REGISTER_JS_SEGMENT_START,
  REGISTER_JS_SEGMENT_STOP,
  REACT_INSTANCE_INIT_START,
  REACT_INSTANCE_INIT_STOP
};

#ifdef __APPLE__
using LogTaggedMarker =
    std::function<void(const ReactMarkerId, const char *tag)>; // Bridge only
using LogTaggedMarkerBridgeless =
    std::function<void(const ReactMarkerId, const char *tag)>;
using GetAppStartTime = std::function<double()>;
#else
typedef void (
    *LogTaggedMarker)(const ReactMarkerId, const char *tag); // Bridge only
typedef void (*LogTaggedMarkerBridgeless)(const ReactMarkerId, const char *tag);
typedef double (*GetAppStartTime)();
#endif

#ifndef RN_EXPORT
#define RN_EXPORT __attribute__((visibility("default")))
#endif

extern RN_EXPORT LogTaggedMarker logTaggedMarkerImpl; // Bridge only
extern RN_EXPORT LogTaggedMarker logTaggedMarkerBridgelessImpl;
extern RN_EXPORT GetAppStartTime getAppStartTimeImpl;

extern RN_EXPORT void logMarker(const ReactMarkerId markerId); // Bridge only
extern RN_EXPORT void logTaggedMarker(
    const ReactMarkerId markerId,
    const char *tag); // Bridge only
extern RN_EXPORT void logMarkerBridgeless(const ReactMarkerId markerId);
extern RN_EXPORT void logTaggedMarkerBridgeless(
    const ReactMarkerId markerId,
    const char *tag);
extern RN_EXPORT double getAppStartTime();

struct ReactMarkerEvent {
  const ReactMarkerId markerId;
  const char *tag;
  double time;
};

class StartupLogger {
 public:
  static StartupLogger &getInstance();

  void logStartupEvent(const ReactMarker::ReactMarkerId markerId);
  double getAppStartTime();
  double getRunJSBundleStartTime();
  double getRunJSBundleEndTime();

 private:
  StartupLogger() = default;
  StartupLogger(const StartupLogger &) = delete;
  StartupLogger &operator=(const StartupLogger &) = delete;

  double runJSBundleStartTime;
  double runJSBundleEndTime;
};

} // namespace ReactMarker
} // namespace react
} // namespace facebook
