#include "Utils.h"
#include "ConnectionRequest.h"
#include <unordered_map>

namespace sharedjsi
{

Function dittoffi_connection_request_peer_key_string(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 connection_request = jsPointerObjectToCPointer<dittoffi_connection_request_t>(runtime, arguments[0]);
    char *res = ::dittoffi_connection_request_peer_key_string(connection_request);
    return cPointerToJSPointerObject<char>(runtime, res);
  });
}

Function dittoffi_connection_request_peer_metadata_json(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 connection_request = jsPointerObjectToCPointer<dittoffi_connection_request_t>(runtime, arguments[0]);
    slice_ref_uint8_t res = ::dittoffi_connection_request_peer_metadata_json(connection_request);
    return cSlicedBoxToJSSlicedBox(runtime, res);

  });
}

Function dittoffi_connection_request_identity_service_json(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 connection_request = jsPointerObjectToCPointer<dittoffi_connection_request_t>(runtime, arguments[0]);
    slice_ref_uint8_t res = ::dittoffi_connection_request_identity_service_metadata_json(connection_request);
    return cSlicedBoxToJSSlicedBox(runtime, res);
  });
}

Function dittoffi_connection_request_authorize(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 connection_request = jsPointerObjectToCPointer<dittoffi_connection_request_t>(runtime, arguments[0]);
    auto authorized_string = arguments[1].toString(runtime).utf8(runtime);
    auto authorized = authorized_string == "Allow" ? DITTOFFI_CONNECTION_REQUEST_AUTHORIZATION_ALLOW : DITTOFFI_CONNECTION_REQUEST_AUTHORIZATION_DENY;

    ::dittoffi_connection_request_authorize(connection_request, authorized);
    return {};
  });
}

Function dittoffi_connection_request_connection_type(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
                                          {
    dittoffi_connection_type_t res = ::dittoffi_connection_request_connection_type(jsPointerObjectToCPointer<dittoffi_connection_request_t>(runtime, arguments[0]));

    static const std::unordered_map<dittoffi_connection_type_t, std::string> lookup = {
      {DITTOFFI_CONNECTION_TYPE_BLUETOOTH, "Bluetooth"},
      {DITTOFFI_CONNECTION_TYPE_ACCESS_POINT, "AccessPoint"},
      {DITTOFFI_CONNECTION_TYPE_P2_P_WI_FI, "P2PWiFi"},
      {DITTOFFI_CONNECTION_TYPE_WEB_SOCKET, "WebSocket"},
    };
    auto it = lookup.find(res);
    if (it != lookup.end()) {
      return String::createFromUtf8(runtime, it->second);
    } else {
      throw std::invalid_argument("Invalid dittoffi_connection_type_t type");
    }
  });
}

Function dittoffi_connection_request_free(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
                                          {
    ::dittoffi_connection_request_free(jsPointerObjectToCPointer<dittoffi_connection_request_t>(runtime, arguments[0]));
    return {};
  });
}
}
