declare global {
  // TODO 这两个应该在 @vue/runtime-vapor-dom2 中
  type UniElementBlock = unknown
  type UniNativeViewBlock = unknown

  type UniSharedDataJSONObject = Record<string, any | null>
  type UniSharedDataArray = Array<UniSharedDataAny>

  type UniSharedDataAny =
    | boolean
    | number
    | string
    | null
    | UniSharedData
    | UniSharedDataJSONObject
    | UniSharedDataArray
    | UniSharedDataFunctionEventListener
    | UniSharedDataFunctionSetTemplateRef

  type UniSharedDataFunctionEventListener = (event: UniEvent) => void
  type UniSharedDataFunctionSetTemplateRef = (el: UniElement) => void

  class UniSharedData {
    /**
     * 所属文件
     * @internal
     */
    _filename?: string | null
    /**
     * ArkTS/Kotlin/JavaScript 层数据缓存，主要用于判断属性值是否有变化
     * @internal
     */
    _cacheProps: Map<string, UniSharedDataAny>
    /**
     * 所属页面，用于批量执行响应式变更
     * @internal
     */
    _scope: UniSharedDataPage
    /**
     * 是否已初始化完成，主要用于二次更新时触发响应式
     * @internal
     */
    _setReady(): void
    /**
     * 属性变更时收集 Jobs
     * @internal
     */
    _queueJobs: (key: string) => void
    /**
     * 设置 callMethod，用于 script cpp 调用 $callMethod 方法
     * @internal
     */
    _setCallMethod(fn: (...args: any[]) => void): void
    /**
     * 重置当前数据对象的所有标记位
     * @internal
     */
    _resetFlags(): void
    /**
     * 设置数据对象的属性值，并触发响应式更新（目前仅kotlin使用）
     * @param key
     * @param value
     */
    _setData(key: string, value: any | null): void
    constructor(scope: UniSharedDataPage)
  }

  enum UniSharedDataComponentStyleIsolation {
    Isolated,
    App,
    AppAndPage,
  }

  enum UniSharedDataComponentRenderer {
    Component,
    Page,
  }

  enum UniSharedDataComponentFlatten {
    None,
    True,
    False,
  }

  interface UniSharedDataComponentOptions {
    vueId: number
    styleIsolation: UniSharedDataComponentStyleIsolation
    renderer: UniSharedDataComponentRenderer
    flatten: UniSharedDataComponentFlatten
  }

  abstract class UniSharedDataComponent extends UniSharedData {
    /**
     * 组件的类名
     */
    static className: string
    /**
     * 当前页面或组件的样式表
     * @internal
     */
    static styleSheet: Map<string, Map<string, Map<number, any>>>
    /**
     * vue实例ID
     * @internal
     */
    _vueId: number
    /**
     * 当前页面或组件关联的 UniPage 对象
     * @internal
     */
    _page: UniPage
    /**
     * 当前组件所在的上下文，主要用于查找上下文组件的样式表
     * @internal
     */
    _ctx: UniSharedDataComponent | null
    /**
     * 当前组件或页面样式隔离策略
     */
    _styleIsolation: UniSharedDataComponentStyleIsolation
    /**
     * 当前组件实例是否拍平
     */
    _flatten: UniSharedDataComponentFlatten
    /**
     * 当前组件或页面渲染类型，页面也有可能作为组件来渲染
     */
    _renderer: UniSharedDataComponentRenderer
    /**
     * 自定义组件需要透传的属性
     * @internal
     */
    _inheritAttrs: UniSharedDataJSONObject
    constructor(scope: UniSharedDataPage, options: UniSharedDataComponentOptions)
    /**
     * 自定义组件需要透传的属性，需要暴露给前端设置: set_inheritAttrs()
     * @param attrs
     */
    set_inheritAttrs(attrs: UniSharedDataJSONObject): void
    /**
     * 监听组件根节点样式变更
     * @internal
     */
    useComputedStyle(options: {
      properties: number[]
      filterProperties?: boolean | null
      callback: (result: Array<[string, any | null]>) => void
    }): Map<string, any | null>
    /**
     * 目前仅限 android 平台
     * c层实现时，对数据暂存_textLayouts中，后批量flush同步至kotlin层
     * kt层由编译器生成
     * 接收三个参数：fid, eid, nodeId
     * 需要将接收到的数据存储到 scope 的 _textLayouts 中，每4个一组
     * [vueId, fid, eid, nodeId, vueId, fid, eid, nodeId, ...]
     * @internal
     */
    _createTextLayout(fid: number, eid: number, nodeId: number): void
    /**
     * 由编译器动态生成的子类中的 Element 渲染器，C层
     * @internal
     */
    _renderElement(): UniElementBlock
    /**
     * @internal
     */
    _dispose(): void

    /**
     * 由编译器动态生成的子类中的 Kotlin Element 渲染器，kt层
     * @internal
     */
    _renderKotlinElement(): UniElementBlock

    /**
     * 由编译器动态生成的子类中的 NativeView 渲染器，android平台是kt层，其他平台是c层
     * @internal
     */
    abstract _renderNativeView(): UniNativeViewBlock
  }

  abstract class UniSharedDataPage extends UniSharedDataComponent {
    /**
     * 当前页面内的组件样式缓存，主要用于缓存组件的样式表，避免重复计算
     * key 是组件class名称
     * @internal
     */
    _styleSheetCache: Map<string, Map<string, Map<string, Map<string, unknown>>>>
    /**
     * 本次更新收集到的element Jobs，用于批量执行响应式变更(c层)
     * @internal
     */
    _elementJobs: Array<ReactiveEffect<any | null>>
    /**
     * 本次更新收集到的kotlin element Jobs，用于批量执行响应式变更
     * @internal
     */
    _kotlinElementJobs: Array<ReactiveEffect<any | null>>
    /**
     * 本次更新收集到的nativeView Jobs，用于批量执行响应式变更
     * @internal
     */
    _nativeViewJobs: Array<ReactiveEffect<any | null>>
    /**
     * 目前仅限 android 平台
     * 文本布局缓存数组
     * [vueId, fid, eid, nodeId, vueId, fid, eid, nodeId, ...]
     * @internal
     */
    _textLayouts: IntArray

    constructor(pageIdOrScope: number | UniSharedDataPage, options: UniSharedDataComponentOptions)
    /**
     * 批量执行响应式变更
     * @internal
     */
    _flushJobs: () => Promise<void> | void
    /**
     * 页面渲染函数
     * 调用页面的 _renderElement 和 _renderNativeView
     * 执行 Element 渲染器（子线程执行）和 NativeView 渲染器（主线程执行）
     * 拿到两个渲染器执行后的 Block 后，插入到页面的根 NativeView 和根 Dom元素中
     * @internal
     */
    _render: () => Promise<void>
    /**
     * 目前仅限 android 平台，c层调用该kt方法同步批量创建textLayout
     * 批量同步文本布局至kotlin层，kotlin层会根据data数组进行处理（编译器生成指定函数switch执行具体的创建逻辑）
     * 需要确保调用时机（确保在排版之前同步触发）：
     * 当页面首次渲染时，在调用c层renderElement之后同步调用
     * 当页面二次更新时，在flushJobs中所有element jobs执行完之后调用
     * @internal
     */
    _flushTextLayouts(data: IntArray): void
  }

  abstract class UniSharedDataApp extends UniSharedData {
    /**
     * 当前应用全局样式
     * @internal
     */
    static styleSheet: Map<string, Map<string, Map<number, any>>>
  }

  enum UniSharedDataVForDirty {
    /**
     * 无变更
     */
    NONE,
    /**
     * 快速变更模式，读取 mount、unmount、update的列表，进行快速更新
     */
    FAST,
    /**
     * 全量模式，触发数组全量diff更新
     */
    FULL,
  }

  type UniSharedDataVForMount = {
    readonly index: number
  }

  type UniSharedDataVForUnmount = {
    /**
     * 需要移除的索引值
     * 重要：该索引值是oldBlocks中的索引值
     */
    readonly index: number
    readonly doRemove: boolean
    readonly doDeregister: boolean
  }

  type UniSharedDataVForUpdate = {
    /**
     * 需要更新的索引值
     * update((newBlocks[index] = oldBlocks[oldIndex]), getItem(source, i))
     */
    readonly index: number
    /**
     * 旧索引值
     */
    readonly oldIndex: number
  }

  class UniSharedDataVFor<T extends UniSharedData = UniSharedData> extends UniSharedData {
    setData(data: T[]): void
    setMount(mount: UniSharedDataVForMount[]): void
    setUnmount(unmount: UniSharedDataVForUnmount[]): void
    setUpdate(update: UniSharedDataVForUpdate[]): void
    setDirty(dirty: UniSharedDataVForDirty): void
    create: () => T
    constructor(scope: UniSharedDataPage)
  }

  enum TrackOpTypes {
    GET = "get",
    HAS = "has",
    ITERATE = "iterate",
  }

  class VueReactivity {
    track(target: object, type: TrackOpTypes, key: unknown): void
  }
  const __elementVueReactivity: VueReactivity
  const __nativeViewVueReactivity: VueReactivity

  const TEXT_LAYOUT_INDEX_VUE_ID = 0
  const TEXT_LAYOUT_INDEX_FID = 1
  const TEXT_LAYOUT_INDEX_EID = 2
  const TEXT_LAYOUT_INDEX_NODE_ID = 3

  // 编译宏

  interface UniSharedDataRegistry {}

  type InferSharedData<T, R extends UniSharedData = UniSharedData> = T extends keyof UniSharedDataRegistry ? UniSharedDataRegistry[T] : R

  function useSharedData<T extends string>(scope: UniSharedDataPage, options?: UniDynamicSharedDataInitOptions): InferSharedData<T>

  function useSharedDataPage<T extends string>(
    pageIdOrScope: number | UniSharedDataPage,
    options: UniSharedDataComponentOptions,
  ): InferSharedData<T, UniSharedDataPage>

  function useSharedDataComponent<T extends string>(
    scope: UniSharedDataPage,
    options: UniSharedDataComponentOptions,
  ): InferSharedData<T, UniSharedDataComponent>

  function useSharedDataVFor<T, S extends UniSharedData>(sharedDataVFor: UniSharedData): S

  function useSharedDataRecycleVFor<T, S extends UniSharedData>(sharedDataVFor: UniSharedData): S
  // android kotlin 属性委托
  function observable(): any
}

declare global {
  /**
   * 动态 sharedData 字段定义。
   *
   * 这里保留最小运行时需要的信息：
   * - fieldId：字段编号
   * - flagGroupId：所在 flag group
   * - flagBit：所在 bit
   */
  interface UniSharedDataDynamicFieldDefinition {
    /**
     * 当前 template 内唯一的字段编号。
     */
    readonly fieldId: number

    /**
     * 该字段对应的 flag group 编号。
     */
    readonly flagGroupId: number

    /**
     * 该字段在 flag group 中对应的 bit。
     */
    readonly flagBit: number
  }

  /**
   * 动态 sharedData class 定义。
   *
   * 用于：
   * - 构造动态 sharedData 实例时初始化字段槽
   * - 初始化 flag group
   * - 调试 / 诊断 / 宿主校验
   */
  interface UniDynamicSharedDataClassDefinition {
    /**
     * 对齐静态 sharedData class 的名称。
     *
     * 主要用于调试、日志和对照，不参与热路径判断。
     */
    readonly sharedDataClassName: string

    /**
     * 当前 template 内唯一的 sharedData class 编号。
     *
     * root page / root component 固定为 0。
     */
    readonly sharedDataClassId: number

    /**
     * 当前 class 的字段数量。
     */
    readonly fieldCount: number

    /**
     * 当前 class 的 flag group 数量。
     */
    readonly flagGroupCount: number

    /**
     * 当前 class 的字段定义。
     */
    readonly fields: ReadonlyArray<UniSharedDataDynamicFieldDefinition>
  }

  /**
   * 动态 sharedData 的初始化参数。
   *
   * 这是 renderSharedData 直接使用的构造参数。
   */
  interface UniDynamicSharedDataInitOptions {
    /**
     * 当前动态 bundle 的稳定标识。
     */
    readonly bundleKey: string

    /**
     * 当前实例对应的 sharedData class 编号。
     *
     * 约束：
     * - root page：0
     * - root component：0
     * - scoped sharedData：编译器分配的实际 classId
     */
    readonly sharedDataClassId: number
  }

  interface UniDynamicSharedDataComponentOptions extends UniSharedDataComponentOptions, UniDynamicSharedDataInitOptions {}

  /**
   * UniDynamicSharedDataState 的初始化参数。
   *
   * 这是宿主真实实现类在内部创建 state 时使用的参数。
   * renderSharedData 不直接传这个对象。
   */
  interface UniDynamicSharedDataStateOptions extends UniDynamicSharedDataInitOptions {
    /**
     * 按 bundleKey 读取原始二进制 bytes。
     *
     * 只负责读取 bytes。
     * 缓存、decode、classDefinition 查询真实实现由 C++ / Kotlin 原生侧完成。
     */
    readonly loadBundleBytes: (bundleKey: string) => Uint8Array
  }

  /**
   * 普通动态 sharedData 的最小读取协议。
   *
   * 解释器只依赖这些读取能力。
   */
  interface IUniDynamicSharedData {
    /**
     * 当前实例所属 bundleKey。
     */
    readonly _bundleKey: string

    /**
     * 当前实例对应的 sharedData class 编号。
     */
    readonly _sharedDataClassId: number

    /**
     * 当前实例绑定的 class 定义。
     */
    readonly _sharedDataClass: UniDynamicSharedDataClassDefinition

    /**
     * 按字段编号读取值。
     */
    getField(fieldId: number): UniSharedDataAny

    /**
     * 按 flag group 编号读取脏标记位图。
     */
    getFlag(flagGroupId: number): number
  }

  /**
   * 动态组件 sharedData 的最小读取协议。
   *
   * 对齐静态 renderer 会直接读取的 builtin。
   */
  interface IUniDynamicSharedDataComponent extends IUniDynamicSharedData {
    getVueId(): number
    getFlatten(): UniSharedDataComponentFlatten
    getRenderer(): UniSharedDataComponentRenderer
  }

  /**
   * 动态页面 sharedData 的最小读取协议。
   *
   * 当前阶段 page 不额外增加读取面，直接继承 component 协议。
   */
  interface IUniDynamicSharedDataPage extends IUniDynamicSharedDataComponent {}

  /**
   * 动态 sharedData 的运行时状态对象。
   *
   * 职责：
   * - load bytes
   * - bundle cache
   * - decode
   * - sharedDataClassId -> classDefinition
   * - 字段值存储
   * - flags 存储
   * - render callback 执行
   */
  class UniDynamicSharedDataState {
    constructor(owner: IUniDynamicSharedData | IUniDynamicSharedDataComponent | IUniDynamicSharedDataPage, options: UniDynamicSharedDataStateOptions)

    /**
     * 当前实例绑定的 classDefinition。
     */
    getClassDefinition(): UniDynamicSharedDataClassDefinition

    /**
     * 读取字段值。
     */
    getField(fieldId: number): UniSharedDataAny

    /**
     * 读取 flag group。
     */
    getFlag(flagGroupId: number): number

    /**
     * 写字段值。
     *
     * 返回值表示该写入是否产生有效变化。
     */
    setField(fieldId: number, value: UniSharedDataAny | null): boolean

    /**
     * 清空当前实例的 flags。
     */
    resetFlags(): void

    /**
     * 执行动态 renderElement callback。
     *
     * 返回值必须和静态渲染一致。
     */
    renderElement(): UniElementBlock

    /**
     * 执行动态 renderKotlinElement callback。
     *
     * 返回值必须和静态渲染一致。
     */
    renderKotlinElement(): UniElementBlock

    /**
     * 执行动态 renderNativeView callback。
     *
     * 返回值必须和静态渲染一致。
     */
    renderNativeView(): UniNativeViewBlock
  }

  /**
   * 普通动态 scope sharedData。
   *
   * 真实实现由宿主仓库提供。
   * renderSharedData 会直接 new 该类。
   */
  class UniDynamicSharedData extends UniSharedData implements IUniDynamicSharedData {
    readonly _bundleKey: string
    readonly _sharedDataClassId: number
    readonly _sharedDataClass: UniDynamicSharedDataClassDefinition
    readonly _dynamicState: UniDynamicSharedDataState

    constructor(scope: UniSharedDataPage, dynamicOptions: UniDynamicSharedDataInitOptions)

    getField(fieldId: number): UniSharedDataAny
    getFlag(flagGroupId: number): number

    /**
     * 仅做类型，动态 sharedData 不支持按 name 写入。
     */
    _setData(name: string, value: UniSharedDataAny | null): void
    /**
     * 动态渲染始终按 fieldId 写入。
     */
    _setData(fieldId: number, value: UniSharedDataAny | null): void

    /**
     * 对齐静态 sharedData 生命周期。
     */
    _resetFlags(): void

    /**
     * 保持和静态渲染一致的 callback 入口。
     */
    _renderElement(): UniElementBlock
    _renderKotlinElement(): UniElementBlock
    _renderNativeView(): UniNativeViewBlock
  }

  /**
   * 动态组件 root sharedData。
   *
   * renderSharedData 会直接 new 该类，
   * 且 sharedDataClassId 固定为 0。
   */
  class UniDynamicSharedDataComponent extends UniSharedDataComponent implements IUniDynamicSharedDataComponent {
    readonly _bundleKey: string
    readonly _sharedDataClassId: number
    readonly _sharedDataClass: UniDynamicSharedDataClassDefinition
    readonly _dynamicState: UniDynamicSharedDataState

    constructor(scope: UniSharedDataPage, options: UniDynamicSharedDataComponentOptions)

    getField(fieldId: number): UniSharedDataAny
    getFlag(flagGroupId: number): number
    getVueId(): number
    getFlatten(): UniSharedDataComponentFlatten
    getRenderer(): UniSharedDataComponentRenderer
    /**
     * 仅做类型，动态 sharedData 不支持按 name 写入。
     */
    _setData(name: string, value: UniSharedDataAny | null): void
    /**
     * 动态渲染始终按 fieldId 写入。
     */
    _setData(fieldId: number, value: UniSharedDataAny | null): void

    _resetFlags(): void

    _renderElement(): UniElementBlock
    _renderKotlinElement(): UniElementBlock
    _renderNativeView(): UniNativeViewBlock
  }

  /**
   * 动态页面 root sharedData。
   *
   * renderSharedData 会直接 new 该类，
   * 且 sharedDataClassId 固定为 0。
   */
  class UniDynamicSharedDataPage extends UniSharedDataPage implements IUniDynamicSharedDataPage {
    readonly _bundleKey: string
    readonly _sharedDataClassId: number
    readonly _sharedDataClass: UniDynamicSharedDataClassDefinition
    readonly _dynamicState: UniDynamicSharedDataState

    constructor(pageIdOrScope: number | UniSharedDataPage, options: UniDynamicSharedDataComponentOptions)

    getField(fieldId: number): UniSharedDataAny
    getFlag(flagGroupId: number): number
    getVueId(): number
    getFlatten(): UniSharedDataComponentFlatten
    getRenderer(): UniSharedDataComponentRenderer

    /**
     * 仅做类型，动态 sharedData 不支持按 name 写入。
     */
    _setData(name: string, value: UniSharedDataAny | null): void
    /**
     * 动态渲染始终按 fieldId 写入。
     */
    _setData(fieldId: number, value: UniSharedDataAny | null): void
    _resetFlags(): void

    _renderElement(): UniElementBlock
    _renderKotlinElement(): UniElementBlock
    _renderNativeView(): UniNativeViewBlock
  }
}

export {}
