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
16#ifndef INPUTMETHOD_IMF_JSPANEL_H
17#define INPUTMETHOD_IMF_JSPANEL_H
18
19#include <mutex>
20#include <uv.h>
21
22#include "async_call.h"
23#include "ffrt_block_queue.h"
24#include "input_method_panel.h"
25#include "js_callback_object.h"
26#include "napi/native_api.h"
27#include "napi/native_common.h"
28#include "napi/native_node_api.h"
29#include "native_engine/native_engine.h"
30#include "native_engine/native_value.h"
31
32namespace OHOS {
33namespace MiscServices {
34
35enum class JsEvent : uint32_t {
36    RESIZE = 0,
37    MOVE_TO,
38    CHANGE_FLAG,
39    ADJUST_PANEL_RECT,
40    EVENT_END,
41};
42
43struct JsEventInfo {
44    std::chrono::system_clock::time_point timestamp{};
45    JsEvent event{ JsEvent::EVENT_END };
46    bool operator==(const JsEventInfo &info) const
47    {
48        return (timestamp == info.timestamp && event == info.event);
49    }
50};
51
52struct JsPanelRect {
53    static napi_value Write(napi_env env, const LayoutParams &layoutParams);
54    static bool Read(napi_env env, napi_value object, LayoutParams &layoutParams);
55};
56
57class JsPanel {
58public:
59    JsPanel() = default;
60    ~JsPanel();
61    static napi_value Init(napi_env env);
62    static napi_value SetUiContent(napi_env env, napi_callback_info info);
63    static napi_value Resize(napi_env env, napi_callback_info info);
64    static napi_value MoveTo(napi_env env, napi_callback_info info);
65    static napi_value Show(napi_env env, napi_callback_info info);
66    static napi_value Hide(napi_env env, napi_callback_info info);
67    static napi_value ChangeFlag(napi_env env, napi_callback_info info);
68    static napi_value SetPrivacyMode(napi_env env, napi_callback_info info);
69    static napi_value Subscribe(napi_env env, napi_callback_info info);
70    static napi_value UnSubscribe(napi_env env, napi_callback_info info);
71    static napi_value AdjustPanelRect(napi_env env, napi_callback_info info);
72    void SetNative(const std::shared_ptr<InputMethodPanel> &panel);
73    std::shared_ptr<InputMethodPanel> GetNative();
74
75private:
76    struct PanelContentContext : public AsyncCall::Context {
77        LayoutParams layoutParams = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } };
78        PanelFlag panelFlag = PanelFlag::FLG_FIXED;
79        std::string path = "";
80        uint32_t width = 0;
81        uint32_t height = 0;
82        int32_t x = 0;
83        int32_t y = 0;
84        std::shared_ptr<InputMethodPanel> inputMethodPanel = nullptr;
85        std::shared_ptr<NativeReference> contentStorage = nullptr;
86        JsEventInfo info;
87        PanelContentContext(napi_env env, napi_callback_info info) : Context(nullptr, nullptr)
88        {
89            napi_value self = nullptr;
90            napi_status status = napi_get_cb_info(env, info, 0, nullptr, &self, nullptr);
91            CHECK_RETURN_VOID((status == napi_ok) && (self != nullptr), "get callback info failed.");
92            void *native = nullptr;
93            status = napi_unwrap(env, self, &native);
94            CHECK_RETURN_VOID((status == napi_ok) && (native != nullptr), "get jsPanel failed.");
95            inputMethodPanel = reinterpret_cast<JsPanel *>(native)->GetNative();
96        };
97        PanelContentContext(InputAction input, OutputAction output) : Context(std::move(input), std::move(output)){};
98        napi_status operator()(napi_env env, size_t argc, napi_value *argv, napi_value self) override
99        {
100            CHECK_RETURN(self != nullptr, "self is nullptr", napi_invalid_arg);
101            return Context::operator()(env, argc, argv, self);
102        }
103        napi_status operator()(napi_env env, napi_value *result) override
104        {
105            if (status_ != napi_ok) {
106                output_ = nullptr;
107                return status_;
108            }
109            return Context::operator()(env, result);
110        }
111    };
112    static napi_value JsNew(napi_env env, napi_callback_info info);
113    static std::shared_ptr<InputMethodPanel> UnwrapPanel(napi_env env, napi_value thisVar);
114    static void PrintEditorQueueInfoIfTimeout(int64_t start, const JsEventInfo &currentInfo);
115    static napi_status CheckParam(napi_env env, size_t argc, napi_value *argv,
116        std::shared_ptr<PanelContentContext> ctxt);
117    static const std::string CLASS_NAME;
118    static constexpr size_t ARGC_MAX = 6;
119    std::shared_ptr<InputMethodPanel> inputMethodPanel_ = nullptr;
120
121    static std::mutex panelConstructorMutex_;
122    static thread_local napi_ref panelConstructorRef_;
123
124    static FFRTBlockQueue<JsEventInfo> jsQueue_;
125};
126} // namespace MiscServices
127} // namespace OHOS
128
129#endif //INPUTMETHOD_IMF_JSPANEL_H
130