#ifndef KERBEROS_NATIVE_EXTENSION_H
#define KERBEROS_NATIVE_EXTENSION_H

#define NAPI_VERSION 9

#include <napi.h>

#include "kerberos_common.h"

namespace node_kerberos {

bool kerberos_libraries_available(std::string* error_out);

class KerberosServer : public Napi::ObjectWrap<KerberosServer> {
   public:
    static Napi::Function Init(Napi::Env env);
    static Napi::Object NewInstance(Napi::Env env, std::shared_ptr<krb_server_state> state);

    std::shared_ptr<krb_server_state> state() const;

   private:
    Napi::Value UserNameGetter(const Napi::CallbackInfo& info);
    Napi::Value ResponseGetter(const Napi::CallbackInfo& info);
    Napi::Value TargetNameGetter(const Napi::CallbackInfo& info);
    Napi::Value ContextCompleteGetter(const Napi::CallbackInfo& info);

    void Step(const Napi::CallbackInfo& info);

   private:
    friend class Napi::ObjectWrap<KerberosServer>;
    explicit KerberosServer(const Napi::CallbackInfo& info);

    std::shared_ptr<krb_server_state> _state;
};

class KerberosClient : public Napi::ObjectWrap<KerberosClient> {
   public:
    static Napi::Function Init(Napi::Env env);
    static Napi::Object NewInstance(Napi::Env env, std::shared_ptr<krb_client_state> state);

    std::shared_ptr<krb_client_state> state() const;

   private:
    Napi::Value UserNameGetter(const Napi::CallbackInfo& info);
    Napi::Value ResponseGetter(const Napi::CallbackInfo& info);
    Napi::Value ResponseConfGetter(const Napi::CallbackInfo& info);
    Napi::Value ContextCompleteGetter(const Napi::CallbackInfo& info);

    void Step(const Napi::CallbackInfo& info);
    void UnwrapData(const Napi::CallbackInfo& info);
    void WrapData(const Napi::CallbackInfo& info);

    int ParseWrapOptionsProtect(const Napi::Object& options);

   private:
    friend class Napi::ObjectWrap<KerberosClient>;
    explicit KerberosClient(const Napi::CallbackInfo& info);

    std::shared_ptr<krb_client_state> _state;
};

void PrincipalDetails(const Napi::CallbackInfo& info);
void InitializeClient(const Napi::CallbackInfo& info);
void InitializeServer(const Napi::CallbackInfo& info);
void CheckPassword(const Napi::CallbackInfo& info);

std::string ToStringWithNonStringAsEmpty(Napi::Value value);

Napi::Value GetDefinedNapiVersion(const Napi::CallbackInfo& info);

}  // namespace node_kerberos

#endif  // KERBEROS_NATIVE_EXTENSION_H
