19596a2c1Sopenharmony_ci/*
29596a2c1Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
39596a2c1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
49596a2c1Sopenharmony_ci * you may not use this file except in compliance with the License.
59596a2c1Sopenharmony_ci * You may obtain a copy of the License at
69596a2c1Sopenharmony_ci *
79596a2c1Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
89596a2c1Sopenharmony_ci *
99596a2c1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
109596a2c1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
119596a2c1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
129596a2c1Sopenharmony_ci * See the License for the specific language governing permissions and
139596a2c1Sopenharmony_ci * limitations under the License.
149596a2c1Sopenharmony_ci */
159596a2c1Sopenharmony_ci#include "character.h"
169596a2c1Sopenharmony_ci#include "error_util.h"
179596a2c1Sopenharmony_ci#include "i18n_hilog.h"
189596a2c1Sopenharmony_ci#include "i18n_timezone_addon.h"
199596a2c1Sopenharmony_ci#include "js_utils.h"
209596a2c1Sopenharmony_ci#include "variable_convertor.h"
219596a2c1Sopenharmony_ci
229596a2c1Sopenharmony_cinamespace OHOS {
239596a2c1Sopenharmony_cinamespace Global {
249596a2c1Sopenharmony_cinamespace I18n {
259596a2c1Sopenharmony_cistatic thread_local napi_ref* g_timezoneConstructor = nullptr;
269596a2c1Sopenharmony_ci
279596a2c1Sopenharmony_ciI18nTimeZoneAddon::I18nTimeZoneAddon() {}
289596a2c1Sopenharmony_ci
299596a2c1Sopenharmony_ciI18nTimeZoneAddon::~I18nTimeZoneAddon() {}
309596a2c1Sopenharmony_ci
319596a2c1Sopenharmony_civoid I18nTimeZoneAddon::Destructor(napi_env env, void *nativeObject, void *hint)
329596a2c1Sopenharmony_ci{
339596a2c1Sopenharmony_ci    if (!nativeObject) {
349596a2c1Sopenharmony_ci        return;
359596a2c1Sopenharmony_ci    }
369596a2c1Sopenharmony_ci    delete reinterpret_cast<I18nTimeZoneAddon *>(nativeObject);
379596a2c1Sopenharmony_ci    nativeObject = nullptr;
389596a2c1Sopenharmony_ci}
399596a2c1Sopenharmony_ci
409596a2c1Sopenharmony_cinapi_value I18nTimeZoneAddon::GetI18nTimeZone(napi_env env, napi_callback_info info)
419596a2c1Sopenharmony_ci{
429596a2c1Sopenharmony_ci    size_t argc = 1;
439596a2c1Sopenharmony_ci    napi_value argv[1] = { nullptr };
449596a2c1Sopenharmony_ci    napi_value thisVar = nullptr;
459596a2c1Sopenharmony_ci    void *data = nullptr;
469596a2c1Sopenharmony_ci    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
479596a2c1Sopenharmony_ci    if (!VariableConvertor::CheckNapiValueType(env, argv[0])) {
489596a2c1Sopenharmony_ci        napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &argv[0]);
499596a2c1Sopenharmony_ci    }
509596a2c1Sopenharmony_ci    return StaticGetTimeZone(env, argv, true);
519596a2c1Sopenharmony_ci}
529596a2c1Sopenharmony_ci
539596a2c1Sopenharmony_cinapi_value I18nTimeZoneAddon::InitI18nTimeZone(napi_env env, napi_value exports)
549596a2c1Sopenharmony_ci{
559596a2c1Sopenharmony_ci    napi_property_descriptor properties[] = {
569596a2c1Sopenharmony_ci        DECLARE_NAPI_FUNCTION("getID", GetID),
579596a2c1Sopenharmony_ci        DECLARE_NAPI_FUNCTION("getDisplayName", GetTimeZoneDisplayName),
589596a2c1Sopenharmony_ci        DECLARE_NAPI_FUNCTION("getRawOffset", GetRawOffset),
599596a2c1Sopenharmony_ci        DECLARE_NAPI_FUNCTION("getOffset", GetOffset),
609596a2c1Sopenharmony_ci    };
619596a2c1Sopenharmony_ci    napi_value constructor = nullptr;
629596a2c1Sopenharmony_ci    napi_status status = napi_define_class(env, "TimeZone", NAPI_AUTO_LENGTH, I18nTimeZoneConstructor, nullptr,
639596a2c1Sopenharmony_ci        sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
649596a2c1Sopenharmony_ci    if (status != napi_ok) {
659596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("InitI18nTimeZone: Failed to define class TimeZone at Init");
669596a2c1Sopenharmony_ci        return nullptr;
679596a2c1Sopenharmony_ci    }
689596a2c1Sopenharmony_ci    exports = I18nTimeZoneAddon::InitTimeZone(env, exports);
699596a2c1Sopenharmony_ci    g_timezoneConstructor = new (std::nothrow) napi_ref;
709596a2c1Sopenharmony_ci    if (!g_timezoneConstructor) {
719596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("InitI18nTimeZone: Failed to create TimeZone ref at init");
729596a2c1Sopenharmony_ci        return nullptr;
739596a2c1Sopenharmony_ci    }
749596a2c1Sopenharmony_ci    status = napi_create_reference(env, constructor, 1, g_timezoneConstructor);
759596a2c1Sopenharmony_ci    if (status != napi_ok) {
769596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("InitI18nTimeZone: Failed to create reference g_timezoneConstructor at init");
779596a2c1Sopenharmony_ci        return nullptr;
789596a2c1Sopenharmony_ci    }
799596a2c1Sopenharmony_ci    return exports;
809596a2c1Sopenharmony_ci}
819596a2c1Sopenharmony_ci
829596a2c1Sopenharmony_cinapi_value I18nTimeZoneAddon::InitTimeZone(napi_env env, napi_value exports)
839596a2c1Sopenharmony_ci{
849596a2c1Sopenharmony_ci    napi_property_descriptor properties[] = {
859596a2c1Sopenharmony_ci        DECLARE_NAPI_STATIC_FUNCTION("getAvailableIDs", GetAvailableTimezoneIDs),
869596a2c1Sopenharmony_ci        DECLARE_NAPI_STATIC_FUNCTION("getAvailableZoneCityIDs", GetAvailableZoneCityIDs),
879596a2c1Sopenharmony_ci        DECLARE_NAPI_STATIC_FUNCTION("getCityDisplayName", GetCityDisplayName),
889596a2c1Sopenharmony_ci        DECLARE_NAPI_STATIC_FUNCTION("getTimezoneFromCity", GetTimezoneFromCity),
899596a2c1Sopenharmony_ci        DECLARE_NAPI_STATIC_FUNCTION("getTimezonesByLocation", GetTimezonesByLocation)
909596a2c1Sopenharmony_ci    };
919596a2c1Sopenharmony_ci    napi_value constructor = nullptr;
929596a2c1Sopenharmony_ci    napi_status status = napi_define_class(env, "I18nTimeZone", NAPI_AUTO_LENGTH, JSUtils::DefaultConstructor, nullptr,
939596a2c1Sopenharmony_ci        sizeof(properties) / sizeof(napi_property_descriptor), properties, &constructor);
949596a2c1Sopenharmony_ci    if (status != napi_ok) {
959596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("InitTimeZone: Failed to define class TimeZone.");
969596a2c1Sopenharmony_ci        return nullptr;
979596a2c1Sopenharmony_ci    }
989596a2c1Sopenharmony_ci    status = napi_set_named_property(env, exports, "TimeZone", constructor);
999596a2c1Sopenharmony_ci    if (status != napi_ok) {
1009596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("InitTimeZone: Set property failed When InitTimeZone.");
1019596a2c1Sopenharmony_ci        return nullptr;
1029596a2c1Sopenharmony_ci    }
1039596a2c1Sopenharmony_ci    return exports;
1049596a2c1Sopenharmony_ci}
1059596a2c1Sopenharmony_ci
1069596a2c1Sopenharmony_cinapi_value I18nTimeZoneAddon::I18nTimeZoneConstructor(napi_env env, napi_callback_info info)
1079596a2c1Sopenharmony_ci{
1089596a2c1Sopenharmony_ci    size_t argc = 2;
1099596a2c1Sopenharmony_ci    napi_value argv[2] = { nullptr };
1109596a2c1Sopenharmony_ci    napi_value thisVar = nullptr;
1119596a2c1Sopenharmony_ci    void *data = nullptr;
1129596a2c1Sopenharmony_ci    napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
1139596a2c1Sopenharmony_ci    if (status != napi_ok) {
1149596a2c1Sopenharmony_ci        return nullptr;
1159596a2c1Sopenharmony_ci    }
1169596a2c1Sopenharmony_ci    std::string zoneID = "";
1179596a2c1Sopenharmony_ci    napi_valuetype valueType = napi_valuetype::napi_undefined;
1189596a2c1Sopenharmony_ci    if (argc > 0) {
1199596a2c1Sopenharmony_ci        napi_typeof(env, argv[0], &valueType);
1209596a2c1Sopenharmony_ci        if (valueType != napi_valuetype::napi_string) {
1219596a2c1Sopenharmony_ci            return nullptr;
1229596a2c1Sopenharmony_ci        }
1239596a2c1Sopenharmony_ci        int32_t code = 0;
1249596a2c1Sopenharmony_ci        zoneID = VariableConvertor::GetString(env, argv[0], code);
1259596a2c1Sopenharmony_ci        if (code != 0) {
1269596a2c1Sopenharmony_ci            return nullptr;
1279596a2c1Sopenharmony_ci        }
1289596a2c1Sopenharmony_ci    }
1299596a2c1Sopenharmony_ci    if (argc < FUNC_ARGS_COUNT) {
1309596a2c1Sopenharmony_ci        return nullptr;
1319596a2c1Sopenharmony_ci    }
1329596a2c1Sopenharmony_ci    napi_typeof(env, argv[1], &valueType);
1339596a2c1Sopenharmony_ci    if (valueType != napi_valuetype::napi_boolean) {
1349596a2c1Sopenharmony_ci        return nullptr;
1359596a2c1Sopenharmony_ci    }
1369596a2c1Sopenharmony_ci    bool isZoneID = false;
1379596a2c1Sopenharmony_ci    status = napi_get_value_bool(env, argv[1], &isZoneID);
1389596a2c1Sopenharmony_ci    if (status != napi_ok) {
1399596a2c1Sopenharmony_ci        return nullptr;
1409596a2c1Sopenharmony_ci    }
1419596a2c1Sopenharmony_ci    std::unique_ptr<I18nTimeZoneAddon> obj = std::make_unique<I18nTimeZoneAddon>();
1429596a2c1Sopenharmony_ci    status =
1439596a2c1Sopenharmony_ci        napi_wrap(env, thisVar, reinterpret_cast<void *>(obj.get()), I18nTimeZoneAddon::Destructor, nullptr, nullptr);
1449596a2c1Sopenharmony_ci    if (status != napi_ok) {
1459596a2c1Sopenharmony_ci        return nullptr;
1469596a2c1Sopenharmony_ci    }
1479596a2c1Sopenharmony_ci    obj->timezone_ = I18nTimeZone::CreateInstance(zoneID, isZoneID);
1489596a2c1Sopenharmony_ci    if (!obj->timezone_) {
1499596a2c1Sopenharmony_ci        return nullptr;
1509596a2c1Sopenharmony_ci    }
1519596a2c1Sopenharmony_ci    obj.release();
1529596a2c1Sopenharmony_ci    return thisVar;
1539596a2c1Sopenharmony_ci}
1549596a2c1Sopenharmony_ci
1559596a2c1Sopenharmony_cinapi_value I18nTimeZoneAddon::GetAvailableTimezoneIDs(napi_env env, napi_callback_info info)
1569596a2c1Sopenharmony_ci{
1579596a2c1Sopenharmony_ci    I18nErrorCode errorCode = I18nErrorCode::SUCCESS;
1589596a2c1Sopenharmony_ci    std::set<std::string> timezoneIDs = I18nTimeZone::GetAvailableIDs(errorCode);
1599596a2c1Sopenharmony_ci    if (errorCode != I18nErrorCode::SUCCESS) {
1609596a2c1Sopenharmony_ci        return nullptr;
1619596a2c1Sopenharmony_ci    }
1629596a2c1Sopenharmony_ci    napi_value result = nullptr;
1639596a2c1Sopenharmony_ci    napi_status status = napi_create_array_with_length(env, timezoneIDs.size(), &result);
1649596a2c1Sopenharmony_ci    if (status != napi_ok) {
1659596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("GetAvailableTimezoneIDs: Failed to create array");
1669596a2c1Sopenharmony_ci        return nullptr;
1679596a2c1Sopenharmony_ci    }
1689596a2c1Sopenharmony_ci    size_t index = 0;
1699596a2c1Sopenharmony_ci    for (std::set<std::string>::iterator it = timezoneIDs.begin(); it != timezoneIDs.end(); ++it) {
1709596a2c1Sopenharmony_ci        napi_value value = nullptr;
1719596a2c1Sopenharmony_ci        status = napi_create_string_utf8(env, (*it).c_str(), NAPI_AUTO_LENGTH, &value);
1729596a2c1Sopenharmony_ci        if (status != napi_ok) {
1739596a2c1Sopenharmony_ci            HILOG_ERROR_I18N("Failed to create string item");
1749596a2c1Sopenharmony_ci            return nullptr;
1759596a2c1Sopenharmony_ci        }
1769596a2c1Sopenharmony_ci        status = napi_set_element(env, result, index, value);
1779596a2c1Sopenharmony_ci        if (status != napi_ok) {
1789596a2c1Sopenharmony_ci            HILOG_ERROR_I18N("Failed to set array item");
1799596a2c1Sopenharmony_ci            return nullptr;
1809596a2c1Sopenharmony_ci        }
1819596a2c1Sopenharmony_ci        ++index;
1829596a2c1Sopenharmony_ci    }
1839596a2c1Sopenharmony_ci    return result;
1849596a2c1Sopenharmony_ci}
1859596a2c1Sopenharmony_ci
1869596a2c1Sopenharmony_cinapi_value I18nTimeZoneAddon::GetAvailableZoneCityIDs(napi_env env, napi_callback_info info)
1879596a2c1Sopenharmony_ci{
1889596a2c1Sopenharmony_ci    std::set<std::string> cityIDs = I18nTimeZone::GetAvailableZoneCityIDs();
1899596a2c1Sopenharmony_ci    napi_value result = nullptr;
1909596a2c1Sopenharmony_ci    napi_status status = napi_create_array_with_length(env, cityIDs.size(), &result);
1919596a2c1Sopenharmony_ci    if (status != napi_ok) {
1929596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("GetAvailableZoneCityIDs: Failed to create array");
1939596a2c1Sopenharmony_ci        return nullptr;
1949596a2c1Sopenharmony_ci    }
1959596a2c1Sopenharmony_ci    size_t index = 0;
1969596a2c1Sopenharmony_ci    for (auto it = cityIDs.begin(); it != cityIDs.end(); ++it) {
1979596a2c1Sopenharmony_ci        napi_value value = nullptr;
1989596a2c1Sopenharmony_ci        status = napi_create_string_utf8(env, (*it).c_str(), NAPI_AUTO_LENGTH, &value);
1999596a2c1Sopenharmony_ci        if (status != napi_ok) {
2009596a2c1Sopenharmony_ci            HILOG_ERROR_I18N("GetAvailableZoneCityIDs: Failed to create string item");
2019596a2c1Sopenharmony_ci            return nullptr;
2029596a2c1Sopenharmony_ci        }
2039596a2c1Sopenharmony_ci        status = napi_set_element(env, result, index, value);
2049596a2c1Sopenharmony_ci        if (status != napi_ok) {
2059596a2c1Sopenharmony_ci            HILOG_ERROR_I18N("GetAvailableZoneCityIDs: Failed to set array item");
2069596a2c1Sopenharmony_ci            return nullptr;
2079596a2c1Sopenharmony_ci        }
2089596a2c1Sopenharmony_ci        ++index;
2099596a2c1Sopenharmony_ci    }
2109596a2c1Sopenharmony_ci    return result;
2119596a2c1Sopenharmony_ci}
2129596a2c1Sopenharmony_ci
2139596a2c1Sopenharmony_cinapi_value I18nTimeZoneAddon::GetCityDisplayName(napi_env env, napi_callback_info info)
2149596a2c1Sopenharmony_ci{
2159596a2c1Sopenharmony_ci    size_t argc = 2;
2169596a2c1Sopenharmony_ci    napi_value argv[2] = { 0 };
2179596a2c1Sopenharmony_ci    napi_value thisVar = nullptr;
2189596a2c1Sopenharmony_ci    void *data = nullptr;
2199596a2c1Sopenharmony_ci    napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2209596a2c1Sopenharmony_ci    if (status != napi_ok) {
2219596a2c1Sopenharmony_ci        return nullptr;
2229596a2c1Sopenharmony_ci    }
2239596a2c1Sopenharmony_ci    if (argc < FUNC_ARGS_COUNT) {
2249596a2c1Sopenharmony_ci        return nullptr;
2259596a2c1Sopenharmony_ci    }
2269596a2c1Sopenharmony_ci    napi_valuetype valueType = napi_valuetype::napi_undefined;
2279596a2c1Sopenharmony_ci    napi_typeof(env, argv[0], &valueType);
2289596a2c1Sopenharmony_ci    if (valueType != napi_valuetype::napi_string) {
2299596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("GetCityDisplayName: Invalid parameter type");
2309596a2c1Sopenharmony_ci        return nullptr;
2319596a2c1Sopenharmony_ci    }
2329596a2c1Sopenharmony_ci    int32_t code = 0;
2339596a2c1Sopenharmony_ci    std::string cityID = VariableConvertor::GetString(env, argv[0], code);
2349596a2c1Sopenharmony_ci    if (code != 0) {
2359596a2c1Sopenharmony_ci        return nullptr;
2369596a2c1Sopenharmony_ci    }
2379596a2c1Sopenharmony_ci    std::string locale = VariableConvertor::GetString(env, argv[1], code);
2389596a2c1Sopenharmony_ci    if (code != 0) {
2399596a2c1Sopenharmony_ci        return nullptr;
2409596a2c1Sopenharmony_ci    }
2419596a2c1Sopenharmony_ci    std::string name = I18nTimeZone::GetCityDisplayName(cityID, locale);
2429596a2c1Sopenharmony_ci    napi_value result = nullptr;
2439596a2c1Sopenharmony_ci    status = napi_create_string_utf8(env, name.c_str(), NAPI_AUTO_LENGTH, &result);
2449596a2c1Sopenharmony_ci    if (status != napi_ok) {
2459596a2c1Sopenharmony_ci        return nullptr;
2469596a2c1Sopenharmony_ci    }
2479596a2c1Sopenharmony_ci    return result;
2489596a2c1Sopenharmony_ci}
2499596a2c1Sopenharmony_ci
2509596a2c1Sopenharmony_cinapi_value I18nTimeZoneAddon::GetTimezoneFromCity(napi_env env, napi_callback_info info)
2519596a2c1Sopenharmony_ci{
2529596a2c1Sopenharmony_ci    size_t argc = 1;
2539596a2c1Sopenharmony_ci    napi_value argv[1] = { nullptr };
2549596a2c1Sopenharmony_ci    napi_value thisVar = nullptr;
2559596a2c1Sopenharmony_ci    void *data = nullptr;
2569596a2c1Sopenharmony_ci    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2579596a2c1Sopenharmony_ci    return StaticGetTimeZone(env, argv, false);
2589596a2c1Sopenharmony_ci}
2599596a2c1Sopenharmony_ci
2609596a2c1Sopenharmony_cinapi_value I18nTimeZoneAddon::GetTimezonesByLocation(napi_env env, napi_callback_info info)
2619596a2c1Sopenharmony_ci{
2629596a2c1Sopenharmony_ci    size_t argc = 2;
2639596a2c1Sopenharmony_ci    napi_value argv[2] = {0, 0};
2649596a2c1Sopenharmony_ci    napi_value thisVar = nullptr;
2659596a2c1Sopenharmony_ci    void *data = nullptr;
2669596a2c1Sopenharmony_ci    napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
2679596a2c1Sopenharmony_ci    if (status != napi_ok) {
2689596a2c1Sopenharmony_ci        return nullptr;
2699596a2c1Sopenharmony_ci    }
2709596a2c1Sopenharmony_ci    if (argc < FUNC_ARGS_COUNT) {
2719596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("GetTimezonesByLocation: Missing parameter");
2729596a2c1Sopenharmony_ci        ErrorUtil::NapiThrow(env, I18N_NOT_FOUND, "longitude or latitude", "", true);
2739596a2c1Sopenharmony_ci        return nullptr;
2749596a2c1Sopenharmony_ci    }
2759596a2c1Sopenharmony_ci    double x;
2769596a2c1Sopenharmony_ci    double y;
2779596a2c1Sopenharmony_ci    VariableConvertor::VerifyType(env, "longitude", "number", argv[0]);
2789596a2c1Sopenharmony_ci    VariableConvertor::VerifyType(env, "latitude", "number", argv[1]);
2799596a2c1Sopenharmony_ci    if (!CheckLongitudeTypeAndScope(env, argv[0], x) ||
2809596a2c1Sopenharmony_ci        !CheckLatitudeTypeAndScope(env, argv[1], y)) {
2819596a2c1Sopenharmony_ci        ErrorUtil::NapiThrow(env, I18N_NOT_VALID, "longitude or latitude", "a valid value", true);
2829596a2c1Sopenharmony_ci        return nullptr;
2839596a2c1Sopenharmony_ci    }
2849596a2c1Sopenharmony_ci    napi_value timezoneList = nullptr;
2859596a2c1Sopenharmony_ci    napi_create_array(env, &timezoneList);
2869596a2c1Sopenharmony_ci    std::vector<std::string> tempList = I18nTimeZone::GetTimezoneIdByLocation(x, y);
2879596a2c1Sopenharmony_ci    for (size_t i = 0; i < tempList.size(); i++) {
2889596a2c1Sopenharmony_ci        napi_value timezoneId = nullptr;
2899596a2c1Sopenharmony_ci        status = napi_create_string_utf8(env, tempList[i].c_str(), NAPI_AUTO_LENGTH, &timezoneId);
2909596a2c1Sopenharmony_ci        if (status != napi_ok) {
2919596a2c1Sopenharmony_ci            return nullptr;
2929596a2c1Sopenharmony_ci        }
2939596a2c1Sopenharmony_ci        napi_value argTimeZoneId[1] = { timezoneId };
2949596a2c1Sopenharmony_ci        napi_value timezone = StaticGetTimeZone(env, argTimeZoneId, true);
2959596a2c1Sopenharmony_ci        status = napi_set_element(env, timezoneList, i, timezone);
2969596a2c1Sopenharmony_ci        if (status != napi_ok) {
2979596a2c1Sopenharmony_ci            return nullptr;
2989596a2c1Sopenharmony_ci        }
2999596a2c1Sopenharmony_ci    }
3009596a2c1Sopenharmony_ci
3019596a2c1Sopenharmony_ci    return timezoneList;
3029596a2c1Sopenharmony_ci}
3039596a2c1Sopenharmony_ci
3049596a2c1Sopenharmony_cibool I18nTimeZoneAddon::CheckLongitudeTypeAndScope(napi_env env, napi_value argv, double &x)
3059596a2c1Sopenharmony_ci{
3069596a2c1Sopenharmony_ci    napi_status status = napi_get_value_double(env, argv, &x);
3079596a2c1Sopenharmony_ci    if (status != napi_ok) {
3089596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("GetTimezonesByLocation: Parse first argument x failed");
3099596a2c1Sopenharmony_ci        return false;
3109596a2c1Sopenharmony_ci    }
3119596a2c1Sopenharmony_ci    // -180 and 179.9 is the scope of longitude
3129596a2c1Sopenharmony_ci    if (x < -180 || x > 179.9) {
3139596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("GetTimezonesByLocation: Args x exceed it's scope.");
3149596a2c1Sopenharmony_ci        return false;
3159596a2c1Sopenharmony_ci    }
3169596a2c1Sopenharmony_ci    return true;
3179596a2c1Sopenharmony_ci}
3189596a2c1Sopenharmony_ci
3199596a2c1Sopenharmony_cibool I18nTimeZoneAddon::CheckLatitudeTypeAndScope(napi_env env, napi_value argv, double &y)
3209596a2c1Sopenharmony_ci{
3219596a2c1Sopenharmony_ci    napi_status status = napi_get_value_double(env, argv, &y);
3229596a2c1Sopenharmony_ci    if (status != napi_ok) {
3239596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("GetTimezonesByLocation: Parse second argument y failed");
3249596a2c1Sopenharmony_ci        return false;
3259596a2c1Sopenharmony_ci    }
3269596a2c1Sopenharmony_ci    // -90 and 89.9 is the scope of latitude
3279596a2c1Sopenharmony_ci    if (y < -90 || y > 89.9) {
3289596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("GetTimezonesByLocation: Args y exceed it's scope.");
3299596a2c1Sopenharmony_ci        return false;
3309596a2c1Sopenharmony_ci    }
3319596a2c1Sopenharmony_ci    return true;
3329596a2c1Sopenharmony_ci}
3339596a2c1Sopenharmony_ci
3349596a2c1Sopenharmony_cinapi_value I18nTimeZoneAddon::GetID(napi_env env, napi_callback_info info)
3359596a2c1Sopenharmony_ci{
3369596a2c1Sopenharmony_ci    size_t argc = 0;
3379596a2c1Sopenharmony_ci    napi_value *argv = nullptr;
3389596a2c1Sopenharmony_ci    napi_value thisVar = nullptr;
3399596a2c1Sopenharmony_ci    void *data = nullptr;
3409596a2c1Sopenharmony_ci    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
3419596a2c1Sopenharmony_ci    I18nTimeZoneAddon *obj = nullptr;
3429596a2c1Sopenharmony_ci    napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
3439596a2c1Sopenharmony_ci    if (status != napi_ok || !obj || !obj->timezone_) {
3449596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("GetID: Get TimeZone object failed");
3459596a2c1Sopenharmony_ci        return nullptr;
3469596a2c1Sopenharmony_ci    }
3479596a2c1Sopenharmony_ci    std::string result = obj->timezone_->GetID();
3489596a2c1Sopenharmony_ci    napi_value value = nullptr;
3499596a2c1Sopenharmony_ci    status = napi_create_string_utf8(env, result.c_str(), NAPI_AUTO_LENGTH, &value);
3509596a2c1Sopenharmony_ci    if (status != napi_ok) {
3519596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("GetID: Create result failed");
3529596a2c1Sopenharmony_ci        return nullptr;
3539596a2c1Sopenharmony_ci    }
3549596a2c1Sopenharmony_ci    return value;
3559596a2c1Sopenharmony_ci}
3569596a2c1Sopenharmony_ci
3579596a2c1Sopenharmony_cinapi_value I18nTimeZoneAddon::GetTimeZoneDisplayName(napi_env env, napi_callback_info info)
3589596a2c1Sopenharmony_ci{
3599596a2c1Sopenharmony_ci    size_t argc = 2;
3609596a2c1Sopenharmony_ci    napi_value argv[2] = { 0 };
3619596a2c1Sopenharmony_ci    napi_value thisVar = nullptr;
3629596a2c1Sopenharmony_ci    void *data = nullptr;
3639596a2c1Sopenharmony_ci    napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
3649596a2c1Sopenharmony_ci    if (status != napi_ok) {
3659596a2c1Sopenharmony_ci        return nullptr;
3669596a2c1Sopenharmony_ci    }
3679596a2c1Sopenharmony_ci
3689596a2c1Sopenharmony_ci    I18nTimeZoneAddon *obj = nullptr;
3699596a2c1Sopenharmony_ci    status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
3709596a2c1Sopenharmony_ci    if (status != napi_ok || !obj || !obj->timezone_) {
3719596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("GetTimeZoneDisplayName: Get TimeZone object failed");
3729596a2c1Sopenharmony_ci        return nullptr;
3739596a2c1Sopenharmony_ci    }
3749596a2c1Sopenharmony_ci
3759596a2c1Sopenharmony_ci    std::string locale;
3769596a2c1Sopenharmony_ci    bool isDST = false;
3779596a2c1Sopenharmony_ci    int32_t parameterStatus = GetParameter(env, argv, locale, isDST);
3789596a2c1Sopenharmony_ci
3799596a2c1Sopenharmony_ci    std::string result;
3809596a2c1Sopenharmony_ci    if (parameterStatus == -1) {  // -1 represents Invalid parameter.
3819596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("GetTimeZoneDisplayName: Parameter type does not match");
3829596a2c1Sopenharmony_ci        return nullptr;
3839596a2c1Sopenharmony_ci    } else if (parameterStatus == 0) {
3849596a2c1Sopenharmony_ci        result = obj->timezone_->GetDisplayName();
3859596a2c1Sopenharmony_ci    } else if (parameterStatus == 1) {  // 1 represents one string parameter.
3869596a2c1Sopenharmony_ci        result = obj->timezone_->GetDisplayName(locale);
3879596a2c1Sopenharmony_ci    } else if (parameterStatus == 2) {  // 2 represents one boolean parameter.
3889596a2c1Sopenharmony_ci        result = obj->timezone_->GetDisplayName(isDST);
3899596a2c1Sopenharmony_ci    } else {
3909596a2c1Sopenharmony_ci        result = obj->timezone_->GetDisplayName(locale, isDST);
3919596a2c1Sopenharmony_ci    }
3929596a2c1Sopenharmony_ci
3939596a2c1Sopenharmony_ci    napi_value value = nullptr;
3949596a2c1Sopenharmony_ci    status = napi_create_string_utf8(env, result.c_str(), NAPI_AUTO_LENGTH, &value);
3959596a2c1Sopenharmony_ci    if (status != napi_ok) {
3969596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("GetTimeZoneDisplayName: Create result failed");
3979596a2c1Sopenharmony_ci        return nullptr;
3989596a2c1Sopenharmony_ci    }
3999596a2c1Sopenharmony_ci    return value;
4009596a2c1Sopenharmony_ci}
4019596a2c1Sopenharmony_ci
4029596a2c1Sopenharmony_cinapi_value I18nTimeZoneAddon::GetRawOffset(napi_env env, napi_callback_info info)
4039596a2c1Sopenharmony_ci{
4049596a2c1Sopenharmony_ci    size_t argc = 0;
4059596a2c1Sopenharmony_ci    napi_value *argv = nullptr;
4069596a2c1Sopenharmony_ci    napi_value thisVar = nullptr;
4079596a2c1Sopenharmony_ci    void *data = nullptr;
4089596a2c1Sopenharmony_ci    napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
4099596a2c1Sopenharmony_ci    I18nTimeZoneAddon *obj = nullptr;
4109596a2c1Sopenharmony_ci    napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
4119596a2c1Sopenharmony_ci    if (status != napi_ok || !obj || !obj->timezone_) {
4129596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("GetRawOffset: Get TimeZone object failed");
4139596a2c1Sopenharmony_ci        return nullptr;
4149596a2c1Sopenharmony_ci    }
4159596a2c1Sopenharmony_ci    int32_t result = obj->timezone_->GetRawOffset();
4169596a2c1Sopenharmony_ci    napi_value value = nullptr;
4179596a2c1Sopenharmony_ci    status = napi_create_int32(env, result, &value);
4189596a2c1Sopenharmony_ci    if (status != napi_ok) {
4199596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("GetRawOffset: Create result failed");
4209596a2c1Sopenharmony_ci        return nullptr;
4219596a2c1Sopenharmony_ci    }
4229596a2c1Sopenharmony_ci    return value;
4239596a2c1Sopenharmony_ci}
4249596a2c1Sopenharmony_ci
4259596a2c1Sopenharmony_cinapi_value I18nTimeZoneAddon::GetOffset(napi_env env, napi_callback_info info)
4269596a2c1Sopenharmony_ci{
4279596a2c1Sopenharmony_ci    size_t argc = 1;
4289596a2c1Sopenharmony_ci    napi_value argv[1] = { 0 };
4299596a2c1Sopenharmony_ci    napi_value thisVar = nullptr;
4309596a2c1Sopenharmony_ci    void *data = nullptr;
4319596a2c1Sopenharmony_ci    napi_status status = napi_get_cb_info(env, info, &argc, argv, &thisVar, &data);
4329596a2c1Sopenharmony_ci    if (status != napi_ok) {
4339596a2c1Sopenharmony_ci        return nullptr;
4349596a2c1Sopenharmony_ci    }
4359596a2c1Sopenharmony_ci
4369596a2c1Sopenharmony_ci    double date = 0;
4379596a2c1Sopenharmony_ci    if (VariableConvertor::CheckNapiValueType(env, argv[0])) {
4389596a2c1Sopenharmony_ci        napi_valuetype valueType = napi_valuetype::napi_undefined;
4399596a2c1Sopenharmony_ci        napi_typeof(env, argv[0], &valueType);
4409596a2c1Sopenharmony_ci        if (valueType != napi_valuetype::napi_number) {
4419596a2c1Sopenharmony_ci            HILOG_ERROR_I18N("GetOffset: Invalid parameter type");
4429596a2c1Sopenharmony_ci            return nullptr;
4439596a2c1Sopenharmony_ci        }
4449596a2c1Sopenharmony_ci        status = napi_get_value_double(env, argv[0], &date);
4459596a2c1Sopenharmony_ci        if (status != napi_ok) {
4469596a2c1Sopenharmony_ci            HILOG_ERROR_I18N("Get parameter date failed");
4479596a2c1Sopenharmony_ci            return nullptr;
4489596a2c1Sopenharmony_ci        }
4499596a2c1Sopenharmony_ci    } else {
4509596a2c1Sopenharmony_ci        auto time = std::chrono::system_clock::now();
4519596a2c1Sopenharmony_ci        auto since_epoch = time.time_since_epoch();
4529596a2c1Sopenharmony_ci        auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(since_epoch);
4539596a2c1Sopenharmony_ci        date = (double)millis.count();
4549596a2c1Sopenharmony_ci    }
4559596a2c1Sopenharmony_ci
4569596a2c1Sopenharmony_ci    I18nTimeZoneAddon *obj = nullptr;
4579596a2c1Sopenharmony_ci    status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&obj));
4589596a2c1Sopenharmony_ci    if (status != napi_ok || !obj || !obj->timezone_) {
4599596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("GetOffset: Get TimeZone object failed");
4609596a2c1Sopenharmony_ci        return nullptr;
4619596a2c1Sopenharmony_ci    }
4629596a2c1Sopenharmony_ci    int32_t result = obj->timezone_->GetOffset(date);
4639596a2c1Sopenharmony_ci    napi_value value = nullptr;
4649596a2c1Sopenharmony_ci    status = napi_create_int32(env, result, &value);
4659596a2c1Sopenharmony_ci    if (status != napi_ok) {
4669596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("GetOffset: Create result failed");
4679596a2c1Sopenharmony_ci        return nullptr;
4689596a2c1Sopenharmony_ci    }
4699596a2c1Sopenharmony_ci    return value;
4709596a2c1Sopenharmony_ci}
4719596a2c1Sopenharmony_ci
4729596a2c1Sopenharmony_cinapi_value I18nTimeZoneAddon::StaticGetTimeZone(napi_env env, napi_value *argv, bool isZoneID)
4739596a2c1Sopenharmony_ci{
4749596a2c1Sopenharmony_ci    napi_value constructor = nullptr;
4759596a2c1Sopenharmony_ci    napi_status status = napi_get_reference_value(env, *g_timezoneConstructor, &constructor);
4769596a2c1Sopenharmony_ci    if (status != napi_ok) {
4779596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("Failed to create reference at StaticGetTimeZone");
4789596a2c1Sopenharmony_ci        return nullptr;
4799596a2c1Sopenharmony_ci    }
4809596a2c1Sopenharmony_ci    napi_value newArgv[2] = { 0 };
4819596a2c1Sopenharmony_ci    newArgv[0] = argv[0];
4829596a2c1Sopenharmony_ci    status = napi_get_boolean(env, isZoneID, &newArgv[1]);
4839596a2c1Sopenharmony_ci    if (status != napi_ok) {
4849596a2c1Sopenharmony_ci        return nullptr;
4859596a2c1Sopenharmony_ci    }
4869596a2c1Sopenharmony_ci    napi_value result = nullptr;
4879596a2c1Sopenharmony_ci    status = napi_new_instance(env, constructor, 2, newArgv, &result); // 2 is parameter num
4889596a2c1Sopenharmony_ci    if (status != napi_ok) {
4899596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("StaticGetTimeZone create instance failed");
4909596a2c1Sopenharmony_ci        return nullptr;
4919596a2c1Sopenharmony_ci    }
4929596a2c1Sopenharmony_ci    return result;
4939596a2c1Sopenharmony_ci}
4949596a2c1Sopenharmony_ci
4959596a2c1Sopenharmony_ciint32_t I18nTimeZoneAddon::GetParameter(napi_env env, napi_value *argv, std::string &localeStr, bool &isDST)
4969596a2c1Sopenharmony_ci{
4979596a2c1Sopenharmony_ci    napi_status status = napi_ok;
4989596a2c1Sopenharmony_ci    if (VariableConvertor::CheckNapiValueType(env, argv[1])) {
4999596a2c1Sopenharmony_ci        napi_valuetype valueType0 = napi_valuetype::napi_undefined;
5009596a2c1Sopenharmony_ci        napi_valuetype valueType1 = napi_valuetype::napi_undefined;
5019596a2c1Sopenharmony_ci        napi_typeof(env, argv[0], &valueType0);  // 0 represents first parameter
5029596a2c1Sopenharmony_ci        napi_typeof(env, argv[1], &valueType1);  // 1 represents second parameter
5039596a2c1Sopenharmony_ci        bool firstParamFlag = VariableConvertor::CheckNapiValueType(env, argv[0]);
5049596a2c1Sopenharmony_ci        if (valueType1 == napi_valuetype::napi_boolean) {
5059596a2c1Sopenharmony_ci            status = napi_get_value_bool(env, argv[1], &isDST);
5069596a2c1Sopenharmony_ci            if (status != napi_ok) {
5079596a2c1Sopenharmony_ci                return -1;  // -1 represents Invalid parameter.
5089596a2c1Sopenharmony_ci            } else if (!firstParamFlag) {
5099596a2c1Sopenharmony_ci                return 2;  // 2 represents one boolean parameter.
5109596a2c1Sopenharmony_ci            }
5119596a2c1Sopenharmony_ci            if (valueType0 == napi_valuetype::napi_string &&
5129596a2c1Sopenharmony_ci                 GetStringFromJS(env, argv[0], localeStr)) {
5139596a2c1Sopenharmony_ci                return 3;  // 3 represents one string parameter and one bool parameter.
5149596a2c1Sopenharmony_ci            }
5159596a2c1Sopenharmony_ci        }
5169596a2c1Sopenharmony_ci        return -1;  // -1 represents Invalid parameter.
5179596a2c1Sopenharmony_ci    }
5189596a2c1Sopenharmony_ci    return GetFirstParameter(env, argv[0], localeStr, isDST);
5199596a2c1Sopenharmony_ci}
5209596a2c1Sopenharmony_ci
5219596a2c1Sopenharmony_cibool I18nTimeZoneAddon::GetStringFromJS(napi_env env, napi_value argv, std::string &jsString)
5229596a2c1Sopenharmony_ci{
5239596a2c1Sopenharmony_ci    size_t len = 0;
5249596a2c1Sopenharmony_ci    napi_status status = napi_get_value_string_utf8(env, argv, nullptr, 0, &len);
5259596a2c1Sopenharmony_ci    if (status != napi_ok) {
5269596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("Failed to get string length");
5279596a2c1Sopenharmony_ci        return false;
5289596a2c1Sopenharmony_ci    }
5299596a2c1Sopenharmony_ci    std::vector<char> argvBuf(len + 1);
5309596a2c1Sopenharmony_ci    status = napi_get_value_string_utf8(env, argv, argvBuf.data(), len + 1, &len);
5319596a2c1Sopenharmony_ci    if (status != napi_ok) {
5329596a2c1Sopenharmony_ci        HILOG_ERROR_I18N("Failed to get string item");
5339596a2c1Sopenharmony_ci        return false;
5349596a2c1Sopenharmony_ci    }
5359596a2c1Sopenharmony_ci    jsString = argvBuf.data();
5369596a2c1Sopenharmony_ci    return true;
5379596a2c1Sopenharmony_ci}
5389596a2c1Sopenharmony_ci
5399596a2c1Sopenharmony_ciint32_t I18nTimeZoneAddon::GetFirstParameter(napi_env env, napi_value value, std::string &localeStr, bool &isDST)
5409596a2c1Sopenharmony_ci{
5419596a2c1Sopenharmony_ci    if (!VariableConvertor::CheckNapiValueType(env, value)) {
5429596a2c1Sopenharmony_ci        return 0;  // 0 represents no parameter.
5439596a2c1Sopenharmony_ci    } else {
5449596a2c1Sopenharmony_ci        napi_status status = napi_ok;
5459596a2c1Sopenharmony_ci        napi_valuetype valueType = napi_valuetype::napi_undefined;
5469596a2c1Sopenharmony_ci        napi_typeof(env, value, &valueType);
5479596a2c1Sopenharmony_ci        if (valueType == napi_valuetype::napi_string) {
5489596a2c1Sopenharmony_ci            bool valid = GetStringFromJS(env, value, localeStr);
5499596a2c1Sopenharmony_ci            // -1 represents Invalid parameter.
5509596a2c1Sopenharmony_ci            // 1 represents one string parameter.
5519596a2c1Sopenharmony_ci            return !valid ? -1 : 1;
5529596a2c1Sopenharmony_ci        } else if (valueType == napi_valuetype::napi_boolean) {
5539596a2c1Sopenharmony_ci            status = napi_get_value_bool(env, value, &isDST);
5549596a2c1Sopenharmony_ci            // -1 represents Invalid parameter.
5559596a2c1Sopenharmony_ci            // 2 represents one boolean parameter.
5569596a2c1Sopenharmony_ci            return (status != napi_ok) ? -1 : 2;
5579596a2c1Sopenharmony_ci        }
5589596a2c1Sopenharmony_ci        return -1;  // -1 represents Invalid parameter.
5599596a2c1Sopenharmony_ci    }
5609596a2c1Sopenharmony_ci}
5619596a2c1Sopenharmony_ci} // namespace I18n
5629596a2c1Sopenharmony_ci} // namespace Global
5639596a2c1Sopenharmony_ci} // namespace OHOS