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

import ExtensionContext from 'application.ExtensionContext';
import Want from '@ohos.app.ability.Want';
import { AsyncCallback, BusinessError, Callback } from '@ohos.base';
import accessibility from '@ohos.accessibility';
import { AccessibilityAction, FocusMoveResultCode, InjectActionType, AccessibilityFocusScene, FocusRuleType } from '@ohos.accessibility';

export interface FocusMoveResult {
  target: Array<AccessibilityElement>;
  result: FocusMoveResultCode;
}

export class FocusMoveResultImpl implements FocusMoveResult {
    target: Array<AccessibilityElement> = [];
    result: FocusMoveResultCode = FocusMoveResultCode.NOT_SUPPORTED;
}

export type FocusCondition = 'forward' | 'backward' |
'findLast' | 'getForwardScrollAncestor' | 'getBackwardScrollAncestor' | 'getScrollableAncestor';

export type FocusRule = 'bypassSelf' | 'bypassSelfDescendants' |
'checkSelf' | 'checkSelfBypassDescendants';

export default class AccessibilityExtensionContext extends ExtensionContext {
    private nativePtr: long = 0;

    constructor() {
        super();
        console.log('STS AccessibilityExtensionContext constructor');
    }

    startAbility(want: Want): Promise<void> {
        console.log('ani AccessibilityExtensionContext startAbility Promise');
        return taskpool.execute(this.startAbilityNative, want).then(() => {
            console.log('ani AccessibilityExtensionContext startAbility Promise success');
        }).catch((err: Error) => {
            console.log('ani AccessibilityExtensionContext startAbility Promise catch');
            let error = err as BusinessError;
            throw error;
        });
    }

    getElements(windowId: int, elementId?: long): Promise<Array<AccessibilityElement>> {
        console.log("getElements begin");
        return new Promise<Array<AccessibilityElement>>((resolve: (data: Array<AccessibilityElement>) => void,
            reject: (err: BusinessError) => void): void => {
            taskpool.execute(this.getElementsNative, windowId, elementId).then((code) => {
                console.log('resolve getElements');
                resolve(code as Array<AccessibilityElement>);
            }).catch((err: Error) => {
                reject(err as BusinessError);
            });
        });
    }

    getDefaultFocusedElementIds(windowId: int): Promise<Array<long>> {
        console.log("getDefaultFocusedElementIds begin");
        return new Promise<Array<long>>((resolve: (data: Array<long>) => void,
            reject: (err: BusinessError) => void): void => {
            taskpool.execute(this.getDefaultFocusedElementIdsNative, windowId).then((code) => {
                console.log('resolve getDefaultFocusedElementIds');
                resolve(code as Array<long>);
            }).catch((err: Error) => {
                reject(err as BusinessError);
            });
        });
    }

    onPreDisconnect(callback: Callback<void>): void {
        this.onNative('preDisconnect', callback);
    }

    offPreDisconnect(callback?: Callback<void>): void {
        this.offNative('preDisconnect', callback);
    }

    getAccessibilityFocusedElement(): Promise<AccessibilityElement> {
        return new Promise<AccessibilityElement>((resolve: (data: AccessibilityElement) => void,
            reject: (err: BusinessError) => void): void => {
            taskpool.execute(this.getAccessibilityFocusedElementNative).then((code) => {
                resolve(code as AccessibilityElement);
            }).catch((err: Error) => {
                reject(err as BusinessError);
            });
        });
    }

    getRootInActiveWindow(windowId?: int): Promise<AccessibilityElement> {
        console.log("getRootInActiveWindow " + windowId);
        return new Promise<AccessibilityElement>((resolve: (data: AccessibilityElement) => void,
            reject: (err: BusinessError) => void): void => {
            taskpool.execute(this.getRootInActiveWindowNative, windowId).then((code) => {
                console.log("resolve getRootInActiveWindow " + windowId);
                resolve(code as AccessibilityElement);
            }).catch((err: Error) => {
                reject(err as BusinessError);
            });
        });
    }

    updateAccessibilityElementProperty(elementId: long, windowId: int, node: AccessibilityVirtualNode):
        Promise<OperateVirtualNodeResult> {
        
        return new Promise<OperateVirtualNodeResult> ((resolve: (v: OperateVirtualNodeResult) => void,
            reject: (error: BusinessError) => void): void => {
            taskpool.execute(this.updateAccessibilityElementPropertyNative, elementId, windowId, node)
            .then((ret: Any): void => {
                resolve(ret as OperateVirtualNodeResult);
            })
            .catch((ret: Any): void => {
                reject(ret as BusinessError);
            });
        });
    }

    addAccessibilityVirtualNodes(elementId: long, windowId: int, nodes: Array<AccessibilityVirtualNode>):
        Promise<OperateVirtualNodeResult> {
        
        return new Promise<OperateVirtualNodeResult> ((resolve: (v: OperateVirtualNodeResult) => void,
            reject: (error: BusinessError) => void): void => {
            taskpool.execute(this.addAccessibilityVirtualNodesNative, elementId, windowId, nodes)
            .then((ret: Any): void => {
                resolve(ret as OperateVirtualNodeResult);
            })
            .catch((ret: Any): void => {
                reject(ret as BusinessError);
            });
        });
    }

    removeAccessibilityVirtualNodes(elementId: long, windowId: int):
        Promise<OperateVirtualNodeResult> {
        
        return new Promise<OperateVirtualNodeResult> ((resolve: (v: OperateVirtualNodeResult) => void,
            reject: (error: BusinessError) => void): void => {
            taskpool.execute(this.removeAccessibilityVirtualNodesNative, elementId, windowId)
            .then((ret: Any): void => {
                resolve(ret as OperateVirtualNodeResult);
            })
            .catch((ret: Any): void => {
                reject(ret as BusinessError);
            });
        });
    }

    native startAbilityNative(want: Want): void;
    native getElementsNative(windowId: int, elementId?: long): Array<AccessibilityElement>;
    native getDefaultFocusedElementIdsNative(windowId: int): Array<long>;
    native holdRunningLockSync(): void;
    native unholdRunningLockSync(): void;
    native onNative(type: string, callback: object): void;
    native offNative(type: string, callback?: object): void;
    native notifyDisconnect(): void;
    native getAccessibilityFocusedElementNative(): AccessibilityElement;
    native getRootInActiveWindowNative(windowId?: int): AccessibilityElement;
    native getAccessibilityWindowsSync(displayId?: long): Array<AccessibilityElement>;
    native updateAccessibilityElementPropertyNative(elementId: long, windowId: int,
        node: AccessibilityVirtualNode): int;
    native addAccessibilityVirtualNodesNative(elementId: long, windowId: int,
        nodes: Array<AccessibilityVirtualNode>): int;
    native removeAccessibilityVirtualNodesNative(elementId: long, windowId: int): int;
}

class AccessibilityElementCleaner {
    private static readonly registry = new FinalizationRegistry<AccessibilityElementCleaner>((cleaner) => {
        console.log('STS AccessibilityExtensionElement cleaner works');
        cleaner.cleanNative();
    });

    private static readonly unregisterToken = new object();

    private nativePtr: long;

    constructor(ptr: long, owner: object) {
        this.nativePtr = ptr;
        AccessibilityElementCleaner.registry.register(owner, this, AccessibilityElementCleaner.unregisterToken);
        console.log('STS AccessibilityExtensionElement cleaner constructor');
    }

    static unregister(owner: object): void {
        AccessibilityElementCleaner.registry.unregister(AccessibilityElementCleaner.unregisterToken);
    }

    native cleanNative(): void
}

export interface AccessibilityElement {
  getCursorPosition(callback: AsyncCallback<int>): void;
  getCursorPosition(): Promise<int>;
  enableScreenCurtain(isEnable: boolean): void;
  findElementByTextType(condition: string): Promise<Array<AccessibilityElement>>;
  findElementByElementId(condition: long): Promise<AccessibilityElement>;
  findElementsByCondition(rule: FocusRule, condition: FocusCondition): Promise<FocusMoveResult>;
  findElementsByCondition(rule: FocusRule, condition: FocusCondition, type: FocusRuleType): Promise<FocusMoveResult>;
  getParent(): Promise<AccessibilityElement>;
  getChildren(): Promise<Array<AccessibilityElement>>;
  getRoot(): Promise<AccessibilityElement>;
  findElementByContent(condition: string): Promise<Array<AccessibilityElement>>;
  findElementByFocusDirection(condition: FocusDirection): Promise<AccessibilityElement>;
  findElementByFocusDirection(condition: FocusDirection, type: FocusRuleType): Promise<AccessibilityElement>;
  findElementsByAccessibilityHintText(condition: string): Promise<Array<AccessibilityElement>>;
  findElementById(condition: long): Promise<AccessibilityElement>;
  executeAction(action: AccessibilityAction, parameters?: Parameter): Promise<void>;

  accessibilityFocused?: boolean;
  bundleName?: string;
  checkable?: boolean;
  checked?: boolean;
  clickable?: boolean;
  componentId?: long;
  componentType?: string;
  contents?: Array<string>;
  customActions?: Array<string>;
  currentIndex?: int;
  description?: string;
  editable?: boolean;
  endIndex?: int;
  error?: string;
  focusable?: boolean;
  hintText?: string;
  inputType?: int;
  inspectorKey?: string;
  isActive?: boolean;
  isEnable?: boolean;
  isHint?: boolean;
  isFocused?: boolean;
  isPassword?: boolean;
  isVisible?: boolean;
  itemCount?: int;
  lastContent?: string;
  layer?: int;
  longClickable?: boolean;
  pageId?: int;
  pluralLineSupported?: boolean;
  rect?: Rect;
  resourceName?: string;
  screenRect?: Rect;
  scrollable?: boolean;
  selected?: boolean;
  startIndex?: int;
  text?: string;
  textLengthLimit?: int;
  textMoveUnit?: accessibility.TextMoveUnit;
  triggerAction?: AccessibilityAction;
  type?: WindowType;
  valueMax?: double;
  valueMin?: double;
  valueNow?: double;
  windowId?: int;
  offset?: double;
  textType?: string;
  accessibilityText?: string;
  hotArea?: Rect;
  customComponentType?: string;
  accessibilityNextFocusId?: long;
  accessibilityPreviousFocusId?: long;
  extraInfo?: string;
  accessibilityScrollable?: boolean;
  supportedActionNames?: Array<string>;
  accessibilityGroup?: boolean;
  accessibilityLevel?: string;
  navDestinationId?: long;
  currentItem?: AccessibilityGrid;
  spans?: AccessibilitySpan[];
  accessibilityVisible?: boolean;
  mainWindowId?: int;
  clip?: boolean;
  parentId?: long;
  childrenIds?: Array<long>;
  accessibilityStateDescription?: string;
  isEssential?: boolean;
  belongTreeId?: int;
  childrenTreeId?: int;
}

export class AccessibilityElementImpl implements AccessibilityElement {
    private nativePtr: long = 0;
    private cleaner: AccessibilityElementCleaner | null = null;

    accessibilityFocused?: boolean = false;
    bundleName?: string = "";
    checkable?: boolean = false;
    checked?: boolean = false;
    clickable?: boolean = false;
    componentId?: long = 0;
    componentType?: string = "";
    contents?: Array<string> = [];
    customActions?:Array<string> = [];
    currentIndex?: int = 0;
    description?: string = "";
    editable?: boolean = false;
    endIndex?: int = 0;
    error?: string = "";
    focusable?: boolean = false;
    hintText?: string = "";
    inputType?: int = 0;
    inspectorKey?: string = "";
    isActive?: boolean = true;
    isEnable?: boolean = true;
    isHint?: boolean = false;
    isFocused?: boolean = false;
    isPassword?: boolean = false;
    isVisible?: boolean = true;
    itemCount?: int = 0;
    lastContent?: string = "";
    layer?: int = 0;
    longClickable?: boolean = false;
    pageId?: int = 0;
    pluralLineSupported?: boolean = false;
    rect?: Rect = new RectImpl();
    resourceName?: string = "";
    screenRect?: Rect = new RectImpl();
    scrollable?: boolean = false;
    selected?: boolean = false;
    startIndex?: int = 0;
    text?: string = "";
    textLengthLimit?: int = 0;
    textMoveUnit?: accessibility.TextMoveUnit = undefined;
    triggerAction?: AccessibilityAction = undefined;
    type?: WindowType = 'application';
    valueMax?: double = 0;
    valueMin?: double = 0;
    valueNow?: double = 0;
    windowId?: int = 0;
    offset?: double = 0;
    textType?: string = "";
    accessibilityText?: string = "";
    hotArea?: Rect = new RectImpl();
    customComponentType?: string = "";
    accessibilityNextFocusId?: long = 0;
    accessibilityPreviousFocusId?: long = 0;
    extraInfo?: string = "";
    accessibilityScrollable?: boolean = false;
    supportedActionNames?: Array<string> = [];
    accessibilityGroup?: boolean = true;
    accessibilityLevel?: string = "auto";
    navDestinationId?: long = 0;
    currentItem?: AccessibilityGrid = new AccessibilityGridImpl();
    spans?: AccessibilitySpan[] = [];
    accessibilityVisible?: boolean = true;
    mainWindowId?: int = 0;
    clip?: boolean = false;
    parentId?: long = 0;
    childrenIds?: Array<long> = [];
    accessibilityStateDescription?: string;
    isEssential?: boolean = false;
    belongTreeId?: int = 0;
    childrenTreeId?: int = 0;

    constructor() {
        super();
        this.cleaner = new AccessibilityElementCleaner(this.nativePtr, this);
        console.log('STS AccessibilityElement constructor');
    }

    getCursorPosition(callback: AsyncCallback<int>): void {
        console.log("getCursorPosition begin");
        let p1 = taskpool.execute(this.getCursorPositionNative, this) as Promise<int>;
        p1.then((code: int) => {
            console.log("getCursorPosition callback" + code);
            callback(null, code);
        }).catch((err: Error) => {
            callback(err as BusinessError, undefined);
        });
    }

    getCursorPosition(): Promise<int> {
        console.log("getCursorPosition begin ");
        return new Promise<int>((resolve: (data: int) => void, reject: (err: BusinessError) => void): void => {
            let p1 = taskpool.execute(this.getCursorPositionNative, this) as Promise<int>;
            p1.then((code: int) => {
                console.log("resolve getCursorPosition " + code);
                resolve(code);
            }).catch((err: Error) => {
                reject(err as BusinessError);
            });
        });
    }

    enableScreenCurtain(isEnable: boolean): void {
        console.log("enableScreenCurtain " + isEnable);
        this.enableScreenCurtainNative(isEnable);
    }

    findElementByTextType(condition: string): Promise<Array<AccessibilityElement>> {
        console.log("findElement by textType");
        return new Promise<Array<AccessibilityElement>>((resolve: (data: Array<AccessibilityElement>) => void,
            reject: (err: BusinessError) => void): void => {
            let p1 = taskpool.execute(this.findElementsNative, 'textType', condition) as Promise<Array<AccessibilityElement>>;
            p1.then((code: Array<AccessibilityElement>) => {
                console.log("resolve findElement size " + code.length);
                resolve(code);
            }).catch((err: Error) => {
                reject(err as BusinessError);
            });
        });
    }

    findElementByElementId(condition: long): Promise<AccessibilityElement> {
        console.log("findElement by elementId");
        return new Promise<AccessibilityElement>((resolve: (data: AccessibilityElement) => void,
            reject: (err: BusinessError) => void): void => {
            let p1 = taskpool.execute(this.findElementNative, 'elementId', condition) as Promise<AccessibilityElement>;
            p1.then((code: AccessibilityElement) => {
                console.log("resolve findElement");
                resolve(code);
            }).catch((err: Error) => {
                reject(err as BusinessError);
            });
        });
    }

    findElementsByCondition(rule: string, condition: string): Promise<FocusMoveResult> {
        console.log("findElements by condition");
        return new Promise<FocusMoveResult>((resolve: (data: FocusMoveResult) => void,
            reject: (err: BusinessError) => void): void => {
            let p1 = taskpool.execute(this.findElementsByConditionNative, rule, condition) as Promise<FocusMoveResult>;
            p1.then((code: FocusMoveResult) => {
                console.log("resolve findElementsByCondition");
                resolve(code);
            }).catch((err: Error) => {
                reject(err as BusinessError);
            });
        });
    }

    findElementsByCondition(rule: string, condition: string, type: FocusRuleType): Promise<FocusMoveResult> {
        console.log("findElements by condition with type");
        return new Promise<FocusMoveResult>((resolve: (data: FocusMoveResult) => void,
            reject: (err: BusinessError) => void): void => {
            let p1 = taskpool.execute(this.findElementsByConditionWithTypeNative, rule, condition, type) as Promise<FocusMoveResult>;
            p1.then((code: FocusMoveResult) => {
                console.log("resolve findElementsByCondition with type");
                resolve(code);
            }).catch((err: Error) => {
                reject(err as BusinessError);
            });
        });
    }

    executeAction(action: AccessibilityAction, parameters?: Parameter): Promise<void> {
        return new Promise<void>((resolve, reject): void => {
            let actualParameter: Parameter = parameters ?? new Parameter();
            taskpool.execute((): void => {
                this.executeActionNative(action, actualParameter);
            })
            .then((ret: Any): void => {
                resolve(ret as undefined);
            })
            .catch((ret: Any): void => {
                reject(ret as BusinessError);
            });
        });
    }

  getParent(): Promise<AccessibilityElement> {
    return new Promise<AccessibilityElement>((resolve: (data: AccessibilityElement) => void,
        reject: (err: BusinessError) => void): void => {
        let p1 = taskpool.execute(this.getParentNative) as Promise<AccessibilityElement>;
        p1.then((code: AccessibilityElement) => {
            resolve(code);
        }).catch((err: Error) => {
            reject(err as BusinessError);
        });
    });
  }

  getChildren(): Promise<Array<AccessibilityElement>> {
    return new Promise<Array<AccessibilityElement>>((resolve: (data: Array<AccessibilityElement>) => void,
        reject: (err: BusinessError) => void): void => {
            let p1 = taskpool.execute(this.getChildrenNative) as Promise<Array<AccessibilityElement>>;
            p1.then((code: Array<AccessibilityElement>) => {
                resolve(code);
            }).catch((err: Error) => {
                reject(err as BusinessError);
            });
        });
  }

  getRoot(): Promise<AccessibilityElement> {
    return new Promise<AccessibilityElement>((resolve: (data: AccessibilityElement) => void,
        reject: (err: BusinessError) => void): void => {
            let p1 = taskpool.execute(this.getRootNative) as Promise<AccessibilityElement>;
            p1.then((code: AccessibilityElement) => {
                resolve(code);
            }).catch((err: Error) => {
                reject(err as BusinessError);
            });
        });
  }

  findElementByContent(condition: string): Promise<Array<AccessibilityElement>> {
    return new Promise<Array<AccessibilityElement>>((resolve: (data: Array<AccessibilityElement>) => void,
        reject: (err: BusinessError) => void): void => {
            let p1 = taskpool.execute(this.findElementByContentNative, condition) as
                Promise<Array<AccessibilityElement>>;
            p1.then((code: Array<AccessibilityElement>) => {
                resolve(code);
            }).catch((err: Error) => {
                reject(err as BusinessError);
            });
        });
  }

  findElementByFocusDirection(condition: FocusDirection): Promise<AccessibilityElement> {
    return new Promise<AccessibilityElement>((resolve: (data: AccessibilityElement) => void,
        reject: (err: BusinessError) => void): void => {
            let p1 = taskpool.execute(this.findElementByFocusDirectionNative, condition) as Promise<AccessibilityElement>;
            p1.then((code: AccessibilityElement) => {
                resolve(code);
            }).catch((err: Error) => {
                reject(err as BusinessError);
            });
        });
  }

  findElementByFocusDirection(condition: FocusDirection, type: FocusRuleType): Promise<AccessibilityElement> {
    return new Promise<AccessibilityElement>((resolve: (data: AccessibilityElement) => void,
        reject: (err: BusinessError) => void): void => {
            let p1 = taskpool.execute(this.findElementByFocusDirectionWithTypeNative, condition, type) as Promise<AccessibilityElement>;
            p1.then((code: AccessibilityElement) => {
                resolve(code);
            }).catch((err: Error) => {
                reject(err as BusinessError);
            });
        });
  }

  findElementsByAccessibilityHintText(condition: string): Promise<Array<AccessibilityElement>> {
    return new Promise<Array<AccessibilityElement>>((resolve: (data: Array<AccessibilityElement>) => void,
        reject: (err: BusinessError) => void): void => {
            let p1 = taskpool.execute(this.findElementsByAccessibilityHintTextNative, condition) as
                Promise<Array<AccessibilityElement>>;
                p1.then((code: Array<AccessibilityElement>) => {
                resolve(code);
            }).catch((err: Error) => {
                reject(err as BusinessError);
            });
        });
  }


  findElementById(condition: long): Promise<AccessibilityElement> {
    return new Promise<AccessibilityElement>((resolve: (data: AccessibilityElement) => void,
        reject: (err: BusinessError) => void): void => {
            let p1 = taskpool.execute(this.findElementByIdNative, condition) as Promise<AccessibilityElement>;
            p1.then((code: AccessibilityElement) => {
                resolve(code);
            }).catch((err: Error) => {
                reject(err as BusinessError);
            });
        });
  }

    native getCursorPositionNative(): int;
    native enableScreenCurtainNative(isEnable: boolean): void;
    native findElementNative(type: string, condition: long): AccessibilityElement;
    native findElementsNative(type: string, condition: string): Array<AccessibilityElement>;
    native findElementsByConditionNative(rule: string, condition: string): FocusMoveResult;
    native findElementsByConditionWithTypeNative(rule: string, condition: string, type: FocusRuleType): FocusMoveResult;
    native executeActionNative(action: AccessibilityAction, parameters: Parameter): void;
    native getParentNative(): AccessibilityElement;
    native getChildrenNative(): Array<AccessibilityElement>;
    native getRootNative(): AccessibilityElement;
    native findElementByContentNative(condition: string): Array<AccessibilityElement>;
    native findElementByFocusDirectionNative(condition: FocusDirection): AccessibilityElement;
    native findElementByFocusDirectionWithTypeNative(condition: FocusDirection, type: FocusRuleType): AccessibilityElement;
    native findElementsByAccessibilityHintTextNative(condition: string): Array<AccessibilityElement>;
    native findElementByIdNative(condition: long): AccessibilityElement;
}

export interface AccessibilityGrid {
  rowIndex: int ;
  columnIndex: int ;
}

export class AccessibilityGridImpl implements AccessibilityGrid {
  rowIndex: int = 0;
  columnIndex: int = 0;
}

export interface AccessibilitySpan {
  spanId: int ;
  spanText: string;
  accessibilityText: string;
  accessibilityDescription: string;
  accessibilityLevel: string;
}

export class AccessibilitySpanImpl implements AccessibilitySpan {
  spanId: int = 0;
  spanText: string = '';
  accessibilityText: string = '';
  accessibilityDescription: string = '';
  accessibilityLevel: string = '';
}

export class Parameter {
    setText?: string = '';
    selectTextBegin?: string = '';
    selectTextEnd?: string = '';
    selectTextInForWard?: boolean = false;
    offset?: string = '';
    spanId?: string = '';
    scrollType?: string = '';
    injectActionType?: InjectActionType;
    customAction?: string = '';
    accessibilityFocusScene?: AccessibilityFocusScene;
}

export type FocusDirection = 'up' | 'down' | 'left' | 'right' | 'forward' | 'backward';

export type WindowType = 'application' | 'system';

export interface Rect {
  left: int;
  top: int;
  width: int;
  height: int;
}

export class RectImpl implements Rect {
    left: int = 0;
    top: int = 0;
    width: int = 0;
    height: int = 0;
}

export class TouchPosition {
  x:int = 0;
  y:int = 0;
}

export interface AccessibilityVirtualNode {
    virtualNodeId: long;
    text?: string;
    accessibilityText?: string;
    accessibilityGroup?: boolean;
    accessibilityLevel?: string;
    rect?: Rect;
    checkable?: boolean;
    checked?: boolean;
    clickable?: boolean;
    enabled?: boolean;
    selected?: boolean;
    customComponentType?: string;
    touchPosition?: TouchPosition;
    accessibilityFocused?: boolean;
    parentId?: long;
    childNodeIds?: Array<long>;
    elementId?: long;
    supportedActionNames?: Array<string>;
}

export class AccessibilityVirtualNodeImpl implements AccessibilityVirtualNode{
  virtualNodeId: long = 0;
  text?: string = "";
  accessibilityText?: string = "";
  accessibilityGroup?: boolean = false;
  accessibilityLevel?: string = "";
  rect?: Rect = new RectImpl();
  checkable?: boolean = false;
  checked?: boolean = false;
  clickable?: boolean = false;
  enabled?: boolean = false;
  selected?: boolean = false;
  customComponentType?: string = "";
  touchPosition?: TouchPosition = new TouchPosition();
  accessibilityFocused?: boolean = false;
  parentId?: long = 0;
  childNodeIds?: Array<long> = [];
  elementId?: long = 0;
  supportedActionNames?: Array<string> = [];
}

export enum OperateVirtualNodeResult {
  SUCCESS = 0,
  ACCESSIBILITY_ELEMENT_NOT_EXIST = 1,
  CANNOT_MODIFY_ROOT_NODE = 2,
  ACCESSIBILITY_PROPERTY_EMPTY = 3,
  ALLOCATE_ID_FAILED = 4,
  ADD_NODE_IS_EMPTY = 5,
  INTERNAL_ERROR = 6,
  VIRTUAL_NODE_NOT_SUPPORT = 7,
}