// Generated by uniffi-bindgen-gecko-js.  DO NOT EDIT.

#include "nsString.h"
#include "nsPrintfCString.h"
#include "mozilla/Logging.h"
#include "mozilla/Maybe.h"
#include "mozilla/StaticPtr.h"
#include "mozilla/dom/UniFFICallbacks.h"
#include "mozilla/dom/UniFFIScaffolding.h"
#include "mozilla/dom/ScaffoldingCall.h"

namespace mozilla::uniffi {

using dom::ArrayBuffer;
using dom::AutoEntryScript;
using dom::GlobalObject;
using dom::RootedDictionary;
using dom::Promise;
using dom::ScaffoldingType;
using dom::Sequence;
using dom::UniFFICallbackHandler;
using dom::UniFFIPointer;
using dom::UniFFIScaffoldingCallResult;

// Define scaffolding functions from UniFFI
extern "C" {
  {%- for (ci, config) in components %}
  {%- for func in ci.iter_user_ffi_function_definitions() %}
  {{ func.rust_return_type() }} {{ func.rust_name() }}({{ func.rust_arg_list() }});
  {%- endfor %}
  {%- endfor %}
}

// Define pointer types
{%- for (ci, config) in components %}
{%- for object in ci.object_definitions() %}
{%- let pointer_type = ci.pointer_type(object) %}
const static mozilla::uniffi::UniFFIPointerType {{ pointer_type }} {
  "{{ "{}::{}"|format(ci.namespace(), object.name()) }}"_ns,
  {{ object.ffi_object_free().rust_name() }}
};
{%- endfor %}
{%- endfor %}

// Define the data we need per-callback interface
{%- for (ci, config) in components %}
{%- for cbi in ci.callback_interface_definitions() %}
MOZ_CAN_RUN_SCRIPT
extern "C" int {{ cbi.c_handler(prefix) }}(uint64_t aHandle, uint32_t aMethod, RustBuffer aArgs, RustBuffer* aOutBuffer) {
    // Currently, we only support "fire-and-forget" async callbacks.  These are
    // callbacks that run asynchronously without returning anything.  The main
    // use case for callbacks is logging, which fits very well with this model.
    //
    // So, here we simple queue the callback and return immediately.
    mozilla::uniffi::QueueCallback({{ callback_ids.get(ci, cbi) }}, aHandle, aMethod, aArgs);
    return CALLBACK_INTERFACE_SUCCESS;
}
static StaticRefPtr<dom::UniFFICallbackHandler> {{ cbi.js_handler() }};
{%- endfor %}
{%- endfor %}

// Define a lookup function for our callback interface info
Maybe<CallbackInterfaceInfo> {{ prefix }}GetCallbackInterfaceInfo(uint64_t aInterfaceId) {
    switch(aInterfaceId) {
        {%- for (ci, config) in components %}
        {%- for cbi in ci.callback_interface_definitions() %}
        case {{ callback_ids.get(ci, cbi) }}: { // {{ callback_ids.name(ci, cbi) }}
            return Some(CallbackInterfaceInfo {
                "{{ cbi.name() }}",
                &{{ cbi.js_handler() }},
                {{ cbi.c_handler(prefix) }},
                {{ cbi.ffi_init_callback().name() }},
            });
        }
        {%- endfor %}
        {%- endfor %}

        default:
            return Nothing();
    }
}

Maybe<already_AddRefed<Promise>> {{ prefix }}CallAsync(const GlobalObject& aGlobal, uint64_t aId, const Sequence<ScaffoldingType>& aArgs, ErrorResult& aError) {
  switch (aId) {
    {%- for (ci, config) in components %}
    {%- for func in ci.exposed_functions() %}
    case {{ function_ids.get(ci, func) }}: { // {{ function_ids.name(ci, func) }}
      using CallHandler = {{ ci.scaffolding_call_handler(func) }};
      return Some(CallHandler::CallAsync({{ func.rust_name() }}, aGlobal, aArgs, "{{ func.name() }}: "_ns, aError));
    }
    {%- endfor %}
    {%- endfor %}
  }
  return Nothing();
}

bool {{ prefix }}CallSync(const GlobalObject& aGlobal, uint64_t aId, const Sequence<ScaffoldingType>& aArgs, RootedDictionary<UniFFIScaffoldingCallResult>& aReturnValue, ErrorResult& aError) {
  switch (aId) {
    {%- for (ci, config) in components %}
    {%- for func in ci.exposed_functions() %}
    case {{ function_ids.get(ci, func) }}: { // {{ function_ids.name(ci, func) }}
      using CallHandler = {{ ci.scaffolding_call_handler(func) }};
      CallHandler::CallSync({{ func.rust_name() }}, aGlobal, aArgs, aReturnValue, "{{ func.name() }}: "_ns, aError);
      return true;
    }
    {%- endfor %}
    {%- endfor %}
  }
  return false;
}

Maybe<already_AddRefed<UniFFIPointer>> {{ prefix }}ReadPointer(const GlobalObject& aGlobal, uint64_t aId, const ArrayBuffer& aArrayBuff, long aPosition, ErrorResult& aError) {
  {%- if self.has_any_objects() %}
  const UniFFIPointerType* type;
  switch (aId) {
    {%- for (ci, config) in components %}
    {%- for object in ci.object_definitions() %}
    case {{ object_ids.get(ci, object) }}: { // {{ object_ids.name(ci, object) }}
      type = &{{ ci.pointer_type(object) }};
      break;
    }
    {%- endfor %}
    {%- endfor %}
    default:
      return Nothing();
  }
  return Some(UniFFIPointer::Read(aArrayBuff, aPosition, type, aError));
  {%- else %}
  return Nothing();
  {%- endif %}
}

bool {{ prefix }}WritePointer(const GlobalObject& aGlobal, uint64_t aId, const UniFFIPointer& aPtr, const ArrayBuffer& aArrayBuff, long aPosition, ErrorResult& aError) {
  {%- if self.has_any_objects() %}
  const UniFFIPointerType* type;
  switch (aId) {
    {%- for (ci, config) in components %}
    {%- for object in ci.object_definitions() %}
    case {{ object_ids.get(ci, object) }}: { // {{ object_ids.name(ci, object) }}
      type = &{{ ci.pointer_type(object) }};
      break;
    }
    {%- endfor %}
    {%- endfor %}
    default:
      return false;
  }
  aPtr.Write(aArrayBuff, aPosition, type, aError);
  return true;
  {%- else %}
  return false;
  {%- endif %}
}

}  // namespace mozilla::uniffi
