#pragma once

#include <iostream>
#include <memory>
#include <thread>
#include <vector>

#include <napi.h>


namespace NS_HELP
{

/**
 * Retrieve integer from n-api object or default value if it does not exist
 */
inline int32_t getObjInt32OrDefault(Napi::Object& obj, const char * name, int32_t defaultValue) {
    if (obj.Has(name)) {
        return obj.Get(name).As<Napi::Number>().Int32Value();
    } else {
        return defaultValue;
    }
}

/**
 * Retrieve bool value from n-api object or default value if it does not exist
 */
inline bool getObjBooleanOrDefault(Napi::Object& obj, const char * name, bool defaultValue) {
    if (obj.Has(name)) {
        return obj.Get(name).As<Napi::Boolean>().ToBoolean();
    } else {
        return defaultValue;
    }
}

/**
 * Retrieve string from n-api object or default value if it does not exist
 */
inline const std::string getObjStringOrDefault(Napi::Object& obj, const char * name, const std::string defaultValue) {
    if (obj.Has(name)) {
        return obj.Get(name).As<Napi::String>().ToString();
    } else {
        return defaultValue;
    }
}

/**
 * Retrieve enum value from n-api object or default value if it does not exist
 */
template<typename T>
const T getObjEnumValueOrDefault(Napi::Object& obj, const char * name, const T defaultValue) {
    if (obj.Has(name)) {
        return (T)obj.Get(name).As<Napi::Number>().Int32Value();
    } else {
        return defaultValue;
    }
}

/**
* Used by VerifyArgs´etc. to describe the type of javascript paramter to a native function.
*/
enum FormalParameterType
{
    _VOID, // Prefixed with "_" to avoid clash with Windows.h macro.
    BOOLEAN,
    NUMBER,
    // BIGINT,
    STRING,
    SYMBOL,
    ARRAYBUFFER,
    TYPEDARRAY,
    OBJECT,
    ARRAY,
    FUNCTION,
    PROMISE,
    DATAVIEW,
    BUFFER,
    EXTERNAL,
    OBJECT_OR_STRING
};

/**
 * Helper that checks if arguments of correct type exists - throws napi exception and returns false if not.
 **/
bool VerifyArgs(const char * const strCallFunctionName, const Napi::CallbackInfo &objInfo, std::initializer_list<FormalParameterType> listExpectedFormalParameterTypes);

/**
 * Create a C-string suitable for storing in a settings object from a std:string
 */
//char * newCString(const std::string& src);

/**
 * Create a C-string suitable for storing in a settings object from a napi string/null object.
 **/
//char * newCString(const Napi::Value& src);

/**
 * Encode a std::string to UTF-8.
 *
 * @param[in]   str         The string to be encoded.
 * @param[in]   callerName  The name of the caller function. Used only for
 *                          logging purposes in case of errors.
 * @param[in]   charset     The encoding of str.
 * @return  `str` encoded in UTF-8.
 */
//std::string toUtf8(const std::string& str, const char* const callerName,
//                   const std::string& charset = "");

/**
 * Create a C-string suitable for storing in a settings object from a std:string
 */
char * NewCString(const std::string& src);

/**
 * Create a C-string suitable for storing in a settings object from a napi string/null object.
 **/
char * NewCString(const Napi::Value& src);

#define NAPI_NEW_STRING(env, ptr)    ((ptr) ? Napi::String::New(env, ptr) : Napi::String::New(env, ""))

} // namespace NS_HELP

