/*
 * Copyright (C) 2022-2026 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "utils.h"

#ifdef OHOS_BUILD_ENABLE_HISYSEVENT
#include <hisysevent.h>
#endif //OHOS_BUILD_ENABLE_HISYSEVENT

#include "accessibility_base_utils.h"
#include "bundle_mgr_client.h"
#include "hilog_wrapper.h"
#include "nlohmann/json.hpp"
#include "ipc_skeleton.h"
#include "parameters.h"
#include "bundle_info.h"
#include "bundlemgr/bundle_mgr_interface.h"
#include "accessibility_resource_bundle_manager.h"
#include "app_mgr_client.h"
#include "configuration.h"
#include "res_config.h"
#include "locale_config.h"
#include "locale_info.h"
#include "os_account_manager.h"

// LCOV_EXCL_START
namespace OHOS {
namespace Accessibility {
namespace {
    const std::string KEY_ACCESSIBILITY_ABILITY_TYPES = "accessibilityAbilityTypes";
    const std::string KEY_ACCESSIBILITY_CAPABILITIES = "accessibilityCapabilities";
    const std::string KEY_SETTINGS_ABILITY = "settingsAbility";
    const std::string KEY_ACCESSIBILITY_CAPABILITIES_RATIONALE = "accessibilityCapabilityRationale";
    const std::string KEY_IS_IMPORTANT = "isImportant";
    const std::string KEY_NEED_HIDE = "needHide";
    const std::string KEY_ACCESSIBILITY_EVENT_CONFIGURE = "accessibilityEventConfigure";
    const std::string KEY_ACCESSIBILITY_READABLE_RULES = "readableRules";

    // The json value of accessibilityAbility type
    const std::string ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_SPOKEN = "spoken";
    const std::string ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_HAPIC = "haptic";
    const std::string ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_AUDIBLE = "audible";
    const std::string ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_VISUAL = "visual";
    const std::string ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_GENERIC = "generic";
    const std::string ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_ALL = "all";

    // The json value of capabilities
    const std::string CAPABILITIES_JSON_VALUE_RETRIEVE = "retrieve";
    const std::string CAPABILITIES_JSON_VALUE_TOUCH_GUIDE = "touchGuide";
    const std::string CAPABILITIES_JSON_VALUE_KEY_EVENT_OBSERVER = "keyEventObserver";
    const std::string CAPABILITIES_JSON_VALUE_ZOOM = "zoom";
    const std::string CAPABILITIES_JSON_VALUE_GESTURE = "gesture";

    const std::string FOLD_SCREEN_TYPE = system::GetParameter("const.window.foldscreen.type", "0,0,0,0");
    const bool IS_WIDE_FOLD = (FOLD_SCREEN_TYPE == "4,2,0,0");
    const bool IS_BIG_FOLD = (FOLD_SCREEN_TYPE == "1,2,0,0") || (FOLD_SCREEN_TYPE == "6,1,0,0");
    const bool IS_SMALL_FOLD = (FOLD_SCREEN_TYPE == "2,2,0,0");
    const int32_t STRING_LEN_MAX = 10240;
    constexpr int32_t BASE_USER_RANGE = 200000;
    constexpr int32_t INVALID_ID = -1;
    constexpr int32_t INVALID_USER_ID = -1;
    constexpr int32_t DECIMAL_BASE = 10;
    constexpr uint64_t ELEMENT_MOVE_BIT = 40;
} // namespace

class JsonUtils {
public:
    static bool GetStringFromJson(const nlohmann::json &json, const std::string &key, std::string &value)
    {
        HILOG_DEBUG("start.");
        if (!json.is_object()) {
            HILOG_ERROR("json is not object.");
            return false;
        }
        if (json.find(key) != json.end() && json.at(key).is_string()) {
            HILOG_DEBUG("Find key[%{public}s] successful.", key.c_str());
            value = json.at(key).get<std::string>();
        }
        return true;
    }

    static bool GetStringVecFromJson(const nlohmann::json &json, const std::string &key,
        std::vector<std::string> &value)
    {
        HILOG_DEBUG("start.");
        if (!json.is_object()) {
            HILOG_ERROR("json is not object.");
            return false;
        }

        auto it = json.find(key);
        if (it != json.end() && it->is_array()) {
            const auto &array = *it;
            for (const auto &item : array) {
                if (!item.is_string()) {
                    HILOG_ERROR("Array elements are not all strings");
                    return false;
                }
            }
            HILOG_DEBUG("Find key[%{public}s] successful.", key.c_str());
            value = array.get<std::vector<std::string>>();
        }
        return true;
    }

    static bool GetJsonStringFromJson(const nlohmann::json &json, const std::string &key, std::string &value)
    {
        HILOG_INFO("start.");
        if (!json.is_object()) {
            HILOG_ERROR("json is not object.");
            return false;
        }
        if (json.contains(key) && json.at(key).is_object()) {
            HILOG_INFO("Find key[%{public}s] successful.", key.c_str());
            value = json.at(key).dump();
        }
        return true;
    }

    static bool GetBoolFromJson(const nlohmann::json &json, const std::string &key, bool &value)
    {
        HILOG_DEBUG("start.");
        if (!json.is_object()) {
            HILOG_ERROR("json is not object.");
            return false;
        }
        if (json.find(key) != json.end() && json.at(key).is_boolean()) {
            HILOG_DEBUG("Find key[%{public}s] successful.", key.c_str());
            value = json.at(key).get<bool>();
        }
        return true;
    }
};

class PraseVecUtils {
public:
    static uint32_t ParseAbilityTypesFromVec(const std::vector<std::string> &abilities)
    {
        HILOG_DEBUG("start.");
        uint32_t abilityTypes = 0;

        for (const auto &ability : abilities) {
            if (ability == ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_SPOKEN) {
                abilityTypes |= AccessibilityAbilityTypes::ACCESSIBILITY_ABILITY_TYPE_SPOKEN;
            }

            if (ability == ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_HAPIC) {
                abilityTypes |= AccessibilityAbilityTypes::ACCESSIBILITY_ABILITY_TYPE_HAPTIC;
            }

            if (ability == ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_AUDIBLE) {
                abilityTypes |= AccessibilityAbilityTypes::ACCESSIBILITY_ABILITY_TYPE_AUDIBLE;
            }

            if (ability == ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_VISUAL) {
                abilityTypes |= AccessibilityAbilityTypes::ACCESSIBILITY_ABILITY_TYPE_VISUAL;
            }

            if (ability == ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_GENERIC) {
                abilityTypes |= AccessibilityAbilityTypes::ACCESSIBILITY_ABILITY_TYPE_GENERIC;
            }

            if (ability == ACCESSIBILITY_ABILITY_TYPES_JSON_VALUE_ALL) {
                abilityTypes |= AccessibilityAbilityTypes::ACCESSIBILITY_ABILITY_TYPE_ALL;
            }
        }
        return abilityTypes;
    }
};

void Utils::Parse(const AppExecFwk::ExtensionAbilityInfo &abilityInfo, AccessibilityAbilityInitParams &initParams)
{
    HILOG_DEBUG("start.");
    initParams.name = abilityInfo.name;
    initParams.bundleName = abilityInfo.bundleName;
    initParams.moduleName = abilityInfo.moduleName;
    initParams.description = abilityInfo.description;
    initParams.label = abilityInfo.label;

    std::vector<std::string> profileInfos;
    std::string metadataName = "ohos.accessibleability";
    AppExecFwk::BundleMgrClient bundleMgrClient;
    bundleMgrClient.GetResConfigFile(abilityInfo, metadataName, profileInfos);
    if (profileInfos.empty()) {
        HILOG_ERROR("profileInfos is empty.");
        return;
    }

    if (!nlohmann::json::accept(profileInfos[0])) {
        HILOG_ERROR("profileInfos is not json format.");
        return;
    }
    nlohmann::json sourceJson = nlohmann::json::parse(profileInfos[0]);

    std::vector<std::string> capabilities;
    if (!JsonUtils::GetStringVecFromJson(sourceJson, KEY_ACCESSIBILITY_CAPABILITIES, capabilities)) {
        HILOG_ERROR("Get accessibilityCapabilities from json failed.");
        return;
    }
    initParams.staticCapabilities = ParseCapabilitiesFromVec(capabilities);

    std::vector<std::string> abilityTypes;
    if (!JsonUtils::GetStringVecFromJson(sourceJson, KEY_ACCESSIBILITY_ABILITY_TYPES, abilityTypes)) {
        HILOG_ERROR("Get accessibilityAbilityTypes from json failed.");
        return;
    }
    initParams.abilityTypes = PraseVecUtils::ParseAbilityTypesFromVec(abilityTypes);

    if (!JsonUtils::GetStringFromJson(sourceJson, KEY_ACCESSIBILITY_CAPABILITIES_RATIONALE, initParams.rationale)) {
        HILOG_ERROR("Get accessibilityCapabilityRationale from json failed.");
        return;
    }

    if (!JsonUtils::GetStringFromJson(sourceJson, KEY_SETTINGS_ABILITY, initParams.settingsAbility)) {
        HILOG_ERROR("Get settingsAbility from json failed.");
        return;
    }

    if (!JsonUtils::GetBoolFromJson(sourceJson, KEY_IS_IMPORTANT, initParams.isImportant)) {
        HILOG_ERROR("Get isImportant from json failed.");
        return;
    }

    if (!JsonUtils::GetBoolFromJson(sourceJson, KEY_NEED_HIDE, initParams.needHide)) {
        HILOG_ERROR("Get needHide from json failed.");
        return;
    }

    if (!JsonUtils::GetJsonStringFromJson(sourceJson, KEY_ACCESSIBILITY_READABLE_RULES, initParams.readableRules)) {
        HILOG_ERROR("Get readableRules from json failed.");
        return;
    }

    if (!JsonUtils::GetStringVecFromJson(sourceJson, KEY_ACCESSIBILITY_EVENT_CONFIGURE, initParams.eventConfigure)) {
        HILOG_ERROR("Get accessibilityEventConfigure from json failed.");
        return;
    }
}

int64_t Utils::GetSystemTime()
{
    HILOG_DEBUG("start.");

    struct timespec times = {0, 0};
    clock_gettime(CLOCK_MONOTONIC, &times);
    int64_t millisecond = static_cast<int64_t>(times.tv_sec * 1000 + times.tv_nsec / 1000000);

    return millisecond;
}

std::string Utils::GetUri(const OHOS::AppExecFwk::ElementName &elementName)
{
    HILOG_DEBUG("bundle name(%{public}s) ability name(%{public}s)",
        elementName.GetBundleName().c_str(), elementName.GetAbilityName().c_str());
    return elementName.GetBundleName() + "/" + elementName.GetAbilityName();
}

std::string Utils::GetUri(const std::string &bundleName, const std::string &abilityName)
{
    HILOG_DEBUG("bundle name(%{public}s) ability name(%{public}s)", bundleName.c_str(), abilityName.c_str());
    return bundleName + "/" + abilityName;
}

std::string Utils::GetBundleNameFromUri(const std::string &uri)
{
    if (uri.empty()) {
        return "";
    }
    size_t pos = uri.find('/');
    if (pos != std::string::npos) {
        return uri.substr(0, pos);
    }
    return uri;
}

std::string Utils::GetAbilityAutoStartStateKey(const std::string &bundleName, const std::string &abilityName,
    int32_t accountId)
{
    HILOG_DEBUG("bundle name(%{public}s) ability name(%{public}s) accountId(%{public}d)",
        bundleName.c_str(), abilityName.c_str(), accountId);
    return bundleName + "/" + abilityName + "/" + std::to_string(accountId);
}

void Utils::SelectUsefulFromVecWithSameBundle(std::vector<std::string> &selectVec, std::vector<std::string> &cmpVec,
    bool &hasDif, const std::string &bundleName)
{
    HILOG_DEBUG();
    for (auto iter = selectVec.begin(); iter != selectVec.end();) {
        if (iter->substr(0, iter->find("/")) != bundleName) {
            ++iter;
            continue;
        }
        auto it = cmpVec.begin();
        for (; it != cmpVec.end(); ++it) {
            if ((*it) == (*iter)) {
                break;
            }
        }
        if (it == cmpVec.end()) {
            iter = selectVec.erase(iter);
            hasDif = true;
        } else {
            ++iter;
        }
    }
}

void Utils::RecordUnavailableEvent(A11yUnavailableEvent event, A11yError errCode,
    const std::string &bundleName, const std::string &abilityName)
{
    if (!(errCode > A11yError::ERROR_NEED_REPORT_BASE && errCode < A11yError::ERROR_NEED_REPORT_END)) {
        return;
    }
    std::ostringstream oss;
    oss << "accessibility function is unavailable: " << "event: " << TransferUnavailableEventToString(event)
        << ", errCode: " << static_cast<int32_t>(errCode)
        << ", bundleName: " << bundleName << ", abilityName: " << abilityName << ";";
    std::string info = oss.str();
    HILOG_DEBUG("accessibility function is unavailable: %{public}s", info.c_str());
#ifdef OHOS_BUILD_ENABLE_HISYSEVENT
    int32_t ret = HiSysEventWrite(
        OHOS::HiviewDFX::HiSysEvent::Domain::ACCESSIBILITY,
        "UNAVAILABLE",
        OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
        "MSG", info);
    if (ret != 0) {
        HILOG_ERROR("Write HiSysEvent error, ret:%{public}d", ret);
    }
#endif //OHOS_BUILD_ENABLE_HISYSEVENT
}

void Utils::RecordOnRemoveSystemAbility(int32_t systemAbilityId, const std::string &bundleName,
    const std::string &abilityName)
{
    std::ostringstream oss;
    oss << "OnRemoveSystemAbility systemAbilityId is: " << systemAbilityId
        << ", bundleName: " << bundleName << ", abilityName: " << abilityName << ";";
    std::string info = oss.str();
    HILOG_DEBUG("accessibility function is unavailable: %{public}s", info.c_str());
#ifdef OHOS_BUILD_ENABLE_HISYSEVENT
    int32_t ret = HiSysEventWrite(
        OHOS::HiviewDFX::HiSysEvent::Domain::ACCESSIBILITY,
        "UNAVAILABLE",
        OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
        "MSG", info);
    if (ret != 0) {
        HILOG_ERROR("Write OnRemoveSystemAbility error, ret:%{public}d", ret);
    }
#endif //OHOS_BUILD_ENABLE_HISYSEVENT
}

void Utils::RecordDatashareInteraction(A11yDatashareValueType type, const std::string &businessName,
    const std::string &bundleName, const std::string &abilityName)
{
    std::ostringstream oss;
    oss << "datashare interaction failed, type is: " << static_cast<uint32_t>(type)
        << ", businessName: " << businessName << ", bundleName: " << bundleName
        << ", abilityName: " << abilityName << ";";
    std::string info = oss.str();
    HILOG_DEBUG("accessibility function is unavailable: %{public}s", info.c_str());
#ifdef OHOS_BUILD_ENABLE_HISYSEVENT
    int32_t ret = HiSysEventWrite(
        OHOS::HiviewDFX::HiSysEvent::Domain::ACCESSIBILITY,
        "UNAVAILABLE",
        OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
        "MSG", info);
    if (ret != 0) {
        HILOG_ERROR("Write RecordDatashareInteraction error, ret:%{public}d", ret);
    }
#endif //OHOS_BUILD_ENABLE_HISYSEVENT
}

void Utils::RecordSetSeniorModeState(const std::map<std::string, int32_t> &seniorModeInfo)
{
    HILOG_INFO();
    std::vector<std::string> bundleNames;
    std::vector<int32_t> appIndexs;
    std::vector<int32_t> times;
    for (const auto &item : seniorModeInfo) {
        std::string bundleName;
        int32_t appIndex = 0;
        if (ParseSeniorModeStateKey(item.first, bundleName, appIndex)) {
            bundleNames.push_back(bundleName);
            appIndexs.push_back(appIndex);
            times.push_back(item.second);
        }
    }
    int32_t retsult = HiSysEventWrite(
        OHOS::HiviewDFX::HiSysEvent::Domain::ACCESSIBILITY,
        "SET_SENIOR_MODE_STATE",
        OHOS::HiviewDFX::HiSysEvent::EventType::STATISTIC,
        "BUNDLENAME", bundleNames, "APPINDEX", appIndexs,
        "TIMES", times);
    if (retsult != 0) {
        HILOG_ERROR("Write RecordSetSeniorModeState error, ret:%{public}d", retsult);
    }
}

std::string Utils::TransferUnavailableEventToString(A11yUnavailableEvent type)
{
    std::string event;
    switch (type) {
        case A11yUnavailableEvent::READ_EVENT:
            event = "READ";
            break;
        case A11yUnavailableEvent::CONNECT_EVENT:
            event = "CONNECT";
            break;
        case A11yUnavailableEvent::QUERY_EVENT:
            event = "QUERY";
            break;
        default:
            event = "UNDEFINE";
            break;
    }
    return event;
}

void Utils::RecordStartingA11yEvent(uint32_t flag)
{
    std::ostringstream oss;
    oss << "starting accessibility: " << "event: " << "system" << ", id: " << flag << ";";
    HILOG_DEBUG("starting accessibility: %{public}s", oss.str().c_str());
#ifdef OHOS_BUILD_ENABLE_HISYSEVENT
    int32_t ret = HiSysEventWrite(
        OHOS::HiviewDFX::HiSysEvent::Domain::ACCESSIBILITY,
        "STARTING_FUNCTION",
        OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
        "MSG", oss.str());
    if (ret != 0) {
        HILOG_ERROR("Write HiSysEvent error, ret:%{public}d", ret);
    }
#endif //OHOS_BUILD_ENABLE_HISYSEVENT
}

void Utils::RecordStartingA11yEvent(const std::string &name)
{
    std::ostringstream oss;
    oss << "starting accessibility: " << "event: " << "extension" << ", name: " << name << ";";
    HILOG_DEBUG("starting accessibility: %{public}s", oss.str().c_str());
#ifdef OHOS_BUILD_ENABLE_HISYSEVENT
    int32_t ret = HiSysEventWrite(
        OHOS::HiviewDFX::HiSysEvent::Domain::ACCESSIBILITY,
        "STARTING_FUNCTION",
        OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
        "MSG", oss.str());
    if (ret != 0) {
        HILOG_ERROR("Write HiSysEvent error, ret:%{public}d", ret);
    }
#endif //OHOS_BUILD_ENABLE_HISYSEVENT
}

void Utils::RecordMSDPUnavailableEvent(const std::string &name)
{
    std::ostringstream oss;
    oss << "msdp run failed" << ", caused by: " << name << ";";
    HILOG_DEBUG("starting accessibility: %{public}s", oss.str().c_str());
    int32_t ret = HiSysEventWrite(
        OHOS::HiviewDFX::HiSysEvent::Domain::ACCESSIBILITY,
        "UNAVAILABLE",
        OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
        "MSG", oss.str());
    if (ret != 0) {
        HILOG_ERROR("Write HiSysEvent error, ret:%{public}d", ret);
    }
}

void Utils::RecordEnableShortkeyAbilityEvent(const std::string &name, const bool &enableState)
{
    std::string MSG_NAME = "enable single targets";
    std::ostringstream oss;
    std::string enableStateValue = enableState ? "on" : "off";
    oss << "targets name: " << name.c_str() << ", state:" << enableStateValue.c_str() << ";";
    HILOG_DEBUG("RecordEnableShortkeyAbilityEvent enable single targets: %{public}s, enableState: %{public}s",
        name.c_str(), enableStateValue.c_str());
#ifdef OHOS_BUILD_ENABLE_HISYSEVENT
    int32_t ret = HiSysEventWrite(
        OHOS::HiviewDFX::HiSysEvent::Domain::ACCESSIBILITY_UE,
        "ENABLE_SHORTKEY_ABILITY_SINGLE",
        OHOS::HiviewDFX::HiSysEvent::EventType::BEHAVIOR,
        "MSG_NAME", MSG_NAME, "MSG_VALUE", oss.str());
    if (ret != 0) {
        HILOG_ERROR("Write HiSysEvent RecordEnableShortkeyAbilityEvent error, ret:%{public}d", ret);
    }
#endif //OHOS_BUILD_ENABLE_HISYSEVENT
}

void Utils::VectorToString(const std::vector<std::string> &vectorVal, std::string &stringOut)
{
    HILOG_DEBUG();
    int32_t i = 0;
    for (auto& var : vectorVal) {
        if (i > 0) {
            stringOut = stringOut + ',';
        }
        stringOut = stringOut + var.c_str();
        i++;
    }
    HILOG_DEBUG("stringOUT = %{public}s .", stringOut.c_str());
}

void Utils::StringToVector(const std::string &stringIn, std::vector<std::string> &vectorResult)
{
    HILOG_DEBUG();
    int32_t strLength = static_cast<int32_t>(stringIn.size());
    std::vector<int32_t> position;

    if (strLength <= 0 || strLength > STRING_LEN_MAX) {
        return;
    }

    for (int32_t j = 0; j < strLength; j++) {
        if (stringIn[j] == ',') {
            position.push_back(j);
        }
    }

    int32_t wrodCount = static_cast<int32_t>(position.size());
    if (wrodCount == 0) {
        vectorResult.push_back(stringIn);
    } else {
        int32_t startWrod = 0;
        int32_t length = 0;
        for (int32_t i = 0; i <= wrodCount; i++) {
            if (i == 0) {
                length = position[i];
                vectorResult.push_back(stringIn.substr(startWrod, length)); // First string
            } else if (i < wrodCount) {
                startWrod = position[i - 1] + 1;
                length = position[i] - position[i - 1] - 1;
                vectorResult.push_back(stringIn.substr(startWrod, length)); // Second string to last-1 string
            } else {
                startWrod = position[i - 1] + 1;
                length = strLength - position[i - 1] - 1;
                vectorResult.push_back(stringIn.substr(startWrod, length)); // Last string
            }
        }
    }
    HILOG_DEBUG("strLength = %{public}d, wrodCount = %{public}d, stringIn : %{public}s",
        strLength, wrodCount, stringIn.c_str());
    for (auto& var : vectorResult) {
        HILOG_DEBUG("vectorResult = %{public}s ", var.c_str());
    }
}

int32_t Utils::GetUserIdByCallingUid()
{
    int32_t uid = IPCSkeleton::GetCallingUid();
    if (uid <= INVALID_ID) {
        return INVALID_USER_ID;
    }
    return (uid / BASE_USER_RANGE);
}

bool Utils::UpdateColorModeConfiguration(int32_t accountId)
{
    HILOG_DEBUG();
    auto appMgrClient = std::make_unique<AppExecFwk::AppMgrClient>();
    if (appMgrClient == nullptr) {
        HILOG_ERROR("create appMgrClient failed");
        return false;
    }
    AppExecFwk::Configuration configuration;
    configuration.AddItem(AAFwk::GlobalConfigurationKey::SYSTEM_COLORMODE,
        AppExecFwk::ConfigurationInner::COLOR_MODE_LIGHT);
    AppExecFwk::AppMgrResultCode status = appMgrClient->UpdateConfiguration(configuration, accountId);
    if (status != AppExecFwk::AppMgrResultCode::RESULT_OK) {
        HILOG_ERROR("UpdateConfiguration: Update configuration failed.");
        return false;
    }
    return true;
}

bool Utils::IsWideFold()
{
    return IS_WIDE_FOLD;
}

bool Utils::IsBigFold()
{
    return IS_BIG_FOLD;
}

bool Utils::IsSmallFold()
{
    return IS_SMALL_FOLD;
}

bool Utils::GetBundleNameByCallingUid(std::string &bundleName)
{
    int32_t uid = IPCSkeleton::GetCallingUid();
    if (uid <= INVALID_ID) {
        return false;
    }
    bool ret = Singleton<AccessibilityResourceBundleManager>::GetInstance().GetBundleNameByUid(uid, bundleName);
    if (ret == false) {
        HILOG_ERROR("GetBundleNameByCallingUid failed");
        return ret;
    }
    HILOG_DEBUG("GetCallingUid:%{public}d, getBundleNameByUid:%{public}s", uid, bundleName.c_str());
    return true;
}

std::string Utils::FormatString(const std::string& format, const std::string& value)
{
    size_t bufferLength = format.size() + value.size() + 1; // +1 for null terminator
    if (bufferLength > INT32_MAX) {
        HILOG_ERROR("string length overflow!");
        return "";
    }
    int bufferSize = static_cast<int>(bufferLength);
    char* buffer = new char[bufferSize];
    if (snprintf_s(buffer, bufferSize, bufferSize -1, format.c_str(), value.c_str()) < 0) {
        delete[] buffer;
        return "";
    }
    std::string result(buffer);
    delete[] buffer;
    return result;
}

float Utils::StringToFloat(const std::string& value, const float& defaultValue)
{
    errno = 0;
    char* pEnd = nullptr;
    float result = std::strtof(value.c_str(), &pEnd);
    if (pEnd == value.c_str() || errno == ERANGE) {
        return defaultValue;
    } else {
        return result;
    }
}

int32_t Utils::GetTreeIdBySplitElementId(const int64_t elementId)
{
    if (elementId < 0) {
        HILOG_DEBUG("The elementId is -1");
        return elementId;
    }
    int32_t treeId = (static_cast<uint64_t>(elementId) >> ELEMENT_MOVE_BIT);
    return treeId;
}

RetError Utils::GetResourceBundleInfo(AccessibilityEventInfo &eventInfo, int32_t userId)
{
    HILOG_DEBUG("BundleName is %{public}s, ModuleName is %{public}s, ResourceId is %{public}d",
        eventInfo.GetResourceBundleName().c_str(), eventInfo.GetResourceModuleName().c_str(),
        eventInfo.GetResourceId());
    if (eventInfo.GetResourceId() > 0) {
        AppExecFwk::BundleInfo bundleInfo;
        ErrCode ret = Singleton<AccessibilityResourceBundleManager>::GetInstance().GetBundleInfoV9(
            eventInfo.GetResourceBundleName(),
            static_cast<int32_t>(AppExecFwk::GetBundleInfoFlag::GET_BUNDLE_INFO_WITH_HAP_MODULE),
            bundleInfo, userId);
        if (ret != ERR_OK) {
            HILOG_ERROR("get BundleInfo failed!");
            return RET_ERR_FAILED;
        }
 
        std::string resourceValue;
        RetError res = GetResourceValue(eventInfo, bundleInfo, userId, resourceValue);
        if (res != RET_OK) {
            HILOG_ERROR("Get Resource Value failed");
            return res;
        }
        HILOG_DEBUG("resource value is %{public}s", resourceValue.c_str());
        eventInfo.SetTextAnnouncedForAccessibility(resourceValue);
    }
    return RET_OK;
}
 
RetError Utils::GetResourceValue(AccessibilityEventInfo &eventInfo,
    AppExecFwk::BundleInfo bundleInfo, int32_t userId, std::string &result)
{
    std::unique_ptr<Global::Resource::ResConfig> resConfig(Global::Resource::CreateResConfig());
    if (resConfig == nullptr) {
        HILOG_ERROR("create resConfig failed");
        return RET_ERR_NULLPTR;
    }
    UErrorCode status = U_ZERO_ERROR;
    icu::Locale locale = icu::Locale::forLanguageTag(Global::I18n::LocaleConfig::GetSystemLanguage(), status);
    resConfig->SetLocaleInfo(locale.getLanguage(), locale.getScript(), locale.getCountry());
 
    std::string hapPath;
    std::vector<std::string> overlayPaths;
    int32_t appType = 0;
    std::shared_ptr<Global::Resource::ResourceManager> resourceManager(Global::Resource::CreateResourceManager(
        eventInfo.GetResourceBundleName(), eventInfo.GetResourceModuleName(), hapPath, overlayPaths, *resConfig,
        appType, userId));
    if (resourceManager == nullptr) {
        HILOG_ERROR("create Resource manager failed");
        return RET_ERR_NULLPTR;
    }
 
    Global::Resource::RState state = resourceManager->UpdateResConfig(*resConfig);
    if (state != Global::Resource::RState::SUCCESS) {
        HILOG_ERROR("UpdateResConfig failed! errCode: %{public}d", state);
        return RET_ERR_FAILED;
    }
 
    for (const auto &hapModuleInfo : bundleInfo.hapModuleInfos) {
        std::string moduleResPath = hapModuleInfo.hapPath.empty() ? hapModuleInfo.resourcePath : hapModuleInfo.hapPath;
        HILOG_DEBUG("hapModuleInfo.hapPath is %{public}s", hapModuleInfo.hapPath.c_str());
        if (moduleResPath.empty()) {
            HILOG_ERROR("moduleResPath is empty");
            continue;
        }
        if (!resourceManager->AddResource(moduleResPath.c_str())) {
            HILOG_ERROR("AddResource is failed");
        }
    }
 
    std::vector<std::tuple<Global::Resource::ResourceManager::NapiValueType, std::string>> arg;
    for (auto &param : eventInfo.GetResourceParams()) {
        HILOG_DEBUG("resource param valueType is %{public}d, value is %{public}s",
            std::get<0>(param), (std::get<1>(param)).c_str());
        if (std::get<0>(param) == 0) {
            arg.emplace_back(std::make_tuple(Global::Resource::ResourceManager::NapiValueType::NAPI_NUMBER,
                std::get<1>(param)));
        } else if (std::get<0>(param) == 1)
            arg.emplace_back(std::make_tuple(Global::Resource::ResourceManager::NapiValueType::NAPI_STRING,
                std::get<1>(param)));
    }
    Global::Resource::RState res = resourceManager->GetStringFormatById(eventInfo.GetResourceId(), result, arg);
    if (res != Global::Resource::RState::SUCCESS) {
        HILOG_ERROR("get resource value failed");
        return RET_ERR_FAILED;
    }
    return RET_OK;
}

std::string Utils::GetSeniorModeStateKey(const std::string& bundleName, int32_t appIndex)
{
    return bundleName + "_" + std::to_string(appIndex);
}

bool Utils::ParseSeniorModeStateKey(const std::string& key, std::string& bundleName, int32_t& appIndex)
{
    size_t pos = key.find_last_of('_');
    if (pos == std::string::npos || pos == key.length() - 1) {
        HILOG_ERROR("Invalid key format: %{public}s", key.c_str());
        return false;
    }

    bundleName = key.substr(0, pos);
    std::string appIndexStr = key.substr(pos + 1);

    for (char c : appIndexStr) {
        if (!std::isdigit(c)) {
            HILOG_ERROR("Invalid appIndex: %{public}s", appIndexStr.c_str());
            return false;
        }
    }

    appIndex = static_cast<int32_t>(std::strtol(appIndexStr.c_str(), nullptr, DECIMAL_BASE));
    return true;
}
// LCOV_EXCL_STOP
} // namespace Accessibility
} // namespace OHOS