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

#ifdef SWIG
%feature("director", assumeoverride=1) TransactionCompletionContinuation;
%feature("director", assumeoverride=1) TransactionExecuteContinuation;
%feature("director", assumeoverride=1) BeginTransactionContinuation;
#endif

/** \brief
 *  Context object for Kotlin DittoTransaction.InternalTransactionCompletionContinuation which handles wiring up the
 *  callback from Rust across the FFI boundary.
 */
class TransactionCompletionContinuation : public Retainable {
public:
    virtual ~TransactionCompletionContinuation() {}

    // To be overridden by Kotlin/Java
    virtual void invoke(dittoffi_result_dittoffi_transaction_completion_action_t result) = 0;

    static void invokeContinuationCompletion(void *const context,
                                             dittoffi_result_dittoffi_transaction_completion_action_t result) {
        auto instance = static_cast<TransactionCompletionContinuation *>(context);
        instance->invoke(result);
    }

    BoxDynFnMut1_void_dittoffi_result_dittoffi_transaction_completion_action_t intoFfi() {
        this->java_retain();
        BoxDynFnMut1_void_dittoffi_result_dittoffi_transaction_completion_action_t ffiCompletion = {};
        ffiCompletion.env_ptr = this;
        ffiCompletion.call = TransactionCompletionContinuation::invokeContinuationCompletion;
        ffiCompletion.free = TransactionCompletionContinuation::invokeRelease;
        return ffiCompletion;
    }
};

/** \brief
 *  Context object for Kotlin DittoTransaction.InternalTransactionExecuteContinuation which handles wiring up the
 *  callback from Rust across the FFI boundary.
 */
class TransactionExecuteContinuation : public Retainable {
public:
    virtual ~TransactionExecuteContinuation() {}

    // To be overridden by Kotlin/Java
    virtual void invoke(dittoffi_result_dittoffi_query_result_ptr_t result) = 0;

    static void invokeContinuationExecute(void *const context,
                                          dittoffi_result_dittoffi_query_result_ptr_t result) {
        auto instance = static_cast<TransactionExecuteContinuation *>(context);
        instance->invoke(result);
    }

    BoxDynFnMut1_void_dittoffi_result_dittoffi_query_result_ptr_t intoFfi() {
        this->java_retain();
        BoxDynFnMut1_void_dittoffi_result_dittoffi_query_result_ptr_t ffiExecute = {};
        ffiExecute.env_ptr = this;
        ffiExecute.call = TransactionExecuteContinuation::invokeContinuationExecute;
        ffiExecute.free = TransactionExecuteContinuation::invokeRelease;
        return ffiExecute;
    }
};

/** \brief
 *  Context object for Kotlin DittoStore.InternalDittoBeginTransactionContinuation which handles wiring up the
 *  callback from Rust across the FFI boundary.
 */
class BeginTransactionContinuation : public Retainable {
public:
    virtual ~BeginTransactionContinuation() {}

    // To be overridden by Kotlin
    virtual void invoke(dittoffi_result_dittoffi_transaction_ptr_t result) = 0;

    static void invokeContinuation(void *const context,
                                   dittoffi_result_dittoffi_transaction_ptr_t result) {
        auto instance = static_cast<BeginTransactionContinuation *>(context);
        instance->invoke(result);
    }

    BoxDynFnMut1_void_dittoffi_result_dittoffi_transaction_ptr_t intoFfi() {
        this->java_retain();
        BoxDynFnMut1_void_dittoffi_result_dittoffi_transaction_ptr_t ffiBeginTransaction = {};
        ffiBeginTransaction.env_ptr = this;
        ffiBeginTransaction.call = BeginTransactionContinuation::invokeContinuation;
        ffiBeginTransaction.free = BeginTransactionContinuation::invokeRelease;
        return ffiBeginTransaction;
    }
};
