1/*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef COMMUNICATIONNETMANAGER_BASE_NETMANAGER_BASE_MODULE_TEMPLATE_H
17#define COMMUNICATIONNETMANAGER_BASE_NETMANAGER_BASE_MODULE_TEMPLATE_H
18
19#include <initializer_list>
20
21#include <napi/native_api.h>
22#include <napi/native_common.h>
23
24#include "base_context.h"
25#include "napi_utils.h"
26#include "netmanager_base_log.h"
27
28#define MAX_PARAM_NUM 64
29
30namespace OHOS {
31namespace NetManagerStandard {
32namespace ModuleTemplate {
33using Finalizer = void (*)(napi_env env, void *data, void *);
34
35template <class Context>
36napi_value InterfaceWithoutManager(napi_env env, napi_callback_info info, const std::string &asyncWorkName,
37                                   bool (*Work)(napi_env, napi_value, Context *), AsyncWorkExecutor executor,
38                                   AsyncWorkCallback callback)
39{
40    static_assert(std::is_base_of<BaseContext, Context>::value);
41
42    napi_value thisVal = nullptr;
43    size_t paramsCount = MAX_PARAM_NUM;
44    napi_value params[MAX_PARAM_NUM] = {nullptr};
45    NAPI_CALL(env, napi_get_cb_info(env, info, &paramsCount, params, &thisVal, nullptr));
46
47    auto context = new Context(env, nullptr);
48    context->ParseParams(params, paramsCount);
49    if (context->IsNeedThrowException()) { // only api9 or later need throw exception.
50        napi_throw_error(env, std::to_string(context->GetErrorCode()).c_str(), context->GetErrorMessage().c_str());
51        delete context;
52        context = nullptr;
53        return NapiUtils::GetUndefined(env);
54    }
55    if (Work != nullptr) {
56        if (!Work(env, thisVal, context)) {
57            NETMANAGER_BASE_LOGE("work failed error code = %{public}d", context->GetErrorCode());
58        }
59    }
60
61    context->CreateAsyncWork(asyncWorkName, executor, callback);
62    if (NapiUtils::GetValueType(env, context->GetCallback()) != napi_function && context->IsNeedPromise()) {
63        return context->CreatePromise();
64    }
65    return NapiUtils::GetUndefined(env);
66}
67
68template <class Context>
69napi_value Interface(napi_env env, napi_callback_info info, const std::string &asyncWorkName,
70                     bool (*Work)(napi_env, napi_value, Context *), AsyncWorkExecutor executor,
71                     AsyncWorkCallback callback)
72{
73    static_assert(std::is_base_of<BaseContext, Context>::value);
74
75    napi_value thisVal = nullptr;
76    size_t paramsCount = MAX_PARAM_NUM;
77    napi_value params[MAX_PARAM_NUM] = {nullptr};
78    NAPI_CALL(env, napi_get_cb_info(env, info, &paramsCount, params, &thisVal, nullptr));
79
80    EventManager *manager = nullptr;
81    napi_unwrap(env, thisVal, reinterpret_cast<void **>(&manager));
82
83    auto context = new Context(env, manager);
84    context->ParseParams(params, paramsCount);
85    if (context->IsNeedThrowException()) { // only api9 or later need throw exception.
86        napi_throw_error(env, std::to_string(context->GetErrorCode()).c_str(), context->GetErrorMessage().c_str());
87        delete context;
88        context = nullptr;
89        return NapiUtils::GetUndefined(env);
90    }
91    if (Work != nullptr) {
92        if (!Work(env, thisVal, context)) {
93            NETMANAGER_BASE_LOGE("work failed error code = %{public}d", context->GetErrorCode());
94        }
95    }
96
97    context->CreateAsyncWork(asyncWorkName, executor, callback);
98    if (NapiUtils::GetValueType(env, context->GetCallback()) != napi_function && context->IsNeedPromise()) {
99        return context->CreatePromise();
100    }
101    return NapiUtils::GetUndefined(env);
102}
103
104template <class Context>
105napi_value InterfaceSync(napi_env env, napi_callback_info info, const std::string &asyncWorkName,
106                         bool (*Work)(napi_env, napi_value, Context *), bool (*executor)(Context *),
107                         napi_value (*callback)(Context *))
108{
109    static_assert(std::is_base_of<BaseContext, Context>::value);
110
111    napi_value thisVal = nullptr;
112    size_t paramsCount = MAX_PARAM_NUM;
113    napi_value params[MAX_PARAM_NUM] = {nullptr};
114    NAPI_CALL(env, napi_get_cb_info(env, info, &paramsCount, params, &thisVal, nullptr));
115    EventManager *manager = nullptr;
116    napi_unwrap(env, thisVal, reinterpret_cast<void **>(&manager));
117
118    auto deleter = [](Context *context) { delete context; };
119    auto text = new Context(env, manager);
120    std::unique_ptr<Context, decltype(deleter)> context(text, deleter);
121    if (!context) {
122        return NapiUtils::GetUndefined(env);
123    }
124
125    context->ParseParams(params, paramsCount);
126    if (!context->IsParseOK()) {
127        napi_throw_error(env, std::to_string(context->GetErrorCode()).c_str(), context->GetErrorMessage().c_str());
128        return NapiUtils::GetUndefined(env);
129    }
130    if (Work != nullptr) {
131        if (!Work(env, thisVal, context.get())) {
132            NETMANAGER_BASE_LOGE("work failed error code = %{public}d", context->GetErrorCode());
133        }
134    }
135
136    if (!executor || !callback) {
137        NETMANAGER_BASE_LOGE("executor or callback is null");
138        return NapiUtils::GetUndefined(context->GetEnv());
139    }
140
141    if (!executor(context.get())) {
142        NETMANAGER_BASE_LOGE("executor is fail, errorcode= %{public}d", context->GetErrorCode());
143        napi_throw_error(env, std::to_string(context->GetErrorCode()).c_str(), context->GetErrorMessage().c_str());
144        return NapiUtils::GetUndefined(env);
145    }
146    return callback(context.get());
147}
148
149template <class Context>
150napi_value InterfaceWithOutAsyncWork(napi_env env, napi_callback_info info,
151                                     bool (*Work)(napi_env, napi_value, Context *))
152{
153    static_assert(std::is_base_of<BaseContext, Context>::value);
154
155    napi_value thisVal = nullptr;
156    size_t paramsCount = MAX_PARAM_NUM;
157    napi_value params[MAX_PARAM_NUM] = {nullptr};
158    NAPI_CALL(env, napi_get_cb_info(env, info, &paramsCount, params, &thisVal, nullptr));
159
160    EventManager *manager = nullptr;
161    napi_unwrap(env, thisVal, reinterpret_cast<void **>(&manager));
162
163    auto context = new Context(env, manager);
164    context->ParseParams(params, paramsCount);
165    if (Work != nullptr) {
166        if (!Work(env, thisVal, context)) {
167            NETMANAGER_BASE_LOGE("work failed error code = %{public}d", context->GetErrorCode());
168        }
169    }
170
171    if (NapiUtils::GetValueType(env, context->GetCallback()) != napi_function && context->IsNeedPromise()) {
172        return context->CreatePromise();
173    }
174    return NapiUtils::GetUndefined(env);
175}
176
177napi_value On(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events,
178              bool asyncCallback);
179
180napi_value Once(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events,
181                bool asyncCallback);
182
183napi_value Off(napi_env env, napi_callback_info info, const std::initializer_list<std::string> &events);
184
185void DefineClass(napi_env env, napi_value exports, const std::initializer_list<napi_property_descriptor> &properties,
186                 const std::string &className);
187
188napi_value NewInstance(napi_env env, napi_callback_info info, const std::string &className,
189                       void *(*MakeData)(napi_env, size_t, napi_value *, EventManager *), Finalizer finalizer);
190} // namespace ModuleTemplate
191} // namespace NetManagerStandard
192} // namespace OHOS
193#endif // COMMUNICATIONNETMANAGER_BASE_NETMANAGER_BASE_MODULE_TEMPLATE_H
194