/*
 * 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.
 */

import * as arkts from '@koalaui/libarkts';
import { GenSymGenerator } from '../../common/gensym-generator';
import {
    DecoratorNames,
    DECORATOR_TYPE_MAP,
    StateManagementTypes,
    ObservedNames,
    MonitorNames,
    TypeNames,
    NodeCacheNames,
    CustomComponentNames,
} from '../../common/predefines';
import { factory as UIFactory } from '../ui-factory';
import {
    canCastTypeFromValue,
    collectStateManagementTypeImport,
    generateThisBacking,
    getValueInAnnotation,
    hasDecorator,
    InitializeValueOptions,
    OptionalMemberInfo,
    PropertyOptionalFieldOptions,
    removeDecorator,
    findCachedMemoMetadata,
} from './utils';
import { optionsHasField } from '../utils';
import { addMemoAnnotation, findCanAddMemoFromTypeAnnotation } from '../../collectors/memo-collectors/utils';
import { annotation, isNumeric } from '../../common/arkts-utils';
import { PropertyFactoryCallTypeCache, PropertyValueCache } from '../memo-collect-cache';
import { MetaDataCollector } from '../../common/metadata-collector';
import { AstNodeCacheValueMetadata, NodeCacheFactory } from '../../common/node-cache';
import { CustomComponentInnerClassPropertyInfo } from 'collectors/ui-collectors/records';
import { PropertyPathNode, PropertyPathResult, resolvePropertyPath } from '../../common/path-resolvers';

const MONITOR_WILDCARD_SUFFIX = '.*';
const MONITOR_WILDCARD_MIN_VERSION = 26;
const MONITOR_WILDCARD_PROPERTY_NAME = 'enableWildcard';

export class factory {
    static createStateManagementFactoryGenericType(
        propertyValue: arkts.Expression | undefined, 
        propertyType: arkts.TypeNode | undefined,
        initializeValueOptions?: InitializeValueOptions 
    ): arkts.TypeNode | undefined {
        if (!propertyType) {
            return undefined;
        }
        if (!!initializeValueOptions?.canDefinitelyBeNonNull) {
            if (arkts.isETSUnionType(propertyType)) {
                propertyType.setTypes([...propertyType.types, arkts.factory.createETSUndefinedType()]);
                return propertyType;
            }
            return arkts.factory.createETSUnionType([propertyType, arkts.factory.createETSUndefinedType()]);
        }
        return propertyType;
    }

    /**
     * generate an substitution for optional expression ?., e.g. `{let _tmp = xxx; _tmp == null ? undefined : xxx}`.
     *
     * @param object item before ?..
     * @param key item after ?..
     * @param info optional member information
     */
    static createBlockStatementForOptionalExpression(
        object: arkts.Expression,
        key: string,
        info?: OptionalMemberInfo,
        alternateFn?: (id: string, key: string) => arkts.Expression
    ): arkts.Expression {
        let id = GenSymGenerator.getInstance().id(key);
        const alternate = !!alternateFn ? alternateFn(id, key) : this.generateConditionalAlternate(id, key, info);
        const statements: arkts.Statement[] = [
            UIFactory.generateLetVariableDecl(arkts.factory.createIdentifier(id), object),
            UIFactory.generateTernaryExpression(id, alternate),
        ];
        return arkts.factory.createBlockExpression(statements);
    }

    /**
     * generate an substitution for optional __options_has expression ?., e.g. `{let <id> = <object>; <id> == null ? undefined : <id>.__options_has_<key>}`.
     *
     * @param object item before ?..
     * @param key item after ?..
     * @param info optional member information
     */
    static createBlockStatementForOptionsHasMemberExpression(
        object: arkts.Expression,
        id: string,
        key: string
    ): arkts.Expression {
        const alternate = UIFactory.generateMemberExpression(arkts.factory.createIdentifier(id), optionsHasField(key));
        const statements: arkts.Statement[] = [
            UIFactory.generateLetVariableDecl(arkts.factory.createIdentifier(id), object),
            UIFactory.generateTernaryExpression(id, alternate),
        ];
        return arkts.factory.createBlockExpression(statements);
    }

    static generateConditionalAlternate(testLeft: string, key: string, info?: OptionalMemberInfo): arkts.Expression {
        const leftIdent: arkts.Identifier = arkts.factory.createIdentifier(testLeft);
        const alternate: arkts.MemberExpression = UIFactory.generateMemberExpression(
            info?.isNonNull ? arkts.factory.createTSNonNullExpression(leftIdent) : leftIdent,
            info?.isNumeric ? '$_get' : key
        );
        return info?.isCall
            ? arkts.factory.createCallExpression(alternate, [], undefined, false, false)
            : info?.isNumeric
              ? arkts.factory.createCallExpression(alternate, [
                    arkts.factory.createNumberLiteral(Number(key)),
                ], undefined, false, false)
              : alternate;
    }

    /**
     * generate an substitution for two optional expression ?., e.g. a?.b?.c.
     *
     * @param node entry wrapper class declaration node.
     */
    static createDoubleBlockStatementForOptionalExpression(
        object: arkts.Expression,
        key1: string,
        key2: string
    ): arkts.Expression {
        let id = GenSymGenerator.getInstance().id(key1);
        let initial: arkts.Expression = factory.createBlockStatementForOptionalExpression(object, key1);
        const alternate = this.generateConditionalAlternate(id, key2);
        const statements: arkts.Statement[] = [
            UIFactory.generateLetVariableDecl(arkts.factory.createIdentifier(id), initial),
            UIFactory.generateTernaryExpression(id, alternate),
        ];
        return arkts.factory.createBlockExpression(statements);
    }

    /**
     * generate an memberExpression with nonNull or optional, e.g. object.property, object?.property or object!.property
     *
     * @param object item before point.
     * @param property item after point.
     */
    static createNonNullOrOptionalMemberExpression(
        object: string,
        property: string,
        optional: boolean,
        nonNull: boolean
    ): arkts.Expression {
        const objectNode: arkts.Identifier = arkts.factory.createIdentifier(object);
        return arkts.factory.createMemberExpression(
            nonNull ? arkts.factory.createTSNonNullExpression(objectNode) : objectNode,
            arkts.factory.createIdentifier(property),
            arkts.Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS,
            false,
            optional
        );
    }

    /*
     * create `(<params>)<typeParams>: <returnType> => { <bodyStatementsList> }`.
     */
    static createArrowFunctionWithParamsAndBody(
        typeParams: arkts.TSTypeParameterDeclaration | undefined,
        params: arkts.Expression[] | undefined,
        returnType: arkts.TypeNode | undefined,
        hasReceiver: boolean,
        bodyStatementsList: arkts.Statement[],
        hasReturn?: boolean
    ): arkts.ArrowFunctionExpression {
        let flag = arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_ARROW;
        if (hasReturn) {
            flag |= arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_HAS_RETURN;
        }
        return arkts.factory.createArrowFunctionExpression(
            arkts.factory.createScriptFunction(
                arkts.BlockStatement.createBlockStatement(bodyStatementsList),
                typeParams, params ? params : [], returnType, hasReceiver,
                flag,
                arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_NONE,
                undefined,
                undefined
            )
        );
    }

    /*
     * create @Watch callback, e.g. (propertyName: string): void => {this.<callbackName>(propertyName)}.
     */
    static createWatchCallback(callbackName: string): arkts.ArrowFunctionExpression {
        return factory.createArrowFunctionWithParamsAndBody(
            undefined,
            [
                arkts.factory.createETSParameterExpression(
                    arkts.factory.createIdentifier('_', UIFactory.createTypeReferenceFromString('string')),
                    false,
                    undefined
                ),
            ],
            arkts.factory.createETSPrimitiveType(arkts.Es2pandaPrimitiveType.PRIMITIVE_TYPE_VOID),
            false,
            [
                arkts.factory.createExpressionStatement(
                    arkts.factory.createCallExpression(generateThisBacking(callbackName), [
                        arkts.factory.createIdentifier('_'),
                    ], undefined, false, false)
                ),
            ]
        );
    }

    /*
     * create `initializers!.<newName>!.<getOrSet>(<args>)`.
     */
    static createBackingGetOrSetCall(
        newName: string,
        getOrSet: string,
        args: arkts.Expression[]
    ): arkts.CallExpression {
        return arkts.factory.createCallExpression(
            arkts.factory.createMemberExpression(
                arkts.factory.createTSNonNullExpression(
                    factory.createNonNullOrOptionalMemberExpression('initializers', newName, false, true)
                ),
                arkts.factory.createIdentifier(getOrSet),
                arkts.Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS,
                false,
                false
            ),
            args,
            undefined,
            false,
            false
        );
    }

    /*
     * create `new <className><typeAnnotation>(<args>)`.
     */
    static createNewDecoratedInstantiate(
        className: string,
        typeAnnotation: arkts.TypeNode | undefined,
        args: arkts.Expression[] | undefined
    ): arkts.ETSNewClassInstanceExpression {
        return arkts.factory.createETSNewClassInstanceExpression(
            arkts.factory.createETSTypeReference(
                arkts.factory.createETSTypeReferencePart(
                    arkts.factory.createIdentifier(className),
                    arkts.factory.createTSTypeParameterInstantiation(typeAnnotation ? [typeAnnotation.clone()] : [])
                )
            ),
            args?.length ? args : []
        );
    }

    /*
     * create `StateMgmtFactory.<makeType><typeArguments>(this, ...<args>);`.
     */
    static generateStateMgmtFactoryCall(
        makeType: StateManagementTypes,
        typeArguments: arkts.TypeNode | undefined,
        args: arkts.Expression[],
        argsContainsThis: boolean,
        memoMetadata?: AstNodeCacheValueMetadata
    ): arkts.CallExpression {
        collectStateManagementTypeImport(StateManagementTypes.STATE_MANAGEMENT_FACTORY);
        if (!!typeArguments && !!memoMetadata) {
            PropertyFactoryCallTypeCache.getInstance().collect({ node: typeArguments, metadata: memoMetadata });
        }
        return arkts.factory.createCallExpression(
            UIFactory.generateMemberExpression(
                arkts.factory.createIdentifier(StateManagementTypes.STATE_MANAGEMENT_FACTORY),
                makeType
            ),
            [...(argsContainsThis ? [arkts.factory.createThisExpression()] : []), ...args],
            typeArguments ? arkts.factory.createTSTypeParameterInstantiation([typeArguments]) : undefined,
            false,
            false
        );
    }

    /*
     * create if statement in __updateStruct method.
     */
    static createIfInUpdateStruct(
        originalName: string,
        member: arkts.Expression,
        args: arkts.Expression[]
    ): arkts.IfStatement {
        const initializers = arkts.factory.createIdentifier(CustomComponentNames.COMPONENT_INITIALIZERS_NAME);
        const binaryItem = factory.createBlockStatementForOptionalExpression(
            initializers,
            optionsHasField(originalName)
        );
        return arkts.factory.createIfStatement(
            binaryItem,
            arkts.factory.createBlockStatement([
                arkts.factory.createExpressionStatement(arkts.factory.createCallExpression(member, args, undefined, false, false)),
            ])
        );
    }

    /*
     * create `initializers!.<originalName> as <type>`.
     */
    static generateDefiniteInitializers(type: arkts.TypeNode | undefined, originalName: string): arkts.Expression {
        return arkts.factory.createTSAsExpression(
            factory.createNonNullOrOptionalMemberExpression(
                CustomComponentNames.COMPONENT_INITIALIZERS_NAME,
                originalName,
                false,
                true
            ),
            type ?? undefined,
            false
        );
    }

    static addWatchFunc(args: arkts.Expression[], property: arkts.ClassProperty): void {
        const watchStr: string | undefined = getValueInAnnotation(property, DecoratorNames.WATCH);
        if (watchStr) {
            args.push(factory.createWatchCallback(watchStr));
        }
    }

    static addWatchFuncProperty(propName: string, property: arkts.ClassProperty): arkts.Property | undefined {
        const watchStr: string | undefined = getValueInAnnotation(property, DecoratorNames.WATCH);
        if (watchStr) {
            return arkts.factory.createProperty(
                arkts.Es2pandaPropertyKind.PROPERTY_KIND_INIT,
                arkts.factory.createIdentifier(propName),
                factory.createWatchCallback(watchStr),
                false,
                false
            );
        }
        return undefined;
    }

    static createOptionalClassProperty(
        options: PropertyOptionalFieldOptions
    ): arkts.ClassProperty {
        const { name, propertyType, modifiers, stateManagementType, needMemo, isRequired } = options;
        const newType: arkts.TypeNode | undefined = !stateManagementType
            ? (propertyType ?? UIFactory.createTypeReferenceFromString(TypeNames.ANY))
            : propertyType;
        if (needMemo && !!newType && arkts.isETSFunctionType(newType) && findCanAddMemoFromTypeAnnotation(newType).canAddMemo) {
            addMemoAnnotation(newType);
        }
        let newPropertyType = !!stateManagementType ? factory.createStageManagementType(stateManagementType, propertyType) : newType;
        if (!isRequired && !!newPropertyType && arkts.isETSFunctionType(newPropertyType)) {
            newPropertyType = arkts.factory.createETSUnionType([newPropertyType, arkts.factory.createETSUndefinedType()]);
        }
        const newProperty = arkts.factory.createClassProperty(
            arkts.factory.createIdentifier(name),
            undefined,
            newPropertyType,
            modifiers,
            false
        );
        if (isRequired) {
            newProperty.setIsImmediateInit();
        } else {
            newProperty.modifierFlags |= arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_OPTIONAL;
        }
        return newProperty;
    }

    static createStageManagementType(
        stageManagementType: StateManagementTypes,
        type: arkts.TypeNode | undefined
    ): arkts.ETSTypeReference {
        collectStateManagementTypeImport(stageManagementType);
        return arkts.factory.createETSTypeReference(
            arkts.factory.createETSTypeReferencePart(
                arkts.factory.createIdentifier(stageManagementType),
                arkts.factory.createTSTypeParameterInstantiation([type ?? arkts.factory.createETSUndefinedType()])
            )
        );
    }

    /*
     * create watch related members in Observed/Track classes
     */
    static createWatchMembers(isDecl: boolean): arkts.AstNode[] {
        const members: arkts.AstNode[] = [];
        if (!isDecl) {
            const subscribedWatches: arkts.ClassProperty = arkts.factory.createClassProperty(
                arkts.factory.createIdentifier(ObservedNames.SUBSCRIBED_WATCHES),
                factory.generateStateMgmtFactoryCall(StateManagementTypes.MAKE_SUBSCRIBED_WATCHES, undefined, [], false),
                arkts.factory.createETSUnionType([
                    arkts.factory.createETSTypeReference(
                        arkts.factory.createETSTypeReferencePart(
                            arkts.factory.createIdentifier(StateManagementTypes.SUBSCRIBED_WATCHES)
                        )
                    ),
                    arkts.factory.createETSUndefinedType()
                ]),
                arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_PRIVATE,
                false
            );
            subscribedWatches.setAnnotations([
                annotation(DecoratorNames.JSONSTRINGIFYIGNORE),
                annotation(DecoratorNames.JSONPARSEIGNORE),
            ]);
            collectStateManagementTypeImport(StateManagementTypes.SUBSCRIBED_WATCHES);
            members.push(subscribedWatches);
        }
        const addWatchSubscriber = factory.createWatchMethod(
            ObservedNames.ADD_WATCH_SUBSCRIBER,
            arkts.Es2pandaPrimitiveType.PRIMITIVE_TYPE_VOID,
            ObservedNames.WATCH_ID,
            StateManagementTypes.WATCH_ID_TYPE,
            false,
            isDecl
        );
        members.push(addWatchSubscriber);

        const removeWatchSubscriber = factory.createWatchMethod(
            ObservedNames.REMOVE_WATCH_SUBSCRIBER,
            arkts.Es2pandaPrimitiveType.PRIMITIVE_TYPE_BOOLEAN,
            ObservedNames.WATCH_ID,
            StateManagementTypes.WATCH_ID_TYPE,
            true,
            isDecl
        );
        collectStateManagementTypeImport(StateManagementTypes.WATCH_ID_TYPE);
        members.push(removeWatchSubscriber);

        const executeOnSubscribingWatches = factory.createWatchMethod(
            ObservedNames.EXECUATE_WATCHES,
            arkts.Es2pandaPrimitiveType.PRIMITIVE_TYPE_VOID,
            ObservedNames.PROPETY_NAME,
            'string',
            false,
            isDecl
        );
        members.push(executeOnSubscribingWatches);
        return members;
    }

    /*
     * helper for createWatchMembers to create watch methods
     */
    static createWatchMethod(
        methodName: string,
        returnType: arkts.Es2pandaPrimitiveType,
        paramName: string,
        paramType: string,
        isReturnStatement: boolean,
        isDecl: boolean
    ): arkts.MethodDefinition {
        let body: arkts.BlockStatement | undefined;
        let modifier = arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC;
        if (!isDecl) {
            const subscribedWatchesAccess = arkts.factory.createMemberExpression(
                arkts.factory.createThisExpression(),
                arkts.factory.createIdentifier(ObservedNames.SUBSCRIBED_WATCHES),
                arkts.Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS,
                false,
                false
            );
            const undefinedCondition = arkts.factory.createBinaryExpression(
                subscribedWatchesAccess,
                arkts.factory.createUndefinedLiteral(),
                arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_NOT_STRICT_EQUAL
            );
            const innerStatement = isReturnStatement
                ? arkts.factory.createReturnStatement(
                        arkts.factory.createCallExpression(
                            factory.thisSubscribedWatchesMember(methodName),
                            [arkts.factory.createIdentifier(paramName)],
                            undefined,
                            false,
                            false
                        )
                    )
                : arkts.factory.createExpressionStatement(
                        arkts.factory.createCallExpression(
                            factory.thisSubscribedWatchesMember(methodName),
                            [arkts.factory.createIdentifier(paramName)],
                            undefined,
                            false,
                            false
                        )
                    );
            const ifStatement = arkts.factory.createIfStatement(
                undefinedCondition,
                arkts.factory.createBlockStatement([innerStatement])
            );
            const bodyStatements: arkts.Statement[] = [ifStatement];
            if (isReturnStatement) {
                bodyStatements.push(
                    arkts.factory.createReturnStatement(
                        arkts.factory.createBooleanLiteral(false)
                    )
                );
            }
            body = arkts.factory.createBlockStatement(bodyStatements);
        } else {
            modifier |= arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_DECLARE;
        }
        return arkts.factory.createMethodDefinition(
            arkts.Es2pandaMethodDefinitionKind.METHOD_DEFINITION_KIND_METHOD,
            arkts.factory.createIdentifier(methodName),
            arkts.factory.createFunctionExpression(
                arkts.factory.createIdentifier(methodName),
                arkts.factory.createScriptFunction(
                    body,
                    undefined,
                    [
                        arkts.factory.createETSParameterExpression(
                            arkts.factory.createIdentifier(
                                paramName,
                                arkts.factory.createETSTypeReference(
                                    arkts.factory.createETSTypeReferencePart(arkts.factory.createIdentifier(paramType))
                                )
                            ),
                            false,
                            undefined
                        )
                    ],
                    arkts.factory.createETSPrimitiveType(returnType),
                    false,
                    arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_METHOD,
                    modifier,
                    arkts.factory.createIdentifier(methodName),
                    undefined
                )
            ),
            modifier,
            false
        );
    }

    /*
     * helper for createWatchMethod, generates this.subscribedWatches.xxx
     */
    static thisSubscribedWatchesMember(member: string): arkts.MemberExpression {
        return arkts.factory.createMemberExpression(
            arkts.factory.createTSNonNullExpression(
                arkts.factory.createMemberExpression(
                    arkts.factory.createThisExpression(),
                    arkts.factory.createIdentifier(ObservedNames.SUBSCRIBED_WATCHES),
                    arkts.Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS,
                    false,
                    false
                )
            ),
            arkts.factory.createIdentifier(member),
            arkts.Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS,
            false,
            false
        );
    }

    /*
     * create ____V1RenderId related members in Observed/Track classes
     */
    static createV1RenderIdMembers(isObservedV2: boolean, isDecl: boolean): arkts.AstNode[] {
        const members: arkts.AstNode[] = [];
        const setV1RenderId: arkts.MethodDefinition = factory.setV1RenderId(isObservedV2, isDecl);
        collectStateManagementTypeImport(StateManagementTypes.RENDER_ID_TYPE);
        members.push(setV1RenderId);
        return members;
    }

    /*
     * helper for createV1RenderIdMembers to generate setV1RenderId method
     */
    static setV1RenderId(isObservedV2: boolean, isDecl: boolean): arkts.MethodDefinition {
        let body: arkts.BlockStatement | undefined;
        let modifiers = arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC;
        if (!isDecl) {
            const bodyStatements: arkts.Statement[] = [];
            body = arkts.factory.createBlockStatement(bodyStatements);
        } else {
            modifiers |= arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_DECLARE;
        }
        return UIFactory.createMethodDefinition({
            key: arkts.factory.createIdentifier(ObservedNames.SET_V1_RERENDER_ID),
            kind: arkts.Es2pandaMethodDefinitionKind.METHOD_DEFINITION_KIND_METHOD,
            function: {
                body,
                params: [
                    arkts.factory.createETSParameterExpression(
                        arkts.factory.createIdentifier(
                            ObservedNames.RERENDER_ID,
                            UIFactory.createTypeReferenceFromString(StateManagementTypes.RENDER_ID_TYPE)
                        ),
                        false,
                        undefined
                    ),
                ],
                returnTypeAnnotation: arkts.factory.createETSPrimitiveType(
                    arkts.Es2pandaPrimitiveType.PRIMITIVE_TYPE_VOID
                ),
                flags: arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_METHOD,
                modifiers,
            },
            modifiers,
        });
    }

    /*
     * create conditionalAddRef method in Observed/Track classes
     */
    static conditionalAddRef(isObservedV2: boolean): arkts.MethodDefinition {
        const metaAddRef: arkts.ExpressionStatement = arkts.factory.createExpressionStatement(
            arkts.factory.createCallExpression(
                UIFactory.generateMemberExpression(
                    arkts.factory.createIdentifier(ObservedNames.META),
                    ObservedNames.ADD_REF
                ),
                [],
                undefined,
                false,
                false
            )
        );
        collectStateManagementTypeImport(StateManagementTypes.MUTABLE_STATE_META);
        return UIFactory.createMethodDefinition({
            key: arkts.factory.createIdentifier(ObservedNames.CONDITIONAL_ADD_REF),
            kind: arkts.Es2pandaMethodDefinitionKind.METHOD_DEFINITION_KIND_METHOD,
            function: {
                body: arkts.factory.createBlockStatement([metaAddRef]),
                params: [
                    arkts.factory.createETSParameterExpression(
                        arkts.factory.createIdentifier(
                            ObservedNames.META,
                            UIFactory.createTypeReferenceFromString(StateManagementTypes.MUTABLE_STATE_META)
                        ),
                        false,
                        undefined
                    ),
                ],
                returnTypeAnnotation: arkts.factory.createETSPrimitiveType(
                    arkts.Es2pandaPrimitiveType.PRIMITIVE_TYPE_VOID
                ),
                flags: arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_METHOD,
                modifiers: arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_PROTECTED,
            },
            modifiers: arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_PROTECTED,
        });
    }

    /*
     * helper for conditionalAddRef to generate shouldAddRef method
     */
    static shouldAddRef(metaAddRef: arkts.ExpressionStatement): arkts.IfStatement {
        const test: arkts.CallExpression = arkts.factory.createCallExpression(
            UIFactory.generateMemberExpression(
                arkts.factory.createIdentifier(StateManagementTypes.OBSERVE),
                ObservedNames.SHOULD_ADD_REF
            ),
            [generateThisBacking(ObservedNames.V1_RERENDER_ID)],
            undefined,
            false,
            false
        );
        collectStateManagementTypeImport(StateManagementTypes.OBSERVE);
        const consequent: arkts.BlockStatement = arkts.factory.createBlockStatement([metaAddRef]);
        return arkts.factory.createIfStatement(test, consequent);
    }

    /*
     * helper to create meta field in classes with only @Observe and no @Track
     */
    static createMetaInObservedClass(): arkts.ClassProperty {
        collectStateManagementTypeImport(StateManagementTypes.MUTABLE_STATE_META);
        const meta = arkts.factory.createClassProperty(
            arkts.factory.createIdentifier(StateManagementTypes.META),
            factory.generateStateMgmtFactoryCall(
                StateManagementTypes.MAKE_MUTABLESTATE_META,
                undefined,
                [arkts.factory.createStringLiteral(`${StateManagementTypes.META}_`)],
                true
            ),
            UIFactory.createTypeReferenceFromString(StateManagementTypes.MUTABLE_STATE_META),
            arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_PRIVATE,
            false
        );
        meta.setAnnotations([
            annotation(DecoratorNames.JSONSTRINGIFYIGNORE),
            annotation(DecoratorNames.JSONPARSEIGNORE),
        ]);
        return meta;
    }

    /**
     * add `@memo` to the `@Builder` methods in class.
     */
    static addMemoToBuilderClassMethod(method: arkts.MethodDefinition): arkts.MethodDefinition {
        if (hasDecorator(method, DecoratorNames.BUILDER)) {
            removeDecorator(method, DecoratorNames.BUILDER);
            addMemoAnnotation(method.function!);
        }
        return method;
    }

    /**
     * wrap interface non-undefined property type `T` to `<wrapTypeName><T>`.
     */
    static wrapInnerClassPropertyTypeInMethod(type: arkts.TypeNode, wrapTypeName: StateManagementTypes): arkts.TypeNode {
        if (arkts.isETSUnionType(type)) {
            return arkts.factory.createETSUnionType([	 
                arkts.factory.createETSTypeReference( 
                    arkts.factory.createETSTypeReferencePart( 
                        arkts.factory.createIdentifier(wrapTypeName), 
                        arkts.factory.createTSTypeParameterInstantiation([type.types[0]]) 
                    ) 
                ), 
                ...type.types.slice(1), 
            ]);
        }
        return arkts.factory.createETSTypeReference(
            arkts.factory.createETSTypeReferencePart(
                arkts.factory.createIdentifier(wrapTypeName),
                arkts.factory.createTSTypeParameterInstantiation([type])
            )
        );
    }

    static wrapInnerClassPropertyTypeInProperty(type: arkts.TypeNode, wrapTypeName: StateManagementTypes): arkts.TypeNode {
        return arkts.factory.createETSTypeReference(
            arkts.factory.createETSTypeReferencePart(
                arkts.factory.createIdentifier(wrapTypeName),
                arkts.factory.createTSTypeParameterInstantiation([type])
            )
        );
    }

    /**
     * wrap interface property parameter that has non-undefined type `T` to `<wrapTypeName><T>`.
     */
    static wrapInnerClassPropertyParamExpr(
        param: arkts.Expression,
        wrapTypeName: StateManagementTypes
    ): arkts.Expression {
        if (!arkts.isETSParameterExpression(param)) {
            return param;
        }
        if (!param.typeAnnotation || !arkts.isETSUnionType(param.typeAnnotation)) {
            return param;
        }
        return arkts.factory.createETSParameterExpression(
            arkts.factory.createIdentifier(
                param.ident!.name,
                factory.wrapInnerClassPropertyTypeInMethod(param.typeAnnotation!, wrapTypeName)
            ),
            param.isOptional,
            param.initializer,
            param.annotations
        );
    }

    static wrapStateManagementTypeToType(
        type: arkts.TypeNode | undefined,
        decoratorName: DecoratorNames,
        wrapFn: (type: arkts.TypeNode, wrapTypeName: StateManagementTypes) => arkts.TypeNode
    ): arkts.TypeNode | undefined {
        let newType: arkts.TypeNode | undefined;
        let wrapTypeName: StateManagementTypes | undefined;
        if (!!type && !!(wrapTypeName = DECORATOR_TYPE_MAP.get(decoratorName))) {
            newType = wrapFn(type, wrapTypeName);
            collectStateManagementTypeImport(wrapTypeName);
        }
        return newType;
    }

    static wrapStateManagementTypeToParam(
        param: arkts.Expression | undefined,
        decoratorName: DecoratorNames,
        metadata?: AstNodeCacheValueMetadata,
    ): arkts.Expression | undefined {
        let newParam: arkts.Expression | undefined;
        let wrapTypeName: StateManagementTypes | undefined;
        if (!!param && !!(wrapTypeName = DECORATOR_TYPE_MAP.get(decoratorName))) {
            newParam = factory.wrapInnerClassPropertyParamExpr(param, wrapTypeName);
            const currentMetadata = findCachedMemoMetadata(param);
            if (!!metadata) {
                NodeCacheFactory.getInstance().getCache(NodeCacheNames.MEMO).collect(newParam, currentMetadata || metadata);
            }
            collectStateManagementTypeImport(wrapTypeName);
        }
        return newParam;
    }

    /**
     * Wrap getter's return type and setter's param type (expecting an union type with `T` and `undefined`)
     * to `<wrapTypeName><T> | undefined`, where `<wrapTypeName>` is getting from `DecoratorName`;
     *
     * @param method expecting getter with decorator annotation and a setter with decorator annotation in the overloads.
     */
    static wrapStateManagementTypeToMethodInInnerClass(
        method: arkts.MethodDefinition,
        decorator: DecoratorNames,
        metadata?: AstNodeCacheValueMetadata,
    ): arkts.MethodDefinition {
        if (method.kind === arkts.Es2pandaMethodDefinitionKind.METHOD_DEFINITION_KIND_GET) {
            const func = method.function!;
            const newType: arkts.TypeNode | undefined = factory.wrapStateManagementTypeToType(
                func.returnTypeAnnotation,
                decorator,
                factory.wrapInnerClassPropertyTypeInMethod
            );
            removeDecorator(method, decorator);
            if (!!newType) {
                const currentMetadata = findCachedMemoMetadata(func.returnTypeAnnotation!)
                if (!!metadata || !!currentMetadata) {
                    NodeCacheFactory.getInstance().getCache(NodeCacheNames.MEMO).collect(newType, currentMetadata || metadata);
                }
                func.setReturnTypeAnnotation(newType);
            }
            return method;
        }
        if (method.kind === arkts.Es2pandaMethodDefinitionKind.METHOD_DEFINITION_KIND_SET) {
            const func = method.function!;
            const newParam: arkts.Expression | undefined = factory.wrapStateManagementTypeToParam(
                method.function.params.at(0),
                decorator,
                metadata
            );
            removeDecorator(method, decorator);
            if (!!newParam) {
                func.setParams([newParam]);
            }
            return method;
        }
        return method;
    }

    /**
     * create external assignment node, e.g. `initializers?.<originalName> ?? <property>.value` or `initializers!.<originalName>!`.
     *
     * @param property class property node.
     * @param propertyType class property type.
     * @param originalName property name.
     */
    static generateInitializeValue(
        propertyValue: arkts.Expression | undefined,
        propertyType: arkts.TypeNode | undefined,
        originalName: string,
        options?: InitializeValueOptions,
        isMemoCached?: boolean,
        metadata?: arkts.AstNodeCacheValueMetadata
    ): arkts.Expression {
        if (options?.shouldCheckNonNull) {
            const id: string = GenSymGenerator.getInstance().id(originalName);
            const optionsType: arkts.TypeNode | undefined = propertyType?.clone();
            const optionsValue: arkts.Expression = factory.generateDefiniteInitializers(optionsType, originalName);
            const canCastType: boolean = canCastTypeFromValue(propertyValue);
            const defaultType: arkts.TypeNode | undefined = canCastType && !!propertyType ? propertyType.clone() : undefined;
            const defaultRawValue: arkts.Expression = !!propertyValue ? propertyValue : arkts.factory.createUndefinedLiteral();
            const defaultValue: arkts.Expression = !!defaultType
                ? arkts.factory.createTSAsExpression(defaultRawValue, defaultType, false)
                : defaultRawValue;
            if (isMemoCached) {
                if (!!optionsType) {
                    PropertyValueCache.getInstance().collect({ value: optionsType, shouldCache: isMemoCached, metadata});
                }
                if (!!defaultType) {
                    PropertyValueCache.getInstance().collect({ value: defaultType, shouldCache: isMemoCached, metadata });
                }
            }
            return arkts.factory.createConditionalExpression(
                factory.createBlockStatementForOptionsHasMemberExpression(
                    arkts.factory.createIdentifier(CustomComponentNames.COMPONENT_INITIALIZERS_NAME),
                    id,
                    originalName
                ), 
                optionsValue, 
                defaultValue
            );
        }
        if (!!options?.isRequired || !propertyValue) {
            return factory.generateDefiniteInitializers(propertyType, originalName);
        }
        const outInitialize: arkts.Expression = factory.createBlockStatementForOptionalExpression(
            arkts.factory.createIdentifier(CustomComponentNames.COMPONENT_INITIALIZERS_NAME),
            originalName,
            { isNonNull: options?.isRequired }
        );
        const binaryItem: arkts.Expression = arkts.factory.createBinaryExpression(
            outInitialize,
            propertyValue,
            arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_NULLISH_COALESCING
        );
        const canCastType: boolean = canCastTypeFromValue(propertyValue);
        const finalBinary: arkts.Expression = !canCastType || !propertyType
            ? binaryItem
            : arkts.factory.createTSAsExpression(binaryItem, propertyType, false);
        return finalBinary;
    }

    /**
     * Wrap to the type of the property (expecting an union type with `T` and `undefined`)
     * to `<wrapTypeName><T> | undefined`, where `<wrapTypeName>` is getting from `DecoratorName`;
     *
     * @param property expecting property with decorator annotation.
     */
    static wrapStateManagementTypeToPropertyInInnerClass(
        property: arkts.ClassProperty,
        decorator: DecoratorNames
    ): arkts.ClassProperty {
        const newType: arkts.TypeNode | undefined = factory.wrapStateManagementTypeToType(
            property.typeAnnotation,
            decorator,
            factory.wrapInnerClassPropertyTypeInProperty
        );
        removeDecorator(property, decorator);
        if (!!newType) {
            property.setTypeAnnotation(newType);
        }
        return property;
    }

    static generateinitAssignment(
        monitorItem: string[] | undefined,
        originalName: string,
        newName: string,
        isFromStruct: boolean,
        paramsLength: number,
        definition?: arkts.ClassDefinition
    ): arkts.ExpressionStatement {
        if (paramsLength === 0) {
            collectStateManagementTypeImport(StateManagementTypes.I_MONITOR);
        }
        const thisValue: arkts.Expression = generateThisBacking(newName, false, false);
        collectStateManagementTypeImport(StateManagementTypes.IMONITOR_PATH_INFO);
        const args: arkts.Expression[] = [
            this.generatePathArg(definition, monitorItem),
            this.generateLambdaArg(originalName, paramsLength)];
        const compatibleVersion = MetaDataCollector.getInstance().projectConfig?.compatibleSdkVersion;
        if (compatibleVersion !== undefined && compatibleVersion >= 24) {
            const makeMonitorOptions = arkts.factory.createObjectExpression(
                [
                    arkts.factory.createProperty(
                        arkts.Es2pandaPropertyKind.PROPERTY_KIND_INIT,
                        arkts.factory.createIdentifier(MonitorNames.OWNER),
                        isFromStruct ? arkts.factory.createThisExpression() : arkts.factory.createUndefinedLiteral(),
                        false, false
                    ),
                    arkts.factory.createProperty(
                        arkts.Es2pandaPropertyKind.PROPERTY_KIND_INIT,
                        arkts.factory.createIdentifier(MonitorNames.FUNCTION_NAME),
                        arkts.factory.createStringLiteral(originalName),
                        false, false
                    ),
                ]
            );
            collectStateManagementTypeImport(StateManagementTypes.MAKE_MONITOR_OPTIONS);
            args.push(arkts.factory.createTSAsExpression(
                makeMonitorOptions,
                UIFactory.createTypeReferenceFromString(StateManagementTypes.MAKE_MONITOR_OPTIONS),
                false
            ));
        } else if (isFromStruct) {
            args.push(arkts.factory.createThisExpression());
        }
        const right: arkts.CallExpression = factory.generateStateMgmtFactoryCall(
            StateManagementTypes.MAKE_MONITOR,
            undefined,
            args,
            false
        );
        return arkts.factory.createExpressionStatement(
            arkts.factory.createAssignmentExpression(
                thisValue,
                right,
                arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_SUBSTITUTION
            )
        );
    }

    static generatePathArg(definition?: arkts.ClassDefinition, monitorItem?: string[]): arkts.ArrayExpression {
        if (!monitorItem || monitorItem.length <= 0) {
            return arkts.factory.createArrayExpression([]);
        }
        const params = monitorItem.map((itemName: string) => {
            return arkts.factory.createTSAsExpression(
                factory.createMonitorPathsInfoParameter(itemName, definition),
                UIFactory.createTypeReferenceFromString(StateManagementTypes.IMONITOR_PATH_INFO),
                false
            );
        });
        return arkts.factory.createArrayExpression(params);
    }

    static generateLambdaArg(originalName: string, paramsLength: number): arkts.ArrowFunctionExpression {
        return arkts.factory.createArrowFunctionExpression(
            UIFactory.createScriptFunction({
                params: [UIFactory.createParameterDeclaration(MonitorNames.M_PARAM, MonitorNames.I_MONITOR)],
                body: arkts.factory.createBlockStatement([
                    arkts.factory.createExpressionStatement(
                        arkts.factory.createCallExpression(generateThisBacking(originalName), 
                            paramsLength > 0 ? [arkts.factory.createIdentifier(MonitorNames.M_PARAM)] : [],
                            undefined, false, false)
                    ),
                ]),
                flags: arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_ARROW,
            })
        );
    }

    static generateMonitorVariable(itemNameSplit: string[]): arkts.Expression {
        const objectFirst: arkts.Expression = generateThisBacking(itemNameSplit[0]);
        if (itemNameSplit.length === 1) {
            return objectFirst;
        }
        itemNameSplit.shift();
        return this.recursiveCreateOptionalMember(objectFirst, itemNameSplit);
    }

    /**
     * recursively create member expression with <object> node and property name in <resNameArr>.
     *
     * @param typeAnnotation expecting property's original type annotation.
     */
    static recursiveCreateOptionalMember(object: arkts.Expression, resNameArr: string[]): arkts.Expression {
        if (resNameArr.length <= 0) {
            return object;
        }
        const optionalInfo: OptionalMemberInfo = { isNumeric: false };
        if (isNumeric(resNameArr[0])) {
            optionalInfo.isNumeric = true;
        }
        const newMember: arkts.Expression = this.createBlockStatementForOptionalExpression(
            object,
            resNameArr[0],
            optionalInfo
        );
        resNameArr.shift();
        return this.recursiveCreateOptionalMember(newMember, resNameArr);
    }

    /**
     * Check if property path contains union types (nodes with multiple branches).
     * Returns the PropertyPathResult if union types are found, undefined otherwise.
     *
     * @param definition Class definition for property resolution.
     * @param monitorItem Property path to check.
     * @param hasWildcard Whether wildcard support is enabled.
     */
    private static findUnionTypesInPropertyPath(
        definition: arkts.ClassDefinition,
        monitorItem: string,
        hasWildcard: boolean
    ): PropertyPathResult | undefined {
        const propertyPathResult = resolvePropertyPath(definition, monitorItem, { enableWildcard: hasWildcard });
        // Check if any node in the path has multiple branches (indicating union types)
        let current: PropertyPathNode | null = propertyPathResult.root;
        while (current) {
            if (current.branchCount > 1) {
                return propertyPathResult;
            }
            current = current.branchCount === 1 ? current.branches[0].next : null;
        }
        return undefined;
    }

    /**
     * Generate blocks for handling union types in property paths.
     * Creates instanceof checks and nested if-else statements to navigate union type branches.
     *
     * @param propertyPathResult Resolved property path containing union type information.
     * @param itemNameSplit Split property path segments.
     * @returns Array of statements for union type path handling.
     */
    private static generateUnionTypePathBlocks(
        propertyPathResult: PropertyPathResult,
        itemNameSplit: string[]
    ): arkts.Statement[] {
        const blocks: arkts.Statement[] = [];
        blocks.push(
            UIFactory.generateLetVariableDecl(
                arkts.factory.createIdentifier('x', UIFactory.createTypeReferenceFromString('Any')),
                arkts.factory.createMemberExpression(
                    arkts.factory.createThisExpression(),
                    arkts.factory.createIdentifier(itemNameSplit[0]),
                    arkts.Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS, false, false
                )
            )
        );

        const resultPaths = propertyPathResult.getAllResultPaths();
        for (let varIdx = 1; varIdx < resultPaths[0].length; varIdx++) {
            let elseBranch: arkts.Statement = arkts.factory.createReturnStatement(
                arkts.factory.createUndefinedLiteral()
            );
            for (let pathIdx = 0; pathIdx < resultPaths.length; pathIdx++) {
                const currentType = resultPaths[pathIdx][varIdx - 1].type;
                let currentTypeName: string = '';
                if (currentType) {
                    currentTypeName = ((currentType as arkts.ETSTypeReference).part.name as arkts.Identifier).name;
                }
                if (currentType && currentTypeName !== 'String') {
                    const assignementRightExpr = factory.createUnionTypeAssignmentExpr(resultPaths[pathIdx][varIdx].segment);
                    elseBranch = factory.createInstanceOfBranch(currentTypeName, assignementRightExpr, elseBranch);
                }
            }
            blocks.push(elseBranch);
        }
        blocks.push(arkts.factory.createReturnStatement(arkts.factory.createIdentifier('x')));
        return blocks;
    }

    /**
     * create IMonitorPathsInfo type parameter `{ path: "<monitorItem>", lambda: () => { return this.<monitorItem> } }`.
     *
     * @param monitorItem monitored property name.
     */
    private static createMonitorPathProperties(
        monitorItem: string,
        hasWildcard: boolean,
        blocks: arkts.Statement[]
    ): arkts.Property[] {
        const properties: arkts.Property[] = [
            arkts.factory.createProperty(
                arkts.Es2pandaPropertyKind.PROPERTY_KIND_INIT,
                arkts.factory.createIdentifier(MonitorNames.PATH),
                arkts.factory.createStringLiteral(monitorItem),
                false,
                false
            ),
        ];
        if (hasWildcard) {
            properties.push(arkts.factory.createProperty(
                arkts.Es2pandaPropertyKind.PROPERTY_KIND_INIT,
                arkts.factory.createIdentifier(MONITOR_WILDCARD_PROPERTY_NAME),
                arkts.factory.createBooleanLiteral(true),
                false,
                false
            ));
        }
        properties.push(arkts.factory.createProperty(
            arkts.Es2pandaPropertyKind.PROPERTY_KIND_INIT,
            arkts.factory.createIdentifier(MonitorNames.VALUE_CALLBACK),
            arkts.factory.createArrowFunctionExpression(
                UIFactory.createScriptFunction({
                    flags: arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_ARROW,
                    body: arkts.factory.createBlockStatement(blocks),
                    returnTypeAnnotation: UIFactory.createTypeReferenceFromString(TypeNames.ANY),
                })
            ),
            false,
            false
        ));
        return properties;
    }

    static createMonitorPathsInfoParameter(
        monitorItem: string,
        definition?: arkts.ClassDefinition
    ): arkts.ObjectExpression {
        const compatibleVersion = MetaDataCollector.getInstance().projectConfig?.compatibleSdkVersion;
        const hasWildcard: boolean = monitorItem.endsWith(MONITOR_WILDCARD_SUFFIX) &&
            compatibleVersion !== undefined && compatibleVersion >= MONITOR_WILDCARD_MIN_VERSION;
        const propertyPathResult = definition ? 
            factory.findUnionTypesInPropertyPath(definition, monitorItem, hasWildcard) : undefined;
        const valueCallbackPath: string = hasWildcard
            ? monitorItem.substring(0, monitorItem.length - MONITOR_WILDCARD_SUFFIX.length)
            : monitorItem;
        const itemNameSplit: string[] = valueCallbackPath.split('.');
        let blocks: arkts.Statement[] = []; 
        if (propertyPathResult === undefined) {
            let monitorVariable: arkts.Expression = arkts.factory.createUndefinedLiteral();
            if (itemNameSplit.length > 0 && itemNameSplit[0] !== '') {
                monitorVariable = this.generateMonitorVariable(itemNameSplit);
            }
            blocks.push(arkts.factory.createReturnStatement(monitorVariable));
        } else {
            blocks.push(...factory.generateUnionTypePathBlocks(propertyPathResult, itemNameSplit));
        }
        return arkts.factory.createObjectExpression(
            this.createMonitorPathProperties(monitorItem, hasWildcard, blocks)
        );
    }

    private static createUnionTypeAssignmentExpr(segment: string): arkts.Expression {
        if (isNumeric(segment)) {
            return arkts.factory.createCallExpression(
                arkts.factory.createMemberExpression(
                    arkts.factory.createIdentifier('x'),
                    arkts.factory.createIdentifier('$_get'),
                    arkts.Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS, false, false),
                [arkts.factory.createNumberLiteral(Number(segment))], undefined, false, false);
        }
        return arkts.factory.createMemberExpression(
            arkts.factory.createIdentifier('x'),
            arkts.factory.createIdentifier(segment),
            arkts.Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS, false, false);
    }

    private static createInstanceOfBranch(
        currentTypeName: string,
        assignementRightExpr: arkts.Expression,
        elseBranch: arkts.Statement
    ): arkts.IfStatement {
        return arkts.factory.createIfStatement(
            arkts.factory.createBinaryExpression(
                arkts.factory.createIdentifier('x'),
                UIFactory.createTypeReferenceFromString(currentTypeName),
                arkts.Es2pandaTokenType.TOKEN_TYPE_KEYW_INSTANCEOF
            ),
            arkts.factory.createBlockStatement([
                arkts.factory.createExpressionStatement(
                    arkts.factory.createAssignmentExpression(
                        arkts.factory.createIdentifier('x'),
                        assignementRightExpr,
                        arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_SUBSTITUTION
                    )
                )
            ]),
            elseBranch
        );
    }

    static generateComputedOwnerAssignment(newName: string): arkts.ExpressionStatement {
        const computedVariable = UIFactory.generateMemberExpression(
            arkts.factory.createThisExpression(),
            newName,
            false
        );
        const setOwnerFunc = UIFactory.generateMemberExpression(
            computedVariable,
            StateManagementTypes.SET_OWNER,
            false
        );
        return arkts.factory.createExpressionStatement(
            arkts.factory.createCallExpression(setOwnerFunc, [arkts.factory.createThisExpression()], undefined, false, false)
        );
    }

    static createResetOnReuseStmt(newName: string, arg?: arkts.Expression): arkts.ExpressionStatement {
        const callee = arkts.factory.createMemberExpression(
            generateThisBacking(newName, false, true),
            arkts.factory.createIdentifier(StateManagementTypes.RESET_ON_REUSE),
            arkts.Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS,
            false,
            false
        );

        return arkts.factory.createExpressionStatement(
            arkts.factory.createCallExpression(callee, arg ? [arg] : [], undefined, false, false)
        );
    }

    static createResetOnReuseStmtWithArgs(newName: string, args: arkts.Expression[]): arkts.ExpressionStatement {
        const callee = arkts.factory.createMemberExpression(
            generateThisBacking(newName, false, true),
            arkts.factory.createIdentifier(StateManagementTypes.RESET_ON_REUSE),
            arkts.Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS,
            false,
            false
        );

        return arkts.factory.createExpressionStatement(
            arkts.factory.createCallExpression(callee, args, undefined, false, false)
        );
    }

    static generateSyncMonitorAssignment(
        monitorItem: string[] | undefined,
        originalName: string,
        newName: string,
        isFromStruct: boolean,
        paramsLength: number,
        definition?: arkts.ClassDefinition
    ): arkts.ExpressionStatement {
        if (paramsLength === 0) {
            collectStateManagementTypeImport(StateManagementTypes.I_MONITOR);
        }
        const thisValue: arkts.Expression = generateThisBacking(newName, false, false);
        const args: arkts.Expression[] = [this.generateSyncMonitorPathArg(monitorItem, definition), this.generateLambdaArg(originalName, paramsLength)];
        const makeSyncMonitorOptions = arkts.factory.createObjectExpression([
            arkts.factory.createProperty(
                arkts.Es2pandaPropertyKind.PROPERTY_KIND_INIT,
                arkts.factory.createIdentifier('owner'),
                isFromStruct ? arkts.factory.createThisExpression() : arkts.factory.createUndefinedLiteral(),
                false,
                false
            ),
            arkts.factory.createProperty(
                arkts.Es2pandaPropertyKind.PROPERTY_KIND_INIT,
                arkts.factory.createIdentifier('functionName'),
                arkts.factory.createStringLiteral(originalName),
                false,
                false
            )
        ]);
        args.push(makeSyncMonitorOptions);
        const right: arkts.CallExpression = factory.generateStateMgmtFactoryCall(
            StateManagementTypes.MAKE_SYNC_MONITOR,
            undefined,
            args,
            false
        );
        return arkts.factory.createExpressionStatement(
            arkts.factory.createAssignmentExpression(
                thisValue,
                right,
                arkts.Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_SUBSTITUTION
            )
        );
    }

    static generateSyncMonitorPathArg(monitorItem: string[] | undefined,
        definition?: arkts.ClassDefinition): arkts.ArrayExpression {
        if (!monitorItem || monitorItem.length <= 0) {
            return arkts.factory.createArrayExpression([]);
        }
        const params = monitorItem.map((itemName: string) => {
            return factory.createSyncMonitorPathsInfoParameter(itemName, definition);
        });
        return arkts.factory.createArrayExpression(params);
    }

    static createSyncMonitorPathsInfoParameter(
        monitorItem: string,
        definition?: arkts.ClassDefinition
    ): arkts.ObjectExpression {
        const hasWildcard: boolean = monitorItem.endsWith(MONITOR_WILDCARD_SUFFIX);
        const valueCallbackPath: string = hasWildcard
            ? monitorItem.substring(0, monitorItem.length - MONITOR_WILDCARD_SUFFIX.length)
            : monitorItem;
        const itemNameSplit: string[] = valueCallbackPath.split('.');
        const propertyPathResult = definition ?
            factory.findUnionTypesInPropertyPath(definition, monitorItem, hasWildcard) : undefined;
        let blocks: arkts.Statement[] = [];
        if (propertyPathResult === undefined) {
            let monitorVariable: arkts.Expression = arkts.factory.createUndefinedLiteral();
            if (itemNameSplit.length > 0 && itemNameSplit[0] !== '') {
                monitorVariable = this.generateMonitorVariable(itemNameSplit);
            }
            blocks.push(arkts.factory.createReturnStatement(monitorVariable));
        } else {
            blocks.push(...factory.generateUnionTypePathBlocks(propertyPathResult, itemNameSplit));
        }
        const properties: arkts.Property[] = [
            arkts.factory.createProperty(
                arkts.Es2pandaPropertyKind.PROPERTY_KIND_INIT,
                arkts.factory.createIdentifier(MonitorNames.PATH),
                arkts.factory.createStringLiteral(monitorItem),
                false,
                false
            ),
        ];
        if (hasWildcard) {
            properties.push(arkts.factory.createProperty(
                arkts.Es2pandaPropertyKind.PROPERTY_KIND_INIT,
                arkts.factory.createIdentifier(MONITOR_WILDCARD_PROPERTY_NAME),
                arkts.factory.createBooleanLiteral(true),
                false,
                false
            ));
        }
        properties.push(arkts.factory.createProperty(
            arkts.Es2pandaPropertyKind.PROPERTY_KIND_INIT,
            arkts.factory.createIdentifier(MonitorNames.VALUE_CALLBACK),
            arkts.factory.createArrowFunctionExpression(
                UIFactory.createScriptFunction({
                    flags: arkts.Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_ARROW,
                    body: arkts.factory.createBlockStatement(blocks),
                    returnTypeAnnotation: UIFactory.createTypeReferenceFromString(TypeNames.ANY),
                })
            ),
            false,
            false
        ));
        return arkts.factory.createObjectExpression(properties);
    }

    static stringLiteralToMemberExpression(node: arkts.Expression): arkts.Expression {
        if (!arkts.isStringLiteral(node)) {
            return node;
        }
        const parts: string[] = node.str.split('.');
        if (parts.length !== 2) {
            return node;
        }
        return arkts.factory.createMemberExpression(
            arkts.factory.createIdentifier(parts[0]),
            arkts.factory.createIdentifier(parts[1]),
            arkts.Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS,
            false,
            false
        );
    }
}