#include "Utils.h"

#include <Misc.h>

namespace sharedjsi
{

Function ditto_small_peer_info_get_is_enabled(Runtime &runtime) {
  return Function::createFromHostFunction(runtime,
                                          PropNameID::forAscii(runtime,
                                                               STRINGIFIED_FUNC_NAME()),
                                          0,
                                          [](Runtime &runtime,
                                             const Value &thisValue,
                                             const Value *arguments,
                                             size_t count) -> Value
                                          {
    return ::ditto_small_peer_info_get_is_enabled(jsPointerObjectToCPointer<CDitto_t>(runtime, arguments[0]));
  });
}

Function ditto_small_peer_info_set_enabled(Runtime &runtime) {
  return Function::createFromHostFunction(runtime,
                                          PropNameID::forAscii(runtime,
                                                               STRINGIFIED_FUNC_NAME()),
                                          0,
                                          [](Runtime &runtime,
                                             const Value &thisValue,
                                             const Value *arguments,
                                             size_t count) -> Value
                                          {

    auto *ditto = jsPointerObjectToCPointer<CDitto_t>(runtime, arguments[0]);
    bool is_enabled = arguments[1].asBool();
    ::ditto_small_peer_info_set_enabled(ditto, is_enabled);
    return {};
  });
}

Function ditto_small_peer_info_get_sync_scope(Runtime &runtime) {
  return Function::createFromHostFunction(runtime,
                                          PropNameID::forAscii(runtime,
                                                               STRINGIFIED_FUNC_NAME()),
                                          0,
                                          [](Runtime &runtime,
                                             const Value &thisValue,
                                             const Value *arguments,
                                             size_t count) -> Value
                                          {
    DittoSmallPeerInfoSyncScope_t sync_scope = ::ditto_small_peer_info_get_sync_scope(jsPointerObjectToCPointer<CDitto_t>(runtime, arguments[0]));
    switch (sync_scope) {
      case DITTO_SMALL_PEER_INFO_SYNC_SCOPE_LOCAL_PEER_ONLY:
        return String::createFromUtf8(runtime, "LocalPeerOnly");
        break;
      case DITTO_SMALL_PEER_INFO_SYNC_SCOPE_BIG_PEER_ONLY:
        return String::createFromUtf8(runtime, "BigPeerOnly");
        break;
    }
  });
}

Function ditto_small_peer_info_set_sync_scope(Runtime &runtime) {
  return Function::createFromHostFunction(runtime,
                                          PropNameID::forAscii(runtime,
                                                               STRINGIFIED_FUNC_NAME()),
                                          0,
                                          [](Runtime &runtime,
                                             const Value &thisValue,
                                             const Value *arguments,
                                             size_t count) -> Value
                                          {

    auto *ditto = jsPointerObjectToCPointer<CDitto_t>(runtime, arguments[0]);
    std::string sync_scope_str = arguments[1].toString(runtime).utf8(runtime);

    DittoSmallPeerInfoSyncScope_t sync_scope;
    if (sync_scope_str == "LocalPeerOnly") {
      sync_scope = DITTO_SMALL_PEER_INFO_SYNC_SCOPE_LOCAL_PEER_ONLY;
    } else if (sync_scope_str == "BigPeerOnly") {
      sync_scope = DITTO_SMALL_PEER_INFO_SYNC_SCOPE_BIG_PEER_ONLY;
    } else {
      throw "The string provided for Sync Scope is incorrect. Please ensure it matches the expected format.";
    }

    ::ditto_small_peer_info_set_sync_scope(ditto, sync_scope);
    return {};
  });
}

Function ditto_small_peer_info_get_metadata(Runtime &runtime) {
  return Function::createFromHostFunction(runtime,
                                          PropNameID::forAscii(runtime,
                                                               STRINGIFIED_FUNC_NAME()),
                                          0,
                                          [](Runtime &runtime,
                                             const Value &thisValue,
                                             const Value *arguments,
                                             size_t count) -> Value
                                          {
    char *metadata = ::ditto_small_peer_info_get_metadata(jsPointerObjectToCPointer<CDitto_t>(runtime, arguments[0]));
    return cPointerToJSPointerObject<char>(runtime, metadata);
  });

}

Function ditto_small_peer_info_set_metadata(Runtime &runtime) {
  return Function::createFromHostFunction(runtime,
                                          PropNameID::forAscii(runtime,
                                                               STRINGIFIED_FUNC_NAME()),
                                          0,
                                          [](Runtime &runtime,
                                             const Value &thisValue,
                                             const Value *arguments,
                                             size_t count) -> Value
                                          {
    auto *ditto = jsPointerObjectToCPointer<CDitto_t>(runtime, arguments[0]);
    std::string metadata_str = jsTypedArrayToCString(runtime, arguments[1]);
    const char *metadata = metadata_str.c_str();

    return ::ditto_small_peer_info_set_metadata(ditto, metadata);
  });
}
}
