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#include <unordered_map>
17#include <unordered_set>
18
19#include "error_util.h"
20#include "i18n_hilog.h"
21#include "i18n_calendar_addon.h"
22#include "js_utils.h"
23#include "variable_convertor.h"
24
25namespace OHOS {
26namespace Global {
27namespace I18n {
28static thread_local napi_ref* g_constructor = nullptr;
29static std::unordered_map<std::string, UCalendarDateFields> g_fieldsMap {
30    { "era", UCAL_ERA },
31    { "year", UCAL_YEAR },
32    { "month", UCAL_MONTH },
33    { "week_of_year", UCAL_WEEK_OF_YEAR },
34    { "week_of_month", UCAL_WEEK_OF_MONTH },
35    { "date", UCAL_DATE },
36    { "day_of_year", UCAL_DAY_OF_YEAR },
37    { "day_of_week", UCAL_DAY_OF_WEEK },
38    { "day_of_week_in_month", UCAL_DAY_OF_WEEK_IN_MONTH },
39    { "ap_pm", UCAL_AM_PM },
40    { "hour", UCAL_HOUR },
41    { "hour_of_day", UCAL_HOUR_OF_DAY },
42    { "minute", UCAL_MINUTE },
43    { "second", UCAL_SECOND },
44    { "millisecond", UCAL_MILLISECOND },
45    { "zone_offset", UCAL_ZONE_OFFSET },
46    { "dst_offset", UCAL_DST_OFFSET },
47    { "year_woy", UCAL_YEAR_WOY },
48    { "dow_local", UCAL_DOW_LOCAL },
49    { "extended_year", UCAL_EXTENDED_YEAR },
50    { "julian_day", UCAL_JULIAN_DAY },
51    { "milliseconds_in_day", UCAL_MILLISECONDS_IN_DAY },
52    { "is_leap_month", UCAL_IS_LEAP_MONTH },
53};
54static std::unordered_set<std::string> g_fieldsInFunctionAdd {
55    "year", "month", "date", "hour", "minute", "second", "millisecond",
56    "week_of_year", "week_of_month", "day_of_year", "day_of_week",
57    "day_of_week_in_month", "hour_of_day", "milliseconds_in_day",
58};
59static std::unordered_map<std::string, CalendarType> g_typeMap {
60    { "buddhist", CalendarType::BUDDHIST },
61    { "chinese", CalendarType::CHINESE },
62    { "coptic", CalendarType::COPTIC },
63    { "ethiopic", CalendarType::ETHIOPIC },
64    { "hebrew", CalendarType::HEBREW },
65    { "gregory", CalendarType::GREGORY },
66    { "indian", CalendarType::INDIAN },
67    { "islamic_civil", CalendarType::ISLAMIC_CIVIL },
68    { "islamic_tbla", CalendarType::ISLAMIC_TBLA },
69    { "islamic_umalqura", CalendarType::ISLAMIC_UMALQURA },
70    { "japanese", CalendarType::JAPANESE },
71    { "persion", CalendarType::PERSIAN },
72};
73
74I18nCalendarAddon::I18nCalendarAddon() {}
75
76I18nCalendarAddon::~I18nCalendarAddon() {}
77
78void I18nCalendarAddon::Destructor(napi_env env, void *nativeObject, void *hint)
79{
80    if (!nativeObject) {
81        return;
82    }
83    delete reinterpret_cast<I18nCalendarAddon *>(nativeObject);
84    nativeObject = nullptr;
85}
86
87napi_value I18nCalendarAddon::InitI18nCalendar(napi_env env, napi_value exports)
88{
89    napi_property_descriptor properties[] = {
90        DECLARE_NAPI_FUNCTION("setTime", SetTime),
91        DECLARE_NAPI_FUNCTION("set", Set),
92        DECLARE_NAPI_FUNCTION("getTimeZone", GetTimeZone),
93        DECLARE_NAPI_FUNCTION("setTimeZone", SetTimeZone),
94        DECLARE_NAPI_FUNCTION("getFirstDayOfWeek", GetFirstDayOfWeek),
95        DECLARE_NAPI_FUNCTION("setFirstDayOfWeek", SetFirstDayOfWeek),
96        DECLARE_NAPI_FUNCTION("getMinimalDaysInFirstWeek", GetMinimalDaysInFirstWeek),
97        DECLARE_NAPI_FUNCTION("setMinimalDaysInFirstWeek", SetMinimalDaysInFirstWeek),
98        DECLARE_NAPI_FUNCTION("get", Get),
99        DECLARE_NAPI_FUNCTION("add", Add),
100        DECLARE_NAPI_FUNCTION("getDisplayName", GetDisplayName),
101        DECLARE_NAPI_FUNCTION("getTimeInMillis", GetTimeInMillis),
102        DECLARE_NAPI_FUNCTION("isWeekend", IsWeekend),
103        DECLARE_NAPI_FUNCTION("compareDays", CompareDays)
104    };
105    napi_value constructor = nullptr;
106    napi_status status = napi_define_class(env, "Calendar", NAPI_AUTO_LENGTH, I18nCalendarConstructor, nullptr,
107        sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
108    if (status != napi_ok) {
109        HILOG_ERROR_I18N("Failed to define class at Init");
110        return nullptr;
111    }
112    exports = I18nCalendarAddon::InitCalendar(env, exports);
113    g_constructor = new (std::nothrow) napi_ref;
114    if (!g_constructor) {
115        HILOG_ERROR_I18N("Failed to create ref at init");
116        return nullptr;
117    }
118    status = napi_create_reference(env, constructor, 1, g_constructor);
119    if (status != napi_ok) {
120        HILOG_ERROR_I18N("Failed to create reference at init");
121        return nullptr;
122    }
123    return exports;
124}
125
126napi_value I18nCalendarAddon::InitCalendar(napi_env env, napi_value exports)
127{
128    napi_property_descriptor properties[] = {};
129    napi_value constructor = nullptr;
130    napi_status status = napi_define_class(env, "I18nCalendar", NAPI_AUTO_LENGTH, JSUtils::DefaultConstructor, nullptr,
131        sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
132    if (status != napi_ok) {
133        HILOG_ERROR_I18N("InitCalendar: Failed to define class Calendar.");
134        return nullptr;
135    }
136    status = napi_set_named_property(env, exports, "Calendar", constructor);
137    if (status != napi_ok) {
138        HILOG_ERROR_I18N("InitCalendar: Set property failed When InitCalendar.");
139        return nullptr;
140    }
141    return exports;
142}
143
144napi_value I18nCalendarAddon::GetCalendar(napi_env env, napi_callback_info info)
145{
146    size_t argc = 2; // retrieve 2 arguments
147    napi_value argv[2] = { 0 };
148    argv[0] = nullptr;
149    argv[1] = nullptr;
150    napi_value thisVar = nullptr;
151    void *data = nullptr;
152    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
153    napi_value constructor = nullptr;
154    napi_status status = napi_get_reference_value(env, *g_constructor, &constructor);
155    if (status != napi_ok) {
156        HILOG_ERROR_I18N("Failed to create reference at GetCalendar");
157        return nullptr;
158    }
159    napi_valuetype valueType = napi_valuetype::napi_undefined;
160    napi_typeof(env, argv[1], &valueType);
161    if (valueType != napi_valuetype::napi_string) {
162        status = napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, argv + 1);
163        if (status != napi_ok) {
164            return nullptr;
165        }
166    }
167    napi_value result = nullptr;
168    status = napi_new_instance(env, constructor, 2, argv, &result); // 2 arguments
169    if (status != napi_ok) {
170        HILOG_ERROR_I18N("Get calendar create instance failed");
171        return nullptr;
172    }
173    return result;
174}
175
176napi_value I18nCalendarAddon::I18nCalendarConstructor(napi_env env, napi_callback_info info)
177{
178    size_t argc = 2;
179    napi_value argv[2] = { 0 };
180    argv[0] = nullptr;
181    argv[1] = nullptr;
182    napi_value thisVar = nullptr;
183    void *data = nullptr;
184    napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
185    if (status != napi_ok) {
186        return nullptr;
187    }
188    napi_valuetype valueType = napi_valuetype::napi_undefined;
189    napi_typeof(env, argv[0], &valueType);
190    if (valueType != napi_valuetype::napi_string) {
191        HILOG_ERROR_I18N("CalendarConstructor: Parameter type does not match");
192        return nullptr;
193    }
194    int32_t code = 0;
195    std::string localeTag = VariableConvertor::GetString(env, argv[0], code);
196    if (code) {
197        return nullptr;
198    }
199    CalendarType type = GetCalendarType(env, argv[1]);
200    std::unique_ptr<I18nCalendarAddon> obj = nullptr;
201    obj = std::make_unique<I18nCalendarAddon>();
202    status =
203        napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), I18nCalendarAddon::Destructor, nullptr, nullptr);
204    if (status != napi_ok) {
205        HILOG_ERROR_I18N("CalendarConstructor: Wrap II18nAddon failed");
206        return nullptr;
207    }
208    if (!obj->InitCalendarContext(env, info, localeTag, type)) {
209        return nullptr;
210    }
211    obj.release();
212    return thisVar;
213}
214
215napi_value I18nCalendarAddon::SetTime(napi_env env, napi_callback_info info)
216{
217    size_t argc = 1;
218    napi_value argv[1] = { 0 };
219    argv[0] = nullptr;
220    napi_value thisVar = nullptr;
221    void *data = nullptr;
222    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
223    if (!argv[0]) {
224        return nullptr;
225    }
226    I18nCalendarAddon *obj = nullptr;
227    napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
228    if (status != napi_ok || !obj || !obj->calendar_) {
229        HILOG_ERROR_I18N("SetTime: Get calendar object failed");
230        return nullptr;
231    }
232    napi_valuetype type = napi_valuetype::napi_undefined;
233    status = napi_typeof(env, argv[0], &type);
234    if (status != napi_ok) {
235        return nullptr;
236    }
237    if (type == napi_valuetype::napi_number) {
238        obj->SetMilliseconds(env, argv[0]);
239        return nullptr;
240    } else {
241        napi_value val = GetDate(env, argv[0]);
242        if (!val) {
243            return nullptr;
244        }
245        obj->SetMilliseconds(env, val);
246        return nullptr;
247    }
248}
249
250napi_value I18nCalendarAddon::Set(napi_env env, napi_callback_info info)
251{
252    size_t argc = 6; // Set may have 6 arguments
253    napi_value argv[6] = { 0 };
254    for (size_t i = 0; i < argc; ++i) {
255        argv[i] = nullptr;
256    }
257    napi_value thisVar = nullptr;
258    void *data = nullptr;
259    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
260    napi_valuetype valueType = napi_valuetype::napi_undefined;
261    napi_status status = napi_ok;
262    int32_t times[3] = { 0 }; // There are at least 3 arguments.
263    for (int i = 0; i < 3; ++i) { // There are at least 3 arguments.
264        napi_typeof(env, argv[i], &valueType);
265        if (valueType != napi_valuetype::napi_number) {
266            HILOG_ERROR_I18N("Set: Parameter type does not match");
267            return nullptr;
268        }
269        status = napi_get_value_int32(env, argv[i], times + i);
270        if (status != napi_ok) {
271            HILOG_ERROR_I18N("Set: Retrieve time value failed");
272            return nullptr;
273        }
274    }
275    I18nCalendarAddon *obj = nullptr;
276    status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
277    if (status != napi_ok || !obj || !obj->calendar_) {
278        HILOG_ERROR_I18N("Set: Get calendar object failed");
279        return nullptr;
280    }
281    obj->calendar_->Set(times[0], times[1], times[2]); // 2 is the index of date
282    obj->SetField(env, argv[3], UCalendarDateFields::UCAL_HOUR_OF_DAY); // 3 is the index of hour
283    obj->SetField(env, argv[4], UCalendarDateFields::UCAL_MINUTE); // 4 is the index of minute
284    obj->SetField(env, argv[5], UCalendarDateFields::UCAL_SECOND); // 5 is the index of second
285    return nullptr;
286}
287
288napi_value I18nCalendarAddon::GetTimeZone(napi_env env, napi_callback_info info)
289{
290    size_t argc = 0;
291    napi_value *argv = nullptr;
292    napi_value thisVar = nullptr;
293    void *data = nullptr;
294    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
295    I18nCalendarAddon *obj = nullptr;
296    napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
297    if (status != napi_ok || !obj || !obj->calendar_) {
298        HILOG_ERROR_I18N("GetTimeZone: Get calendar object failed");
299        return nullptr;
300    }
301    std::string temp = obj->calendar_->GetTimeZone();
302    napi_value result = nullptr;
303    status = napi_create_string_utf8(env, temp.c_str(), NAPI_AUTO_LENGTH, &result);
304    if (status != napi_ok) {
305        HILOG_ERROR_I18N("Create timezone string failed");
306        return nullptr;
307    }
308    return result;
309}
310
311napi_value I18nCalendarAddon::SetTimeZone(napi_env env, napi_callback_info info)
312{
313    size_t argc = 1;
314    napi_value argv[1] = { 0 };
315    argv[0] = nullptr;
316    napi_value thisVar = nullptr;
317    void *data = nullptr;
318    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
319    napi_valuetype valueType = napi_valuetype::napi_undefined;
320    napi_typeof(env, argv[0], &valueType);
321    if (valueType != napi_valuetype::napi_string) {
322        HILOG_ERROR_I18N("SetTimeZone: Parameter type does not match");
323        return nullptr;
324    }
325    size_t len = 0;
326    napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
327    if (status != napi_ok) {
328        HILOG_ERROR_I18N("SetTimeZone: Get timezone length failed");
329        return nullptr;
330    }
331    std::vector<char> buf(len + 1);
332    status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len);
333    if (status != napi_ok) {
334        HILOG_ERROR_I18N("SetTimeZone: Get timezone failed");
335        return nullptr;
336    }
337    std::string timezone(buf.data());
338    I18nCalendarAddon *obj = nullptr;
339    status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
340    if (status != napi_ok || !obj || !obj->calendar_) {
341        HILOG_ERROR_I18N("SetTimeZone: Get calendar object failed");
342        return nullptr;
343    }
344    obj->calendar_->SetTimeZone(timezone);
345    return nullptr;
346}
347
348napi_value I18nCalendarAddon::GetFirstDayOfWeek(napi_env env, napi_callback_info info)
349{
350    size_t argc = 0;
351    napi_value *argv = nullptr;
352    napi_value thisVar = nullptr;
353    void *data = nullptr;
354    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
355    I18nCalendarAddon *obj = nullptr;
356    napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
357    if (status != napi_ok || !obj || !obj->calendar_) {
358        HILOG_ERROR_I18N("GetFirstDayOfWeek: Get calendar object failed");
359        return nullptr;
360    }
361    int32_t temp = obj->calendar_->GetFirstDayOfWeek();
362    napi_value result = nullptr;
363    status = napi_create_int32(env, temp, &result);
364    if (status != napi_ok) {
365        HILOG_ERROR_I18N("GetFirstDayOfWeek: Create int32 failed");
366        return nullptr;
367    }
368    return result;
369}
370
371napi_value I18nCalendarAddon::SetFirstDayOfWeek(napi_env env, napi_callback_info info)
372{
373    size_t argc = 1;
374    napi_value argv[1] = { 0 };
375    argv[0] = nullptr;
376    napi_value thisVar = nullptr;
377    void *data = nullptr;
378    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
379    napi_valuetype valueType = napi_valuetype::napi_undefined;
380    napi_typeof(env, argv[0], &valueType);
381    if (valueType != napi_valuetype::napi_number) {
382        HILOG_ERROR_I18N("SetFirstDayOfWeek: Parameter type does not match");
383        return nullptr;
384    }
385    int32_t value = 0;
386    napi_status status = napi_get_value_int32(env, argv[0], &value);
387    if (status != napi_ok) {
388        HILOG_ERROR_I18N("SetFirstDayOfWeek: Get int32 failed");
389        return nullptr;
390    }
391    I18nCalendarAddon *obj = nullptr;
392    status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
393    if (status != napi_ok || !obj || !obj->calendar_) {
394        HILOG_ERROR_I18N("SetFirstDayOfWeek: Get calendar object failed");
395        return nullptr;
396    }
397    obj->calendar_->SetFirstDayOfWeek(value);
398    return nullptr;
399}
400
401napi_value I18nCalendarAddon::GetMinimalDaysInFirstWeek(napi_env env, napi_callback_info info)
402{
403    size_t argc = 0;
404    napi_value *argv = nullptr;
405    napi_value thisVar = nullptr;
406    void *data = nullptr;
407    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
408    I18nCalendarAddon *obj = nullptr;
409    napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
410    if (status != napi_ok || !obj || !obj->calendar_) {
411        HILOG_ERROR_I18N("GetMinimalDaysInFirstWeek: Get calendar object failed");
412        return nullptr;
413    }
414    int32_t temp = obj->calendar_->GetMinimalDaysInFirstWeek();
415    napi_value result = nullptr;
416    status = napi_create_int32(env, temp, &result);
417    if (status != napi_ok) {
418        HILOG_ERROR_I18N("GetMinimalDaysInFirstWeek: Create int32 failed");
419        return nullptr;
420    }
421    return result;
422}
423
424napi_value I18nCalendarAddon::SetMinimalDaysInFirstWeek(napi_env env, napi_callback_info info)
425{
426    size_t argc = 1;
427    napi_value argv[1] = { 0 };
428    argv[0] = nullptr;
429    napi_value thisVar = nullptr;
430    void *data = nullptr;
431    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
432    napi_valuetype valueType = napi_valuetype::napi_undefined;
433    napi_typeof(env, argv[0], &valueType);
434    if (valueType != napi_valuetype::napi_number) {
435        HILOG_ERROR_I18N("SetMinimalDaysInFirstWeek: Parameter type does not match");
436        return nullptr;
437    }
438    int32_t value = 0;
439    napi_status status = napi_get_value_int32(env, argv[0], &value);
440    if (status != napi_ok) {
441        HILOG_ERROR_I18N("SetMinimalDaysInFirstWeek: Get int32 failed");
442        return nullptr;
443    }
444    I18nCalendarAddon *obj = nullptr;
445    status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
446    if (status != napi_ok || !obj || !obj->calendar_) {
447        HILOG_ERROR_I18N("SetMinimalDaysInFirstWeek: Get calendar object failed");
448        return nullptr;
449    }
450    obj->calendar_->SetMinimalDaysInFirstWeek(value);
451    return nullptr;
452}
453
454napi_value I18nCalendarAddon::Get(napi_env env, napi_callback_info info)
455{
456    size_t argc = 1;
457    napi_value argv[1] = { 0 };
458    argv[0] = nullptr;
459    napi_value thisVar = nullptr;
460    void *data = nullptr;
461    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
462    napi_valuetype valueType = napi_valuetype::napi_undefined;
463    napi_typeof(env, argv[0], &valueType);
464    if (valueType != napi_valuetype::napi_string) {
465        HILOG_ERROR_I18N("Get: Parameter type does not match");
466        return nullptr;
467    }
468    size_t len = 0;
469    napi_status status = napi_get_value_string_utf8(env, argv[0], nullptr, 0, &len);
470    if (status != napi_ok) {
471        HILOG_ERROR_I18N("Get field length failed");
472        return nullptr;
473    }
474    std::vector<char> buf(len + 1);
475    status = napi_get_value_string_utf8(env, argv[0], buf.data(), len + 1, &len);
476    if (status != napi_ok) {
477        HILOG_ERROR_I18N("Get field failed");
478        return nullptr;
479    }
480    std::string field(buf.data());
481    if (g_fieldsMap.find(field) == g_fieldsMap.end()) {
482        HILOG_ERROR_I18N("Invalid field");
483        return nullptr;
484    }
485    I18nCalendarAddon *obj = nullptr;
486    status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
487    if (status != napi_ok || !obj || !obj->calendar_) {
488        HILOG_ERROR_I18N("Get: Get calendar object failed");
489        return nullptr;
490    }
491    int32_t value = obj->calendar_->Get(g_fieldsMap[field]);
492    napi_value result = nullptr;
493    status = napi_create_int32(env, value, &result);
494    if (status != napi_ok) {
495        HILOG_ERROR_I18N("Get: Create int32 failed");
496        return nullptr;
497    }
498    return result;
499}
500
501napi_value I18nCalendarAddon::Add(napi_env env, napi_callback_info info)
502{
503    size_t argc = 2;
504    napi_value argv[2] = { 0 };
505    napi_value thisVar = nullptr;
506    void *data = nullptr;
507    napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
508    if (status != napi_ok) {
509        HILOG_ERROR_I18N("Add: can not obtain add function param.");
510        return nullptr;
511    }
512    napi_valuetype valueType = napi_valuetype::napi_undefined;
513    napi_typeof(env, argv[0], &valueType);
514    if (valueType != napi_valuetype::napi_string) {
515        HILOG_ERROR_I18N("Parameter type does not match argv[0]");
516        ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "field", "string", true);
517        return nullptr;
518    }
519    int32_t code = 0;
520    std::string field = GetAddField(env, argv[0], code);
521    if (code) {
522        return nullptr;
523    }
524    napi_typeof(env, argv[1], &valueType);
525    if (valueType != napi_valuetype::napi_number) {
526        HILOG_ERROR_I18N("Parameter type does not match argv[1]");
527        ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "amount", "number", true);
528        return nullptr;
529    }
530    int32_t amount;
531    status = napi_get_value_int32(env, argv[1], &amount);
532    if (status != napi_ok) {
533        HILOG_ERROR_I18N("Add: Can not obtain add function param.");
534        return nullptr;
535    }
536    I18nCalendarAddon *obj = nullptr;
537    status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
538    if (status != napi_ok || !obj || !obj->calendar_) {
539        HILOG_ERROR_I18N("Add: Get calendar object failed");
540        return nullptr;
541    }
542    obj->calendar_->Add(g_fieldsMap[field], amount);
543    return nullptr;
544}
545
546napi_value I18nCalendarAddon::GetDisplayName(napi_env env, napi_callback_info info)
547{
548    size_t argc = 1;
549    napi_value argv[1] = { 0 };
550    argv[0] = nullptr;
551    napi_value thisVar = nullptr;
552    void *data = nullptr;
553    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
554    napi_valuetype valueType = napi_valuetype::napi_undefined;
555    napi_typeof(env, argv[0], &valueType);
556    if (valueType != napi_valuetype::napi_string) {
557        HILOG_ERROR_I18N("GetDisplayName: Parameter type does not match");
558        return nullptr;
559    }
560    int32_t code = 0;
561    std::string localeTag = VariableConvertor::GetString(env, argv[0], code);
562    if (code) {
563        return nullptr;
564    }
565    I18nCalendarAddon *obj = nullptr;
566    napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
567    if (status != napi_ok || !obj || !obj->calendar_) {
568        HILOG_ERROR_I18N("GetDisplayName: Get calendar object failed");
569        return nullptr;
570    }
571    if (!obj->calendar_) {
572        return nullptr;
573    }
574    std::string name = obj->calendar_->GetDisplayName(localeTag);
575    napi_value result = nullptr;
576    status = napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &result);
577    if (status != napi_ok) {
578        HILOG_ERROR_I18N("Create calendar name string failed");
579        return nullptr;
580    }
581    return result;
582}
583
584napi_value I18nCalendarAddon::GetTimeInMillis(napi_env env, napi_callback_info info)
585{
586    bool flag = true;
587    size_t argc = 0;
588    napi_value *argv = nullptr;
589    napi_value thisVar = nullptr;
590    void *data = nullptr;
591    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
592    I18nCalendarAddon *obj = nullptr;
593    napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
594    if (status != napi_ok || !obj || !obj->calendar_) {
595        HILOG_ERROR_I18N("GetTimeInMillis: Get calendar object failed");
596        flag = false;
597    }
598    UDate temp = 0;
599    if (flag) {
600        temp = obj->calendar_->GetTimeInMillis();
601    }
602    napi_value result = nullptr;
603    status = napi_create_double(env, temp, &result);
604    if (status != napi_ok) {
605        HILOG_ERROR_I18N("Create UDate failed");
606        napi_create_double(env, 0, &result);
607    }
608    return result;
609}
610
611napi_value I18nCalendarAddon::IsWeekend(napi_env env, napi_callback_info info)
612{
613    size_t argc = 1;
614    napi_value argv[1] = { 0 };
615    argv[0] = nullptr;
616    napi_value thisVar = nullptr;
617    void *data = nullptr;
618    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
619    I18nCalendarAddon *obj = nullptr;
620    bool isWeekEnd = false;
621    napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
622    do {
623        if (status != napi_ok || !obj || !obj->calendar_) {
624            HILOG_ERROR_I18N("IsWeekend: Get calendar object failed");
625            break;
626        }
627        if (!VariableConvertor::CheckNapiValueType(env, argv[0])) {
628            isWeekEnd = obj->calendar_->IsWeekend();
629        } else {
630            napi_value funcGetDateInfo = nullptr;
631            status = napi_get_named_property(env, argv[0], "valueOf", &funcGetDateInfo);
632            if (status != napi_ok) {
633                HILOG_ERROR_I18N("Get method now failed");
634                break;
635            }
636            napi_value value = nullptr;
637            status = napi_call_function(env, argv[0], funcGetDateInfo, 0, nullptr, &value);
638            if (status != napi_ok) {
639                HILOG_ERROR_I18N("IsWeekend: Get milliseconds failed");
640                break;
641            }
642            double milliseconds = 0;
643            status = napi_get_value_double(env, value, &milliseconds);
644            if (status != napi_ok) {
645                HILOG_ERROR_I18N("IsWeekend: Retrieve milliseconds failed");
646                break;
647            }
648            UErrorCode error = U_ZERO_ERROR;
649            isWeekEnd = obj->calendar_->IsWeekend(milliseconds, error);
650        }
651    } while (false);
652    napi_value result = nullptr;
653    status = napi_get_boolean(env, isWeekEnd, &result);
654    if (status != napi_ok) {
655        HILOG_ERROR_I18N("Create boolean failed");
656        return nullptr;
657    }
658    return result;
659}
660
661napi_value I18nCalendarAddon::CompareDays(napi_env env, napi_callback_info info)
662{
663    size_t argc = 1;
664    napi_value argv[1] = { 0 };
665    napi_value thisVar = nullptr;
666    void *data = nullptr;
667    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
668    napi_value result = nullptr;
669    UDate milliseconds = 0;
670    napi_status status = napi_get_date_value(env, argv[0], &milliseconds);
671    if (status != napi_ok) {
672        HILOG_ERROR_I18N("compareDays: function param is not Date");
673        return nullptr;
674    }
675
676    I18nCalendarAddon *obj = nullptr;
677    status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
678    if (status != napi_ok || !obj || !obj->calendar_) {
679        HILOG_ERROR_I18N("CompareDays: Get calendar object failed");
680        status = napi_create_int32(env, 0, &result); // if error return 0
681        return result;
682    }
683
684    int32_t diff_date = obj->calendar_->CompareDays(milliseconds);
685    status = napi_create_int32(env, diff_date, &result);
686    return result;
687}
688
689bool I18nCalendarAddon::InitCalendarContext(napi_env env, napi_callback_info info, const std::string &localeTag,
690    CalendarType type)
691{
692    calendar_ = std::make_unique<I18nCalendar>(localeTag, type);
693    return calendar_ != nullptr;
694}
695
696CalendarType I18nCalendarAddon::GetCalendarType(napi_env env, napi_value value)
697{
698    CalendarType type = CalendarType::UNDEFINED;
699    if (value != nullptr) {
700        napi_valuetype valueType = napi_valuetype::napi_undefined;
701        napi_typeof(env, value, &valueType);
702        if (valueType != napi_valuetype::napi_string) {
703            HILOG_ERROR_I18N("GetCalendarType: Parameter type does not match");
704            return type;
705        }
706        int32_t code = 0;
707        std::string calendarType = VariableConvertor::GetString(env, value, code);
708        if (code) {
709            return type;
710        }
711        if (g_typeMap.find(calendarType) != g_typeMap.end()) {
712            type = g_typeMap[calendarType];
713        }
714    }
715    return type;
716}
717
718void I18nCalendarAddon::SetField(napi_env env, napi_value value, UCalendarDateFields field)
719{
720    if (!VariableConvertor::CheckNapiValueType(env, value)) {
721        return;
722    }
723    int32_t val = 0;
724    napi_valuetype valueType = napi_valuetype::napi_undefined;
725    napi_typeof(env, value, &valueType);
726    if (valueType != napi_valuetype::napi_number) {
727        HILOG_ERROR_I18N("SetField: Parameter type does not match");
728        return;
729    }
730    napi_status status = napi_get_value_int32(env, value, &val);
731    if (status != napi_ok) {
732        HILOG_ERROR_I18N("SetField: Retrieve field failed");
733        return;
734    }
735    if (calendar_ != nullptr) {
736        calendar_->Set(field, val);
737    }
738}
739
740std::string I18nCalendarAddon::GetAddField(napi_env &env, napi_value &value, int32_t &code)
741{
742    std::string field = VariableConvertor::GetString(env, value, code);
743    if (code != 0) {
744        HILOG_ERROR_I18N("GetAddField: can't get string from js array param.");
745        return field;
746    }
747    if (g_fieldsInFunctionAdd.find(field) == g_fieldsInFunctionAdd.end()) {
748        code = 1;
749        HILOG_ERROR_I18N("Parameter rangs do not match");
750        ErrorUtil::NapiThrow(env, I18N_NOT_VALID, "field", "a valid field", true);
751        return field;
752    }
753    return field;
754}
755
756napi_value I18nCalendarAddon::GetDate(napi_env env, napi_value value)
757{
758    if (!value) {
759        return nullptr;
760    }
761    napi_value funcGetDateInfo = nullptr;
762    napi_status status = napi_get_named_property(env, value, "valueOf", &funcGetDateInfo);
763    if (status != napi_ok) {
764        HILOG_ERROR_I18N("Get method valueOf failed");
765        return nullptr;
766    }
767    napi_value ret_value = nullptr;
768    status = napi_call_function(env, value, funcGetDateInfo, 0, nullptr, &ret_value);
769    if (status != napi_ok) {
770        HILOG_ERROR_I18N("GetDate: Get milliseconds failed");
771        return nullptr;
772    }
773    return ret_value;
774}
775
776void I18nCalendarAddon::SetMilliseconds(napi_env env, napi_value value)
777{
778    if (!value) {
779        return;
780    }
781    double milliseconds = 0;
782    napi_valuetype valueType = napi_valuetype::napi_undefined;
783    napi_typeof(env, value, &valueType);
784    if (valueType != napi_valuetype::napi_number) {
785        HILOG_ERROR_I18N("SetMilliseconds: Parameter type does not match");
786        return;
787    }
788    napi_status status = napi_get_value_double(env, value, &milliseconds);
789    if (status != napi_ok) {
790        HILOG_ERROR_I18N("SetMilliseconds: Retrieve milliseconds failed");
791        return;
792    }
793    if (calendar_ != nullptr) {
794        calendar_->SetTime(milliseconds);
795    }
796}
797
798} // namespace I18n
799} // namespace Global
800} // namespace OHOS