#ifndef _DITTO_SWIG_RETAINABLE_
#define _DITTO_SWIG_RETAINABLE_

// Note that assumeoverride=1 is required on Retainable subclasses
#ifdef SWIG
%feature("director", assumeoverride=1) Retainable;
%typemap(javainterfaces) Retainable %{ AutoCloseable %}
%typemap(javaout) void java_retain() {
  live.ditto.internal.ffi.FfiResource.retain(this);
}
%typemap(javaout) void java_release() {
  live.ditto.internal.ffi.FfiResource.release(this);
}
%javaexception("Exception") Retainable::java_release %{
try {
$action
} catch (Swig::DirectorException &e) {}
%}
%typemap(javacode) Retainable %{
  public void close() throws Exception {}
%}
#endif

typedef struct Erased Erased_t;

class Retainable {
public:
  virtual ~Retainable() {}
  virtual void java_retain() = 0;
  virtual void java_release() = 0;
  bool is_closing = false;
  static void invokeRetain(void *ctx) {
    auto inst = static_cast<Retainable*>(ctx);
    inst->java_retain();
  }
  static Erased_t * invokeVirtualPtrRetain(Erased_t const *ctx) {
    auto inst = (Retainable*)(ctx);
    inst->java_retain();
    return const_cast<Erased_t *>(ctx);
  }
  static void invokeRelease(void *ctx) {
    auto inst = static_cast<Retainable*>(ctx);
    inst->java_release();
  }
};

#endif
