/*
 * Copyright (c) 2025 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 "sts_common.h"

#include "ans_log_wrapper.h"
#include "ani_common_util.h"
#include "os_account_constants.h"
#include "os_account_info.h"
#include "os_account_manager.h"

namespace OHOS {
namespace NotificationSts {
constexpr const char* CLASSNAME_BOOLEAN = "std.core.Boolean";
constexpr const char* CLASSNAME_DOUBLE = "std.core.Double";
constexpr const char* CLASSNAME_INT = "std.core.Int";
constexpr const char* CLASSNAME_LONG = "std.core.Long";
ani_object GetNullObject(ani_env *env)
{
    if (env == nullptr) {
        ANS_LOGE("GetNullObject failed, env is nullptr");
        return nullptr;
    }
    ani_ref nullRef;
    ani_status status = env->GetNull(&nullRef);
    if (status != ANI_OK) {
        ANS_LOGE("GetNull failed, status: %{public}d", status);
        return nullptr;
    }
    return static_cast<ani_object>(nullRef);
}
std::string GetResizeStr(std::string instr, int32_t length)
{
    if (static_cast<int32_t>(instr.length()) <= length) {
        return instr;
    } else {
        int32_t endPos = 0;
        for (int32_t i = 0; i < static_cast<int32_t>(instr.size());) {
            if ((instr[i] & 0x80) == 0) {          // ASCII字符
                i += 1;
            } else if ((instr[i] & 0xE0) == 0xC0) { // 2字节字符
                i += 2;
            } else if ((instr[i] & 0xF0) == 0xE0) { // 3字节字符
                i += 3;
            } else if ((instr[i] & 0xF8) == 0xF0) { // 4字节字符
                i += 4;
            } else {
                // 无效的UTF-8序列
                i += 1;
            }
            if (i > length) {
                break;
            }
            endPos = i;
        }
        return instr.substr(0, endPos);
    }
}

int32_t GetOsAccountLocalIdFromUid(const int32_t uid, int32_t &userId)
{
    int32_t ret = AccountSA::OsAccountManager::GetOsAccountLocalIdFromUid(uid, userId);
    if (ret != ERR_OK) {
        ANS_LOGE("Get userId failed, uid = <%{public}d>, code is %{public}d", uid, ret);
        return ret;
    }
    ANS_LOGD("Get userId succ, uid = <%{public}d> userId = <%{public}d>", uid, userId);
    return ret;
}

bool IsUndefine(ani_env *env, const ani_object &obj)
{
    if (env == nullptr || obj == nullptr) {
        ANS_LOGE("IsUndefine fail, has nullptr");
        return true;
    }
    ani_boolean isUndefined;
    if (env->Reference_IsUndefined(obj, &isUndefined) != ANI_OK) {
        ANS_LOGE("Reference_IsUndefined  faild");
        return true;
    }
    return (isUndefined == ANI_TRUE) ? true : false;
}

ani_status GetAniStringByString(ani_env* env, const std::string str, ani_string& aniStr)
{
    if (env == nullptr) {
        ANS_LOGE("GetAniStringByString fail, env is nullptr");
        return ANI_INVALID_ARGS;
    }
    ani_status status = env->String_NewUTF8(str.c_str(), str.size(), &aniStr);
    if (status != ANI_OK) {
        ANS_LOGE("String_NewUTF8 failed %{public}d", status);
        return status;
    }
    return status;
}

ani_status GetStringByAniString(ani_env *env, ani_string str, std::string &res)
{
    if (str == nullptr || env == nullptr) {
        ANS_LOGE("GetStringByAniString fail, has nullptr");
        return ANI_INVALID_ARGS;
    }
    res = "";
    ani_size sz {};
    ani_status status = ANI_ERROR;
    if ((status = env->String_GetUTF8Size(str, &sz)) != ANI_OK) {
        ANS_LOGE("status : %{public}d", status);
        return status;
    }
    res.resize(sz + 1);
    if ((status = env->String_GetUTF8SubString(str, 0, sz, res.data(), res.size(), &sz)) != ANI_OK) {
        ANS_LOGE("status : %{public}d", status);
        return status;
    }
    res.resize(sz);
    return status;
}

bool GetStringArrayByAniObj(ani_env *env, const ani_object ani_obj, std::vector<std::string> &stdVString)
{
    if (env == nullptr || ani_obj == nullptr) {
        ANS_LOGE("GetStringArrayByAniObj fail, has nullptr");
        return false;
    }
    ani_int length;
    ani_status status = env->Object_GetPropertyByName_Int(ani_obj, "length", &length);
    if (status != ANI_OK) {
        ANS_LOGE("Object_GetPropertyByName_Int faild. status %{public}d", status);
        return false;
    }
    for (int32_t i = 0; i < length; i++) {
        ani_ref stringEntryRef;
        status = env->Object_CallMethodByName_Ref(ani_obj, "$_get", "i:Y", &stringEntryRef, i);
        if (status != ANI_OK) {
            ANS_LOGE("Object_CallMethodByName_Ref faild. status : %{public}d", status);
            return false;
        }
        std::string std_string;
        if ((status = GetStringByAniString(env, static_cast<ani_string>(stringEntryRef), std_string)) != ANI_OK) {
            ANS_LOGE("GetStringByAniString faild. status %{public}d", status);
            return false;
        }
        stdVString.emplace_back(std_string);
    }
    return true;
}

ani_status GetPropertyString(ani_env *env, ani_object obj, const char *name,
    ani_boolean &isUndefined, std::string &outStr)
{
    if (env == nullptr || obj == nullptr || name == nullptr) {
        ANS_LOGE("GetPropertyString fail, has nullptr");
        return ANI_INVALID_ARGS;
    }
    ANS_LOGD("GetPropertyString: %{public}s", name);
    ani_status status = ANI_ERROR;
    ani_ref strRef;
    if ((status =env->Object_GetPropertyByName_Ref(obj, name, &strRef)) != ANI_OK) {
        ANS_LOGE("Object_GetField_Ref bundle fail, status: %{public}d", status);
        return status;
    }
    status = env->Reference_IsUndefined(strRef, &isUndefined);
    if (status != ANI_OK) {
        ANS_LOGE("Failed to check undefined for '%{public}s', status: %{public}d", name, status);
        return status;
    }
    if (isUndefined == ANI_TRUE) {
        ANS_LOGE("%{public}s is undefined", name);
        return status;
    }
    if ((status = GetStringByAniString(env, reinterpret_cast<ani_string>(strRef), outStr)) != ANI_OK) {
        ANS_LOGE("GetStdString failed");
        return status;
    }
    return status;
}

ani_status GetPropertyBool(ani_env *env, ani_object obj, const char *name,
    ani_boolean &isUndefined, bool &outvalue)
{
    ANS_LOGD("GetPropertyBool start");
    if (env == nullptr || obj == nullptr || name == nullptr) {
        ANS_LOGE("GetPropertyBool fail, has nullptr");
        return ANI_INVALID_ARGS;
    }
    ANS_LOGD("GetPropertyBool: %{public}s", name);
    ani_ref refObj = nullptr;
    ani_status status = ANI_ERROR;
    status = env->Object_GetPropertyByName_Ref(obj, name, &refObj);
    if (ANI_OK != status) {
        ANS_LOGE("Object_GetPropertyByName_Ref fail, status: %{public}d", status);
        return status;
    }
    if ((status = env->Reference_IsUndefined(refObj, &isUndefined)) != ANI_OK) {
        ANS_LOGE("Reference_IsUndefined failed, status : %{public}d", status);
        return status;
    }
    if (isUndefined) {
        ANS_LOGE("%{public}s is undefined", name);
        return ANI_INVALID_ARGS;
    }
    ani_boolean result = ANI_FALSE;
    if ((status = env->Object_CallMethodByName_Boolean(static_cast<ani_object>(refObj),
        "toBoolean", ":z", &result)) != ANI_OK) {
        ANS_LOGE("Object_CallMethodByName_Boolean failed, status : %{public}d", status);
        return status;
    }
    outvalue = (result == ANI_TRUE);
    return status;
}

ani_status GetPropertyDouble(ani_env *env, ani_object obj, const char *name,
    ani_boolean &isUndefined, ani_double &outvalue)
{
    if (env == nullptr || obj == nullptr || name == nullptr) {
        ANS_LOGE("GetPropertyDouble fail, has nullptr");
        return ANI_INVALID_ARGS;
    }
    ANS_LOGD("GetPropertyDouble: %{public}s", name);
    ani_status status = ANI_ERROR;
    ani_ref refObj;
    status = GetPropertyRef(env, obj, name, isUndefined, refObj);
    if (status != ANI_OK || isUndefined == ANI_TRUE) {
        ANS_LOGE("%{public}s is undefined", name);
        return ANI_INVALID_ARGS;
    }
    if ((status = env->Object_CallMethodByName_Double(static_cast<ani_object>(refObj),
        "toDouble", ":d", &outvalue)) != ANI_OK) {
        ANS_LOGE("Object_CallMethodByName_Double failed, status : %{public}d", status);
        return status;
    }
    ANS_LOGD("GetPropertyDouble sucess");
    return status;
}

ani_status GetPropertyValueDouble(ani_env *env, ani_object param, const char *name, double &value)
{
    if (env == nullptr || param == nullptr || name == nullptr) {
        ANS_LOGE("GetPropertyValueDouble fail, has nullptr");
        return ANI_INVALID_ARGS;
    }
    ani_status status = ANI_ERROR;
    ani_double res = value;
    if ((status = env->Object_GetPropertyByName_Double(param, name, &res)) != ANI_OK) {
        ANS_LOGE("Object_GetPropertyByName_Double failed, status : %{public}d", status);
        return status;
    }
    value = static_cast<double>(res);
    return status;
}

ani_status GetPropertyInt(ani_env *env, ani_object obj, const char *name,
    ani_boolean &isUndefined, ani_int &outvalue)
{
    if (env == nullptr || obj == nullptr || name == nullptr) {
        ANS_LOGE("GetPropertyInt fail, has nullptr");
        return ANI_INVALID_ARGS;
    }
    ANS_LOGD("GetPropertyInt: %{public}s", name);
    ani_status status = ANI_ERROR;
    ani_ref refObj;
    status = GetPropertyRef(env, obj, name, isUndefined, refObj);
    if (status != ANI_OK || isUndefined == ANI_TRUE) {
        ANS_LOGE("%{public}s is undefined", name);
        return ANI_INVALID_ARGS;
    }
    if ((status = env->Object_CallMethodByName_Int(static_cast<ani_object>(refObj),
        "toInt", ":i", &outvalue)) != ANI_OK) {
        ANS_LOGE("Object_CallMethodByName_Int failed, status : %{public}d", status);
        return status;
    }
    ANS_LOGD("GetPropertyInt sucess");
    return status;
}

ani_status GetPropertyLong(ani_env *env, ani_object obj, const char *name,
    ani_boolean &isUndefined, ani_long &outvalue)
{
    if (env == nullptr || obj == nullptr || name == nullptr) {
        ANS_LOGE("GetPropertyLong fail, has nullptr");
        return ANI_INVALID_ARGS;
    }
    ANS_LOGD("GetPropertyLong: %{public}s", name);
    ani_status status = ANI_ERROR;
    ani_ref refObj;
    status = GetPropertyRef(env, obj, name, isUndefined, refObj);
    if (status != ANI_OK || isUndefined == ANI_TRUE) {
        ANS_LOGE("%{public}s is undefined", name);
        return ANI_INVALID_ARGS;
    }
    if ((status = env->Object_CallMethodByName_Long(static_cast<ani_object>(refObj),
        "toLong", ":l", &outvalue)) != ANI_OK) {
        ANS_LOGE("Object_CallMethodByName_Long failed, status : %{public}d", status);
        return status;
    }
    ANS_LOGD("GetPropertyLong sucess");
    return status;
}

void GetPropertyRefValue(ani_env *env, ani_object obj, const char *name, ani_boolean &isUndefined, ani_ref &outRef)
{
    if (env == nullptr || obj == nullptr || name == nullptr) {
        ANS_LOGE("GetPropertyRefValue fail, has nullptr");
        return;
    }
    outRef = nullptr;
    isUndefined = ANI_TRUE;
    ani_status status = ANI_ERROR;
    status = env->Object_GetPropertyByName_Ref(obj, name, &outRef);
    if (status != ANI_OK) {
        ANS_LOGE("Object_GetPropertyByName_Ref failed, status : %{public}d", status);
        return;
    }
    if (outRef == nullptr) {
        return;
    }
    env->Reference_IsUndefined(outRef, &isUndefined);
}

ani_status GetPropertyRef(ani_env *env, ani_object obj, const char *name, ani_boolean &isUndefined, ani_ref &outRef)
{
    ANS_LOGD("GetPropertyRef call");
    if (env == nullptr || obj == nullptr || name == nullptr) {
        ANS_LOGE("GetPropertyRef fail, has nullptr");
        return ANI_INVALID_ARGS;
    }
    ANS_LOGD("GetPropertyRef: %{public}s", name);
    ani_status status = env->Object_GetPropertyByName_Ref(obj, name, &outRef);
    if (status != ANI_OK) {
        ANS_LOGE("Failed to get property '%{public}s', status: %{public}d", name, status);
        return status;
    }
    if (outRef == nullptr) {
        ANS_LOGE("get Ref fialed, outRef is nullptr");
        return ANI_ERROR;
    }
    status = env->Reference_IsUndefined(outRef, &isUndefined);
    if (status != ANI_OK) {
        ANS_LOGE("Failed to check undefined for '%{public}s', status: %{public}d", name, status);
    }
    ANS_LOGD("GetPropertyRef end");
    return status;
}

ani_status GetPropertyStringArray(ani_env *env, ani_object param, const char *name,
    std::vector<std::string> &res, const uint32_t maxLen)
{
    if (env == nullptr || param == nullptr || name == nullptr) {
        ANS_LOGE("GetPropertyStringArray fail, has nullptr");
        return ANI_INVALID_ARGS;
    }
    ANS_LOGD("GetPropertyStringArray: %{public}s", name);
    ani_ref arrayObj = nullptr;
    ani_status status;
    ani_int length;
    ani_boolean isUndefined = ANI_FALSE;
    if ((status = GetPropertyRef(env, param, name, isUndefined, arrayObj)) != ANI_OK || isUndefined == ANI_TRUE) {
        ANS_LOGE("GetPropertyRef fail, status = %{public}d, isUndefind = %{public}d", status, isUndefined);
        return ANI_INVALID_ARGS;
    }
    status = env->Object_GetPropertyByName_Int(static_cast<ani_object>(arrayObj), "length", &length);
    if (status != ANI_OK) {
        ANS_LOGE("status : %{public}d", status);
        return status;
    }
    if (maxLen > 0 && length > static_cast<ani_int>(maxLen)) {
        length = static_cast<ani_int>(maxLen);
    }
    std::string str = "";
    for (int32_t i = 0; i < length; i++) {
        ani_ref stringEntryRef;
        status = env->Object_CallMethodByName_Ref(static_cast<ani_object>(arrayObj),
            "$_get", "i:Y", &stringEntryRef, i);
        if (status != ANI_OK) {
            ANS_LOGE("status : %{public}d, index: %{public}d", status, i);
            return status;
        }
        status = GetStringByAniString(env, static_cast<ani_string>(stringEntryRef), str);
        if (status != ANI_OK) {
            ANS_LOGE("GetStdString failed, index: %{public}d", i);
            return status;
        }
        res.push_back(str);
    }
    return status;
}

ani_status GetPropertyEnumItemArray(ani_env *env, ani_object param, const char *name,
    ani_boolean &isUndefined, std::vector<ani_enum_item> &res)
{
    if (env == nullptr || param == nullptr || name == nullptr) {
        ANS_LOGE("GetPropertyEnumItemArray fail, has nullptr");
        return ANI_INVALID_ARGS;
    }
    ANS_LOGD("GetPropertyEnumItemArray: %{public}s", name);
    ani_ref arrayObj = nullptr;
    ani_status status;
    ani_int length;
    if ((status = GetPropertyRef(env, param, name, isUndefined, arrayObj)) != ANI_OK) {
        ANS_LOGE("GetPropertyRef fail, status = %{public}d, isUndefind = %{public}d", status, isUndefined);
        return ANI_INVALID_ARGS;
    }
    if (isUndefined == ANI_TRUE) {
        return ANI_OK;
    }
    status = env->Object_GetPropertyByName_Int(static_cast<ani_object>(arrayObj), "length", &length);
    if (status != ANI_OK) {
        ANS_LOGE("status: %{public}d", status);
        return status;
    }
    for (int i = 0; i < static_cast<int>(length); i++) {
        ani_ref enumItemRef;
        status = env->Object_CallMethodByName_Ref(static_cast<ani_object>(arrayObj),
            "$_get", "i:Y", &enumItemRef, (ani_int)i);
        if (status != ANI_OK) {
            ANS_LOGE("status: %{public}d, index: %{public}d", status, i);
            return status;
        }
        res.push_back(static_cast<ani_enum_item>(enumItemRef));
    }
    return ANI_OK;
}

ani_status GetPropertyNumberArray(ani_env *env, ani_object param, const char *name,
    ani_boolean &isUndefined, std::vector<int64_t> &res)
{
    ANS_LOGD("GetPropertyNumberArray enter");
    ani_ref arrayObj = nullptr;
    ani_status status;
    ani_int length;
    if ((status = GetPropertyRef(env, param, name, isUndefined, arrayObj)) != ANI_OK || isUndefined == ANI_TRUE) {
        return ANI_INVALID_ARGS;
    }

    status = env->Object_GetPropertyByName_Int(static_cast<ani_object>(arrayObj), "length", &length);
    if (status != ANI_OK) {
        ANS_LOGE("status : %{public}d", status);
        return status;
    }

    for (int32_t i = 0; i < length; i++) {
        ani_ref numEntryRef;
        status = env->Object_CallMethodByName_Ref(static_cast<ani_object>(arrayObj),
            "$_get", "i:Y", &numEntryRef, i);
        if (status != ANI_OK) {
            ANS_LOGE("status : %{public}d, index: %{public}d", status, i);
            return status;
        }
        ani_double doubleValue = 0.0;
        status = env->Object_CallMethodByName_Double(static_cast<ani_object>(numEntryRef), "toDouble",
            ":d", &doubleValue);
        if (status != ANI_OK) {
            ANS_LOGE("Object_CallMethodByName_Double uid fail, status: %{public}d", status);
            return status;
        }
        res.push_back(static_cast<int64_t>(doubleValue));
    }
    ANS_LOGD("GetPropertyNumberArray leave");
    return status;
}

ani_status GetPropertyLongArray(ani_env *env, ani_object param, const char *name,
    ani_boolean &isUndefined, std::vector<int64_t> &res)
{
    ANS_LOGD("GetPropertyLongArray enter");
    ani_ref arrayObj = nullptr;
    ani_status status;
    ani_int length;
    if ((status = GetPropertyRef(env, param, name, isUndefined, arrayObj)) != ANI_OK || isUndefined == ANI_TRUE) {
        ANS_LOGE("GetPropertyRef fail. status : %{public}d", status);
        return ANI_INVALID_ARGS;
    }

    status = env->Object_GetPropertyByName_Int(static_cast<ani_object>(arrayObj), "length", &length);
    if (status != ANI_OK) {
        ANS_LOGE("Object_GetPropertyByName_Int status : %{public}d", status);
        return status;
    }

    for (int32_t i = 0; i < length; i++) {
        ani_ref numEntryRef;
        status = env->Object_CallMethodByName_Ref(static_cast<ani_object>(arrayObj),
            "$_get", "i:Y", &numEntryRef, i);
        if (status != ANI_OK) {
            ANS_LOGE("Object_CallMethodByName_Ref status : %{public}d, index: %{public}d", status, i);
            return status;
        }
        ani_long longValue = 0.0;
        status = env->Object_CallMethodByName_Long(static_cast<ani_object>(numEntryRef), "toLong",
            ":l", &longValue);
        if (status != ANI_OK) {
            ANS_LOGE("Object_CallMethodByName_Long uid fail, status: %{public}d", status);
            return status;
        }
        res.push_back(static_cast<int64_t>(longValue));
    }
    ANS_LOGD("GetPropertyLongArray leave");
    return status;
}

ani_object GetAniStringArrayByVectorString(ani_env *env, std::vector<std::string> strs)
{
    if (env == nullptr) {
        ANS_LOGE("GetAniStringArrayByVectorString fail, env is nullptr");
        return nullptr;
    }
    int length = strs.size();
    ani_array arrayObj = newArrayClass(env, length);
    if (arrayObj == nullptr) {
        return nullptr;
    }
    ani_size i = 0;
    for (auto &str : strs) {
        ani_string aniStr;
        if ((GetAniStringByString(env, str, aniStr) != ANI_OK) || aniStr == nullptr) {
            ANS_LOGE("GetAniStringByString faild");
            return nullptr;
        }
        ani_status status = env->Array_Set(arrayObj, i, aniStr);
        if (status != ANI_OK) {
            ANS_LOGE("Array_Set failed %{public}d", status);
            return nullptr;
        }
        i++;
    }
    return arrayObj;
}

bool GetAniStringArrayByVectorStringV2(ani_env *env, std::vector<std::string> strs, ani_object& aniArray)
{
    ANS_LOGD("GetAniStringArrayByVectorStringV2 call");
    if (env == nullptr) {
        ANS_LOGE("GetAniStringArrayByVectorStringV2 failed, has nullptr");
        return false;
    }
    ani_class cls = nullptr;
    ani_status status = env->FindClass("std.core.String", &cls);
    if (status != ANI_OK) {
        ANS_LOGE("FindClass failed. status : %{public}d", status);
        return false;
    }
    ani_array array = nullptr;
    size_t size = strs.size();
    ani_object nullObj = GetNullObject(env);
    status = env->Array_New(size, nullObj, &array);
    if (status != ANI_OK) {
        ANS_LOGE("Array_New failed. status : %{public}d", status);
        return false;
    }
    int32_t index = 0;
    for (auto& str : strs) {
        ani_string aniStr;
        if ((GetAniStringByString(env, str, aniStr) != ANI_OK) || aniStr == nullptr) {
            ANS_LOGE("GetAniStringByString failed");
            return false;
        }
        status = env->Array_Set(array, index, aniStr);
        if (status != ANI_OK) {
            ANS_LOGE("Array_Set Failed. index = %{public}d, status = %{public}d", index, status);
            return false;
        }
        index++;
    }
    ANS_LOGD("GetAniStringArrayByVectorStringV2 end");
    aniArray = array;
    return true;
}

bool SetFieldString(ani_env *env, ani_class cls, ani_object &object,
    const std::string fieldName, const std::string value)
{
    if (env == nullptr || cls == nullptr || object == nullptr || fieldName.empty()) {
        ANS_LOGE("SetFieldString fail, has nullptr or fieldName is empty");
        return false;
    }
    ani_field field = nullptr;
    ani_string string = nullptr;
    ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field);
    ANS_LOGD("SetFieldString fieldName : %{public}s", fieldName.c_str());
    if (status != ANI_OK || field == nullptr) {
        ANS_LOGE("SetFieldString status : %{public}d", status);
        return false;
    }
    if (value.empty()) {
        ani_ref nullRef = nullptr;
        if ((status = env->GetNull(&nullRef)) != ANI_OK) {
            ANS_LOGE("SetFieldString GetNull fail status : %{public}d", status);
            return false;
        }
        if ((status = env->Object_SetField_Ref(object, field, nullRef)) != ANI_OK) {
            ANS_LOGE("SetFieldString Object_SetField_Ref fail status : %{public}d", status);
            return false;
        }
        return true;
    }
    if ((status = env->String_NewUTF8(value.c_str(), value.size(), &string)) != ANI_OK) {
        ANS_LOGE("SetFieldString String_NewUTF8 fail status : %{public}d", status);
        return false;
    }
    if ((status = env->Object_SetField_Ref(object, field, string)) != ANI_OK) {
        ANS_LOGE("SetFieldString Object_SetField_Ref fail status : %{public}d", status);
        return false;
    }
    return true;
}

bool SetFieldInt(ani_env *env, ani_class cls, ani_object &object,
    const std::string fieldName, const int32_t value)
{
    if (env == nullptr || cls == nullptr || object == nullptr || fieldName.empty()) {
        ANS_LOGE("SetFieldInt fail. has nullptr or fieldName is empty");
        return false;
    }
    ani_field field = nullptr;
    ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field);
    ANS_LOGD("SetFieldInt fieldName : %{public}s", fieldName.c_str());
    if (status != ANI_OK || field == nullptr) {
        ANS_LOGE("Class_FindField fail. status : %{public}d", status);
        return false;
    }
    if ((status = env->Object_SetField_Int(object, field, static_cast<ani_int>(value))) != ANI_OK) {
        ANS_LOGE("Object_SetField_Int fail. status : %{public}d", status);
        return false;
    }
    return true;
}

bool SetFieldLong(ani_env *env, ani_class cls, ani_object &object,
    const std::string fieldName, const int64_t value)
{
    if (env == nullptr || cls == nullptr || object == nullptr || fieldName.empty()) {
        ANS_LOGE("SetFieldLong fail. has nullptr or fieldName is empty");
        return false;
    }
    ani_field field = nullptr;
    ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field);
    ANS_LOGD("SetFieldLong fieldName : %{public}s", fieldName.c_str());
    if (status != ANI_OK || field == nullptr) {
        ANS_LOGE("Class_FindField fail. status : %{public}d", status);
        return false;
    }
    if ((status = env->Object_SetField_Long(object, field, static_cast<ani_long>(value))) != ANI_OK) {
        ANS_LOGE("Object_SetField_Long fail. status : %{public}d", status);
        return false;
    }
    return true;
}

bool SetOptionalFieldBoolean(ani_env *env, ani_class cls, ani_object &object,
    const std::string fieldName, bool value)
{
    if (env == nullptr || cls == nullptr || object == nullptr || fieldName.empty()) {
        ANS_LOGE("SetOptionalFieldBoolean fail, has nullptr or fieldName is empty");
        return false;
    }
    ani_field field = nullptr;
    ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field);
    if (status != ANI_OK || field == nullptr) {
        ANS_LOGE("Class_FindField failed or null field, status=%{public}d, fieldName=%{public}s",
            status, fieldName.c_str());
        return false;
    }
    ani_object boolObj = CreateBoolean(env, BoolToAniBoolean(value));
    if (boolObj == nullptr) {
        return false;
    }
    status = env->Object_SetField_Boolean(object, field, static_cast<ani_boolean>(value));
    if (status != ANI_OK) {
        ANS_LOGE("Object_SetField_Boolean failed, status=%{public}d, fieldName=%{public}s",
            status, fieldName.c_str());
        return false;
    }
    return true;
}

bool SetOptionalFieldDouble(ani_env *env, ani_class cls, ani_object &object,
    const std::string fieldName, double value)
{
    if (env == nullptr || cls == nullptr || object == nullptr || fieldName.empty()) {
        ANS_LOGE("SetOptionalFieldDouble fail, has nullptr or fieldName is empty");
        return false;
    }
    ani_field field = nullptr;
    ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field);
    if (status != ANI_OK || field == nullptr) {
        ANS_LOGE("Class_FindField failed or null field, status=%{public}d, fieldName=%{public}s",
            status, fieldName.c_str());
        return false;
    }
    ani_object doubleObj = CreateDouble(env, value);
    if (doubleObj == nullptr) {
        return false;
    }
    status = env->Object_SetField_Ref(object, field, doubleObj);
    if (status != ANI_OK) {
        ANS_LOGE("Object_SetField_Ref failed, status=%{public}d, fieldName=%{public}s",
            status, fieldName.c_str());
        return false;
    }
    return true;
}

ani_object CreateBoolean(ani_env *env, bool value)
{
    ani_class persion_cls;
    ani_status status = ANI_ERROR;
    if ((status = env->FindClass(CLASSNAME_BOOLEAN, &persion_cls)) != ANI_OK) {
        ANS_LOGE("status : %{public}d", status);
        return nullptr;
    }
    ani_method personInfoCtor;
    if ((status = env->Class_FindMethod(persion_cls, "<ctor>", "z:", &personInfoCtor)) != ANI_OK) {
        ANS_LOGE("Class_FindMethod fail, status : %{public}d", status);
        return nullptr;
    }
    ani_object personInfoObj;
    if ((status = env->Object_New(persion_cls, personInfoCtor, &personInfoObj, value ? ANI_TRUE : ANI_FALSE))
        != ANI_OK) {
        ANS_LOGE("status : %{public}d", status);
        return nullptr;
    }
    return personInfoObj;
}

ani_object CreateLong(ani_env *env, int64_t value)
{
    if (env == nullptr) {
        ANS_LOGE("CreateLong fail, env is nullptr");
        return nullptr;
    }
    ani_class longCls;
    ani_status status = ANI_ERROR;
    if ((status = env->FindClass(CLASSNAME_LONG, &longCls)) != ANI_OK) {
        ANS_LOGE("FindClass fail, status : %{public}d", status);
        return nullptr;
    }
    ani_method longCtor;
    if ((status = env->Class_FindMethod(longCls, "<ctor>", "l:", &longCtor)) != ANI_OK) {
        ANS_LOGE("Class_FindMethod fail, status : %{public}d", status);
        return nullptr;
    }
    ani_object longObj;
    if ((status = env->Object_New(longCls, longCtor, &longObj, value)) != ANI_OK) {
        ANS_LOGE("Object_New fail, status : %{public}d", status);
        return nullptr;
    }
    return longObj;
}

ani_object CreateDouble(ani_env *env, double value)
{
    if (env == nullptr) {
        ANS_LOGE("CreateDouble fail, env is nullptr");
        return nullptr;
    }
    ani_class doubleCls;
    ani_status status = ANI_ERROR;
    if ((status = env->FindClass(CLASSNAME_DOUBLE, &doubleCls)) != ANI_OK) {
        ANS_LOGE("status : %{public}d", status);
        return nullptr;
    }
    ani_method doubleCtor;
    if ((status = env->Class_FindMethod(doubleCls, "<ctor>", "d:", &doubleCtor)) != ANI_OK) {
        ANS_LOGE("Class_FindMethod fail, status : %{public}d", status);
        return nullptr;
    }
    ani_object doubleObj;
    if ((status = env->Object_New(doubleCls, doubleCtor, &doubleObj, static_cast<ani_double>(value))) != ANI_OK) {
        ANS_LOGE("status : %{public}d", status);
        return nullptr;
    }
    return doubleObj;
}

ani_array newArrayClass(ani_env *env, int length)
{
    ANS_LOGD("newArrayClass call");
    if (env == nullptr || length < 0) {
        ANS_LOGE("newArrayClass fail, env is nullptr or length is less than zero");
        return nullptr;
    }
    ani_class arrayCls = nullptr;
    if (ANI_OK != env->FindClass("std.core.Array", &arrayCls)) {
        ANS_LOGE("FindClass std.core.Array Failed");
        return nullptr;
    }
    ani_method arrayCtor;
    if (ANI_OK != env->Class_FindMethod(arrayCls, "<ctor>", "i:", &arrayCtor)) {
        ANS_LOGE("Class_FindMethod <ctor> Failed");
        return nullptr;
    }
    ani_object arrayObj = nullptr;
    if (env->Object_New(arrayCls, arrayCtor, &arrayObj, length) != ANI_OK) {
        ANS_LOGE("Object_New Array Faild");
        return nullptr;
    }
    ANS_LOGD("newArrayClass end");
    return static_cast<ani_array>(arrayObj);
}

ani_object ConvertArrayLongToAniObj(ani_env *env, const std::vector<std::int64_t> values)
{
    if (env == nullptr) {
        ANS_LOGE("ConvertArrayLongToAniObj fail, env is nullptr");
        return nullptr;
    }
    ani_array arrayObj = newArrayClass(env, values.size());
    if (arrayObj == nullptr) {
        return nullptr;
    }
    ani_size i = 0;
    for (auto value : values) {
        ani_object longObj = CreateLong(env, value);
        if (longObj == nullptr) {
            ANS_LOGE("null intObj");
            return nullptr;
        }
        ani_status status = env->Array_Set(arrayObj, i, longObj);
        if (status != ANI_OK) {
            ANS_LOGE("status : %{public}d", status);
            return nullptr;
        }
        i++;
    }
    return arrayObj;
}

bool SetOptionalFieldArrayLong(ani_env *env, ani_class cls, ani_object &object, const std::string fieldName,
    const std::vector<std::int64_t> values)
{
    if (env == nullptr || cls == nullptr || object == nullptr || fieldName.empty()) {
        ANS_LOGE("SetOptionalFieldArrayLong fail, has nullptr or fieldName is empty");
        return false;
    }
    ani_field field = nullptr;
    ani_status status = env->Class_FindField(cls, fieldName.c_str(), &field);
    if (status != ANI_OK) {
        ANS_LOGE("status : %{public}d", status);
        return false;
    }
    ani_object arrayObj = ConvertArrayLongToAniObj(env, values);
    if (arrayObj == nullptr) {
        ANS_LOGE("arrayObj is nullptr.");
        return false;
    }
    status = env->Object_SetField_Ref(object, field, arrayObj);
    if (status != ANI_OK) {
        ANS_LOGE("status : %{public}d", status);
        return false;
    }
    return true;
}

bool CreateClassObjByClassName(ani_env *env, const char *className, ani_class &cls, ani_object &outAniObj)
{
    if (env == nullptr || className == nullptr) {
        ANS_LOGE("CreateClassObjByClassName fail, has nullptr");
        return false;
    }
    if (env->FindClass(className, &cls) != ANI_OK) {
        ANS_LOGE("FindClass fail");
        return false;
    }
    ani_method ctor;
    if (env->Class_FindMethod(cls, "<ctor>", nullptr, &ctor) != ANI_OK) {
        ANS_LOGE("FindMethod fail");
        return false;
    }
    outAniObj = {};
    if (env->Object_New(cls, ctor, &outAniObj) != ANI_OK) {
        ANS_LOGE("Object_New fail");
        return false;
    }
    return true;
}

bool CreateDate(ani_env *env, int64_t time, ani_object &outObj)
{
    if (env == nullptr) {
        ANS_LOGE("CreateDate fail, env is nullptr");
        return false;
    }
    ani_class cls;
    ani_status status;
    if (ANI_OK != (status = env->FindClass("std.core.Date", &cls))) {
        ANS_LOGE("error. not find class name 'std.core.Date'. status %{public}d", status);
        return false;
    }
    ani_method ctor;
    if ((status = env->Class_FindMethod(cls, "<ctor>", ":", &ctor)) != ANI_OK) {
        ANS_LOGE("error. not find method name '<ctor>'. status %{public}d", status);
        return false;
    }
    if ((status = env->Object_New(cls, ctor, &outObj)) != ANI_OK) {
        ANS_LOGE("Object_New faild. status %{public}d", status);
        return false;
    }
    ani_long msObj = 0;
    if ((status = env->Object_CallMethodByName_Long(outObj, "setTime", "l:l", &msObj, time))
        != ANI_OK) {
        ANS_LOGE("Object_CallMethodByName_Long setDate faild. status %{public}d", status);
        return false;
    }
    return true;
}

bool GetDateByObject(ani_env *env, ani_object timeObj, int64_t &time)
{
    ANS_LOGD("GetDateByObject call");
    if (env == nullptr || timeObj == nullptr) {
        ANS_LOGE("GetDateByObject fail, env or timeObj is nullptr");
        return false;
    }

    ani_status status;
    ani_long timeMsObj = 0;
    if ((status = env->Object_CallMethodByName_Long(timeObj, "getTime", ":l", &timeMsObj)) != ANI_OK) {
        ANS_LOGD("Object_CallMethodByName_Long faild. status %{public}d", status);
        return false;
    }
    time = static_cast<int64_t>(timeMsObj);
    ANS_LOGD("GetDateByObject end");
    return true;
}

ani_object CreateInt(ani_env *env, int32_t value)
{
    ani_class cls;
    ani_status status = ANI_ERROR;
    if ((status = env->FindClass(CLASSNAME_INT, &cls)) != ANI_OK) {
        ANS_LOGE("FindClass '%{public}s' faild. status %{public}d", CLASSNAME_INT, status);
        return nullptr;
    }
    ani_method ctor;
    if ((status = env->Class_FindMethod(cls, "<ctor>", "i:", &ctor)) != ANI_OK) {
        ANS_LOGE("Class_FindMethod '%{public}s' faild. status %{public}d", CLASSNAME_INT, status);
        return nullptr;
    }
    ani_object outObj;
    if ((status = env->Object_New(cls, ctor, &outObj, value)) != ANI_OK) {
        ANS_LOGE("Object_New '%{public}s' faild. status %{public}d", CLASSNAME_INT, status);
        return nullptr;
    }
    return outObj;
}

bool SetPropertyOptionalByBoolean(ani_env *env, ani_object &object, const char *name, bool value)
{
    ANS_LOGD("enter SetPropertyOptionalByBoolean");
    if (env == nullptr || object == nullptr || name == nullptr) {
        ANS_LOGE("The parameter is invalid.");
        return false;
    }
    ani_ref boolObj = CreateBoolean(env, value);
    if (boolObj == nullptr) {
        ANS_LOGE("CreateBoolean faild");
        return false;
    }
    return SetPropertyByRef(env, object, name, boolObj);
}

bool SetPropertyOptionalByDouble(ani_env *env, ani_object &object, const char *name, double value)
{
    ANS_LOGD("enter SetPropertyOptionalByDouble");
    if (env == nullptr || object == nullptr || name == nullptr) {
        ANS_LOGE("The parameter is invalid.");
        return false;
    }
    ani_ref doubleObj = CreateDouble(env, value);
    if (doubleObj == nullptr) {
        ANS_LOGE("CreateDouble faild");
        return false;
    }
    return SetPropertyByRef(env, object, name, doubleObj);
}

bool SetPropertyValueDouble(ani_env *env, ani_object param, const char *name, double value)
{
    ANS_LOGD("enter SetPropertyValueDouble");
    if (env == nullptr || param == nullptr || name == nullptr) {
        ANS_LOGE("SetPropertyValueDouble fail, has nullptr");
        return false;
    }

    ani_status status = ANI_ERROR;
    if ((status = env->Object_SetPropertyByName_Double(param, name, value)) != ANI_OK) {
        ANS_LOGE("Object_SetPropertyByName_Double, status: %{public}d", status);
        return false;
    }
    return true;
}

bool SetPropertyOptionalByLong(ani_env *env, ani_object &object, const char *name, int64_t value)
{
    ANS_LOGD("enter SetPropertyOptionalByLong");
    if (env == nullptr || object == nullptr || name == nullptr) {
        ANS_LOGE("The parameter is invalid.");
        return false;
    }
    ani_ref longObj = CreateLong(env, value);
    if (longObj == nullptr) {
        ANS_LOGE("CreateLong faild");
        return false;
    }
    return SetPropertyByRef(env, object, name, longObj);
}

bool SetPropertyOptionalByString(ani_env *env, ani_object &object, const char *name, const std::string value)
{
    ANS_LOGD("enter SetPropertyOptionalByString");
    if (env == nullptr || object == nullptr || name == nullptr) {
        ANS_LOGE("The parameter is invalid.");
        return false;
    }
    ani_string stringObj;
    ani_status status = ANI_OK;
    if ((status = GetAniStringByString(env, value, stringObj)) != ANI_OK) {
        ANS_LOGE("GetAniStringByString faild. status %{public}d", status);
        return false;
    }
    if (stringObj == nullptr) {
        ANS_LOGE("CreateString faild");
        return false;
    }
    return SetPropertyByRef(env, object, name, static_cast<ani_ref>(stringObj));
}

bool SetPropertyOptionalByInt(ani_env *env, ani_object &object, const char *name, int32_t value)
{
    ANS_LOGD("enter SetPropertyOptionalByInt");
    if (env == nullptr || object == nullptr || name == nullptr) {
        ANS_LOGE("The parameter is invalid.");
        return false;
    }
    ani_ref IntObj = CreateInt(env, value);
    if (IntObj == nullptr) {
        ANS_LOGE("CreateInt faild");
        return false;
    }
    return SetPropertyByRef(env, object, name, IntObj);
}

bool SetPropertyByRef(ani_env *env, ani_object &object, const char *name, ani_ref value)
{
    ANS_LOGD("enter SetPropertyByRef");
    ani_status status = ANI_OK;
    if (env == nullptr || object == nullptr || name == nullptr || value == nullptr) {
        ANS_LOGE("The parameter is invalid.");
        return false;
    }
    if ((status = env->Object_SetPropertyByName_Ref(object, name, value)) != ANI_OK) {
        ANS_LOGE("set '%{public}s' faild. status %{public}d", name, status);
        return false;
    }
    return true;
}

void ParseRecord(ani_env *env, ani_object recordRef, std::map<std::string, ani_ref>& recordResult)
{
    if (env == nullptr) {
        return;
    }
    ani_ref keys {};
    if (env->Object_CallMethodByName_Ref(recordRef, "keys",
        ":C{std.core.IterableIterator}", &keys) != ANI_OK) {
        ANS_LOGE("call method keys() failed.");
        return;
    }
    ani_boolean done = ANI_FALSE;
    while (!done) {
        ani_ref next {};
        if (env->Object_CallMethodByName_Ref(static_cast<ani_object>(keys), "next", nullptr, &next) != ANI_OK) {
            ANS_LOGE("call method next() failed.");
            break;
        }
        if (env->Object_GetFieldByName_Boolean(static_cast<ani_object>(next), "done", &done) != ANI_OK) {
            ANS_LOGE("get field done failed.");
            break;
        }
        if (done) {
            break;
        }
        ani_ref keyRef {};
        if (env->Object_GetFieldByName_Ref(static_cast<ani_object>(next), "value", &keyRef) != ANI_OK) {
            ANS_LOGE("get field value failed.");
            break;
        }
        ani_ref valueRef {};
        if (env->Object_CallMethodByName_Ref(static_cast<ani_object>(recordRef),
            "$_get", nullptr, &valueRef, keyRef) != ANI_OK) {
            ANS_LOGE("call method $_get failed.");
            break;
        }
        std::string keyStr;
        GetStringByAniString(env, static_cast<ani_string>(keyRef), keyStr);
        recordResult[keyStr] = valueRef;
    }
}

ani_object CreateAniUndefined(ani_env *env)
{
    if (env == nullptr) {
        ANS_LOGE("CreateAniUndefined failed, env is nullptr");
        return nullptr;
    }
    ani_ref aniRef;
    ani_status status = env->GetUndefined(&aniRef);
    if (status != ANI_OK) {
        ANS_LOGE("GetUndefined failed, status: %{public}d", status);
        return nullptr;
    }
    return reinterpret_cast<ani_object>(aniRef);
}

ani_object CreateMapObject(ani_env *env, const std::string name, const char *signature)
{
    ani_class cls = nullptr;
    if (env->FindClass(name.c_str(), &cls) != ANI_OK) {
        ANS_LOGE("Failed to found %{public}s", name.c_str());
        return nullptr;
    }

    ani_method ctor;
    if (env->Class_FindMethod(cls, "<ctor>", signature, &ctor) != ANI_OK) {
        ANS_LOGE("Failed to get ctor %{public}s", name.c_str());
        return nullptr;
    }
    ani_object obj = {};
    ani_ref undefinedArgument;
    if (ANI_OK != env->GetUndefined(&undefinedArgument)) {
        ANS_LOGE("Failed to get undefined %{public}s", name.c_str());
        return nullptr;
    }
    if (env->Object_New(cls, ctor, &obj, undefinedArgument) != ANI_OK) {
        ANS_LOGE("Failed to create object %{public}s", name.c_str());
        return nullptr;
    }
    return obj;
}

ani_status GetMapIterator(ani_env *env, ani_object &mapObj, const char *method, ani_ref *it)
{
    ani_status status = env->Object_CallMethodByName_Ref(mapObj, method, nullptr, it);
    if (status != ANI_OK) {
        ANS_LOGD("Failed to get %{public}s iterator, status: %{public}d", method, status);
    }
    return status;
}

ani_status GetMapIteratorNext(ani_env *env, ani_ref &it, ani_ref *next)
{
    ani_status status = env->Object_CallMethodByName_Ref(reinterpret_cast<ani_object>(it), "next", nullptr, next);
    if (status != ANI_OK) {
        ANS_LOGD("Failed to get next, status: %{public}d", status);
    }
    return status;
}

ani_status GetMapIteratorStringValue(ani_env *env, ani_ref &next, std::string &str)
{
    ani_ref val;
    ani_status status = env->Object_GetFieldByName_Ref(reinterpret_cast<ani_object>(next), "value", &val);
    if (status != ANI_OK) {
        ANS_LOGD("Failed to get value, status: %{public}d", status);
    }
    status = GetStringByAniString(env, reinterpret_cast<ani_string>(val), str);
    if (status == ANI_OK && str.size() > STRUCTURED_TEXT_SIZE) {
        str.resize(STRUCTURED_TEXT_SIZE);
        ANS_LOGW("Structured text truncated to 512 bytes.");
    }
    return status;
}
 
ani_status GetMapByAniMap(ani_env *env, ani_object &mapObj,
    std::vector<std::pair<std::string, std::string>> &out)
{
    ani_status status = ANI_ERROR;
    ani_ref keys;
    ani_ref values;
    bool done = false;

    if (GetMapIterator(env, mapObj, "keys", &keys) != ANI_OK ||
        GetMapIterator(env, mapObj, "values", &values) != ANI_OK) {
        return ANI_ERROR;
    }

    while (!done) {
        ani_ref nextKey;
        ani_ref nextVal;
        ani_boolean done;

        if (GetMapIteratorNext(env, keys, &nextKey) != ANI_OK ||
            GetMapIteratorNext(env, values, &nextVal) != ANI_OK) {
            return ANI_ERROR;
        }

        if ((status = env->Object_GetFieldByName_Boolean(reinterpret_cast<ani_object>(nextKey), "done", &done))
            != ANI_OK) {
            ANS_LOGD("Failed to check iterator done, status: %{public}d", status);
            return ANI_ERROR;
        }
        if (done) {
            break;
        }

        std::string keyStr;
        std::string valStr;
        if (GetMapIteratorStringValue(env, nextKey, keyStr) != ANI_OK||
            GetMapIteratorStringValue(env, nextVal, valStr) != ANI_OK) {
            return ANI_ERROR;
        }
        out.emplace_back(keyStr, valStr);
    }

    return ANI_OK;
}
} // namespace NotificationSts
} // OHOS