extern "C" {
#include "dittoffi.h"
}

#include "retainable.h"

#ifdef SWIG
%feature("director", assumeoverride=1) StoreObserverHandlerRust;
%apply(char *STRING, size_t LENGTH) { (const unsigned char *query_args_cbor, uintptr_t query_args_cbor_len) };
#endif

/** \brief
 *  Context object for Kotlin DittoStoreObserver which handles wiring up callbacks from rust
 *  across the FFI boundary.
 */
class StoreObserverHandlerRust: public Retainable {
public:
  virtual ~StoreObserverHandlerRust() {}

  virtual void eventHandler(
    ChangeHandlerWithQueryResult_t c_cb_params
  ) = 0;

  static void invokeEventHandler(
    void *ctx,
    ChangeHandlerWithQueryResult_t c_cb_params
  ) {
    auto inst = static_cast<StoreObserverHandlerRust*>(ctx);
    return inst->eventHandler(c_cb_params);
  }

  virtual dittoffi_result_int64_t registerStoreObserver(
    struct CDitto *ditto_raw,
    const char *query,
    const unsigned char *query_args_cbor,
    uintptr_t query_args_cbor_len,
    LiveQueryAvailability_t lq_availability
  ) {
    return dittoffi_try_experimental_register_change_observer_str(
      ditto_raw,
      query,
      slice_ref_uint8_t {
        .ptr = (uint8_t const *)query_args_cbor,
        .len = query_args_cbor_len,
      },
      lq_availability,
      this,
      StoreObserverHandlerRust::invokeRetain,
      StoreObserverHandlerRust::invokeRelease,
      StoreObserverHandlerRust::invokeEventHandler
    );
  }

  virtual int startLiveQuery(struct CDitto *ditto_raw, int64_t id) {
    return ditto_live_query_start(ditto_raw, id);
  }
};
