#pragma once

// N-API (node-addon-api)
#include <napi.h>

// Catboost C API
#include <c_api.h>

#include <util/generic/vector.h>

// Using STD version of string as it is used by N-API.
#include <string>

namespace NHelper {

// Checks if the condition is true, throws JS exception otherwise.
inline void Check(Napi::Env env, bool condition, const std::string& message) {
    if (!condition) {
        Napi::TypeError::New(env, message)
	    .ThrowAsJavaScriptException();
    }
}

// Checks if the pointer is not null, throws JS exception otherwise.
template <typename T>
inline void CheckNotNull(Napi::Env env, T* ptr, const std::string& message) {
    Check(env, ptr != nullptr, message);
}

// Checks that the model handle is not null. As this should never be the case throws internal error.
inline void CheckNotNullHandle(Napi::Env env, ModelCalcerHandle* handle) {
    return CheckNotNull(env, handle, "Internal error - null handle encountered");
}

// Checks that the return status of C API is true, returns error in JS exception otherwise.
inline void CheckStatus(Napi::Env& env, bool status) {
    if (!status) {
        const char* errorMessage = GetErrorString();
        CheckNotNull(env, errorMessage, "Internal error - error message expected, but missing");
        Napi::Error::New(env, errorMessage).ThrowAsJavaScriptException();
    }
}

// Matrix types in N-API
enum ENApiType {
    NAT_NUMBER,
    NAT_STRING,
};

// Checks if the value a matrix with element of a given type.
bool IsMatrix(const Napi::Value& value, ENApiType type);

// Converts vector of numbers to N-API array.
template <typename T>
Napi::Array ConvertToArray(Napi::Env env, const TVector<T>& values) {
    Napi::Array result = Napi::Array::New(env);
    uint32_t index = 0;
    for (const auto value: values) {
        result[index++] = Napi::Number::New(env, static_cast<double>(value));
    }

    return result;
}

}
