1/*
2 * Copyright (c) 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#ifndef CALENDAR_MANAGER_NAPI_QUEUE_H
16#define CALENDAR_MANAGER_NAPI_QUEUE_H
17#include <functional>
18#include <memory>
19#include <string>
20
21#include "calendar_log.h"
22#include "napi/native_api.h"
23#include "napi/native_common.h"
24#include "napi/native_node_api.h"
25
26namespace OHOS::CalendarApi {
27constexpr size_t ARGC_MAX = 6;
28using NapiCbInfoParser = std::function<void(size_t argc, napi_value* argv)>;
29using NapiAsyncExecute = std::function<void(void)>;
30using NapiAsyncComplete = std::function<void(napi_value&)>;
31
32struct ContextBase {
33    virtual ~ContextBase();
34    void GetCbInfo(napi_env env, napi_callback_info info,
35                   NapiCbInfoParser parse = NapiCbInfoParser(), bool sync = false);
36
37    inline void GetCbInfoSync(napi_env env, napi_callback_info info, NapiCbInfoParser parse = NapiCbInfoParser())
38    {
39        GetCbInfo(env, info, parse, true);
40    }
41
42    napi_env env = nullptr;
43    napi_value output = nullptr;
44    napi_status status = napi_invalid_arg;
45    std::string error;
46
47    napi_value self = nullptr;
48    void* native = nullptr;
49
50private:
51    napi_ref callbackRef = nullptr;
52    napi_ref selfRef = nullptr;
53    friend class NapiQueue;
54};
55
56/* check condition related to argc/argv, return and logging. */
57#define CHECK_ARGS_RETURN_VOID(ctxt, condition, message)                    \
58    do {                                                                    \
59        if (!(condition)) {                                                 \
60            (ctxt)->status = napi_invalid_arg;                              \
61            (ctxt)->error = std::string(message);                           \
62            LOG_ERROR("test (" #condition ") failed: " message);            \
63            return;                                                         \
64        }                                                                   \
65    } while (0)
66
67#define CHECK_STATUS_RETURN_VOID(ctxt, message)                        \
68    do {                                                               \
69        if ((ctxt)->status != napi_ok) {                               \
70            (ctxt)->error = std::string(message);                      \
71            LOG_ERROR("test (ctxt->status %{public}d) failed: " message, (ctxt)->status);  \
72            return;                                                    \
73        }                                                              \
74    } while (0)
75
76/* check condition, return and logging if condition not true. */
77#define CHECK_RETURN(condition, message, retVal)             \
78    do {                                                     \
79        if (!(condition)) {                                  \
80            LOG_ERROR("test (" #condition ") failed: " message); \
81            return retVal;                                   \
82        }                                                    \
83    } while (0)
84
85#define CHECK_RETURN_VOID(condition, message)                \
86    do {                                                     \
87        if (!(condition)) {                                  \
88            LOG_ERROR("test (" #condition ") failed: " message); \
89            return;                                          \
90        }                                                    \
91    } while (0)
92
93class NapiQueue {
94public:
95    static napi_value AsyncWork(napi_env env, std::shared_ptr<ContextBase> ctxt,
96                                const std::string& name, NapiAsyncExecute execute = NapiAsyncExecute(),
97                                NapiAsyncComplete complete = NapiAsyncComplete());
98
99private:
100    enum {
101        RESULT_ERROR = 0,
102        RESULT_DATA = 1,
103        RESULT_ALL = 2
104    };
105
106    struct AsyncContext {
107        napi_env env = nullptr;
108        std::shared_ptr<ContextBase> ctx;
109        NapiAsyncExecute execute = nullptr;
110        NapiAsyncComplete complete = nullptr;
111        napi_deferred deferred = nullptr;
112        napi_async_work work = nullptr;
113        ~AsyncContext()
114        {
115            execute = nullptr;
116            complete = nullptr;
117            ctx = nullptr;
118            if (env != nullptr) {
119                if (work != nullptr) {
120                    napi_delete_async_work(env, work);
121                }
122            }
123        }
124    };
125    static void GenerateOutput(AsyncContext &ctx, napi_value output);
126};
127} // namespace Calendar::CalendarApi
128#endif