/**
 *
 * Agora Real Time Engagement
 * Created by Wei Hu in 2022-02.
 * Copyright (c) 2022 Agora IO. All rights reserved.
 *
 */
#pragma once

#include "rte_config.h"

#include <node_api.h>

#include "lib/shared_ptr.h"
#include "lib/signature.h"
#include "rte_runtime/sanitizer/thread_check.h"

#define RTE_NODEJS_MSG_SIGNATURE 0x544E62A3726AAF6EU

/**
 * @brief For the coding and architecture consistency of the overall RTE nodejs
 * binding, the architecture of the JS msg also uses the so-called 'shared-ptr'
 * architecture, and the shared-ptr is used to destroy the msg bridge.
 * However, only JS msg holds the reference count of the shared-ptr, and C
 * msg does _not_ hold the reference count of the shared-ptr, that is to say,
 * the JS msg has full control over the life cycle of not only the JS msg, but
 * also the msg bridge, and the underlying C msg, in other words, as long as the
 * JS msg is finalized, it will destroy the msg bridge, and the underlying C
 * msg.
 */
typedef struct rte_nodejs_msg_t {
  rte_signature_t signature;

  // Used to determine the timing of destroying this bridge.
  rte_sharedptr_t* shared_ptr;

  rte_sharedptr_t* c_msg;  // Point to the corresponding C msg.
  napi_ref js_ref;         // Point to the corresponding JS msg.

  rte_sanitizer_thread_check_t thread_check;
} rte_nodejs_msg_t;

AGORA_RTE_PRIVATE_API bool rte_nodejs_msg_check_integrity(
    rte_nodejs_msg_t* self, bool check_thread);

AGORA_RTE_PRIVATE_API void rte_nodejs_msg_init_from_c_msg(
    rte_nodejs_msg_t* self, rte_sharedptr_t* c_msg);

AGORA_RTE_PRIVATE_API void rte_nodejs_msg_deinit(rte_nodejs_msg_t* self);

AGORA_RTE_PRIVATE_API void rte_nodejs_msg_take_ownership_from_js(
    rte_nodejs_msg_t* self);

AGORA_RTE_PRIVATE_API void rte_nodejs_msg_release_ownership_from_js(
    rte_nodejs_msg_t* self);

AGORA_RTE_PRIVATE_API void rte_nodejs_msg_finalize(napi_env env,
                                                   rte_nodejs_msg_t* self);

AGORA_RTE_API napi_value rte_nodejs_msg_module_init(napi_env env,
                                                    napi_value exports);
