#include "retainable.h"

extern "C" {
    #include "dittoffi.h"
    #include <android/log.h>
}

#ifdef SWIG
%feature("director", assumeoverride=1) PresenceRust;
#endif
class PresenceRust : public Retainable {
private:
    CDitto_t *ditto;

public:
    PresenceRust() = delete;
    explicit PresenceRust(CDitto_t *ditto) : ditto(ditto) {}
    ~PresenceRust() override = default;

    virtual void v1Callback(const char *const json) = 0;
    virtual void v2Callback(const char *const json) = 0;
    virtual void v3Callback(const char *const json) = 0;

    static void invokeV1Callback(void *const ctx, const char *json) {
        const auto inst = static_cast<PresenceRust *>(ctx);
        return inst->v1Callback(json);
    }

    static void invokeV2Callback(void *const ctx, const char *const json) {
        const auto inst = static_cast<PresenceRust *>(ctx);
        return inst->v2Callback(json);
    }

    static void invokeV3Callback(void *const ctx, const char *const json) {
        const auto inst = static_cast<PresenceRust *>(ctx);
        return inst->v3Callback(json);
    }

    virtual void register_v1() {
        ditto_register_presence_v1_callback(ditto, this, PresenceRust::invokeRetain,
                                            PresenceRust::invokeRelease,
                                            PresenceRust::invokeV1Callback);
    }

    virtual void register_v2() {
        ditto_register_presence_v2_callback(ditto, this, PresenceRust::invokeRetain,
                                            PresenceRust::invokeRelease,
                                            PresenceRust::invokeV2Callback);
    }

    virtual void register_v3() {
        ditto_register_presence_callback_v3(ditto, this, PresenceRust::invokeRetain,
                                            PresenceRust::invokeRelease,
                                            PresenceRust::invokeV3Callback);
    }

    virtual void requestV1Update() {
        auto json = ditto_presence_v1(ditto);
        v1Callback(json);
        ditto_c_string_free(json);
    }

    virtual void requestV2Update() {
        auto json = ditto_presence_v2(ditto);
        v2Callback(json);
        ditto_c_string_free(json);
    }

    // Handler for a single update. Called immediately after register_v3 is invoked to deliver a
    // fresh value to the observer.
    virtual void requestV3Update() {
        auto json = ditto_presence_v3(ditto);
        if (json == nullptr) {
            // https://developer.android.com/ndk/reference/group/logging#__android_log_print
            __android_log_print(ANDROID_LOG_ERROR, "PresenceRust",
                                "requestV3Update: json returned from ditto_presence_v3 was NULL");
            return;
        }
        v3Callback(json);
        ditto_c_string_free(json);
    }
};
