1/*
2 * Copyright (c) 2022 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#include "event_manager.h"
17
18#include "netmanager_base_log.h"
19#include "securec.h"
20
21namespace OHOS {
22namespace NetManagerStandard {
23namespace {
24static constexpr const int CALLBACK_PARAM_NUM = 1;
25static constexpr const int ASYNC_CALLBACK_PARAM_NUM = 2;
26} // namespace
27
28EventManager::EventManager() : data_(nullptr), isValid_(true) {}
29
30void EventManager::SetInvalid()
31{
32    isValid_ = false;
33}
34
35bool EventManager::IsValid() const
36{
37    return isValid_;
38}
39
40void EventManager::AddListener(napi_env env, const std::string &type, napi_value callback, bool once,
41                               bool asyncCallback)
42{
43    std::lock_guard lock(mutexForListenersAndEmitByUv_);
44    auto it = std::remove_if(listeners_.begin(), listeners_.end(),
45                             [type](const EventListener &listener) -> bool { return listener.MatchType(type); });
46    if (it != listeners_.end()) {
47        listeners_.erase(it, listeners_.end());
48    }
49    listeners_.emplace_back(EventListener(env, type, callback, once, asyncCallback));
50}
51
52void EventManager::DeleteListener(const std::string &type, napi_value callback)
53{
54    std::lock_guard lock(mutexForListenersAndEmitByUv_);
55    auto it =
56        std::remove_if(listeners_.begin(), listeners_.end(), [type, callback](const EventListener &listener) -> bool {
57            return listener.Match(type, callback);
58        });
59    listeners_.erase(it, listeners_.end());
60}
61
62void EventManager::Emit(const std::string &type, const std::pair<napi_value, napi_value> &argv)
63{
64    std::lock_guard lock1(mutexForListenersAndEmitByUv_);
65    std::lock_guard lock2(mutexForEmitAndEmitByUv_);
66    std::for_each(listeners_.begin(), listeners_.end(), [type, argv](const EventListener &listener) {
67        if (listener.IsAsyncCallback()) {
68            /* AsyncCallback(BusinessError error, T data) */
69            napi_value arg[ASYNC_CALLBACK_PARAM_NUM] = {argv.first, argv.second};
70            listener.Emit(type, ASYNC_CALLBACK_PARAM_NUM, arg);
71        } else {
72            /* Callback(T data) */
73            napi_value arg[CALLBACK_PARAM_NUM] = {argv.second};
74            listener.Emit(type, CALLBACK_PARAM_NUM, arg);
75        }
76    });
77
78    auto it = std::remove_if(listeners_.begin(), listeners_.end(),
79                             [type](const EventListener &listener) -> bool { return listener.MatchOnce(type); });
80    listeners_.erase(it, listeners_.end());
81}
82
83void EventManager::SetData(void *data)
84{
85    std::lock_guard<std::mutex> lock(mutex_);
86    data_ = data;
87}
88
89void *EventManager::GetData()
90{
91    std::lock_guard<std::mutex> lock(mutex_);
92    return data_;
93}
94
95void EventManager::EmitByUvWithModuleId(const std::string &type, const NapiUtils::UvHandler &handler, uint64_t moduleId)
96{
97    std::lock_guard lock1(mutexForListenersAndEmitByUv_);
98    std::lock_guard lock2(mutexForEmitAndEmitByUv_);
99    if (!IsValid()) {
100        return;
101    }
102
103    std::for_each(listeners_.begin(), listeners_.end(), [type, handler, moduleId](const EventListener &listener) {
104        listener.EmitByUvByModuleId(type, handler, moduleId);
105    });
106}
107
108void EventManager::EmitByUv(const std::string &type, void *data, void(handler)(uv_work_t *, int status))
109{
110    std::lock_guard lock1(mutexForListenersAndEmitByUv_);
111    std::lock_guard lock2(mutexForEmitAndEmitByUv_);
112    if (!IsValid()) {
113        return;
114    }
115
116    std::for_each(listeners_.begin(), listeners_.end(), [type, data, handler, this](const EventListener &listener) {
117        auto workWrapper = new UvWorkWrapper(data, listener.GetEnv(), type, this);
118        listener.EmitByUv(type, workWrapper, handler);
119    });
120}
121
122bool EventManager::HasEventListener(const std::string &type)
123{
124    std::lock_guard lock2(mutexForListenersAndEmitByUv_);
125    return std::any_of(listeners_.begin(), listeners_.end(),
126                       [&type](const EventListener &listener) -> bool { return listener.MatchType(type); });
127}
128
129void EventManager::DeleteListener(const std::string &type)
130{
131    std::lock_guard lock2(mutexForListenersAndEmitByUv_);
132    auto it = std::remove_if(listeners_.begin(), listeners_.end(),
133                             [type](const EventListener &listener) -> bool { return listener.MatchType(type); });
134    listeners_.erase(it, listeners_.end());
135}
136
137void EventManager::DeleteAllListener()
138{
139    NETMANAGER_BASE_LOGI("DeleteAllListener");
140    std::lock_guard lock(mutexForListenersAndEmitByUv_);
141    listeners_.clear();
142}
143
144napi_ref EventManager::GetRef() const
145{
146    return ref_;
147}
148
149void EventManager::SetRef(napi_ref ref)
150{
151    ref_ = ref;
152}
153
154UvWorkWrapper::UvWorkWrapper(void *theData, napi_env theEnv, std::string eventType, EventManager *eventManager)
155    : data(theData), env(theEnv), type(std::move(eventType)), manager(eventManager)
156{
157}
158} // namespace NetManagerStandard
159} // namespace OHOS
160