// Copyright 2024 The Lynx Authors. All rights reserved.
// Licensed under the Apache License Version 2.0 that can be found in the
// LICENSE file in the root directory of this source tree.
import { hydrationMap } from '../../snapshot/snapshotInstanceHydrationMap.js';
/**
 * A flag to indicate whether UI operations should be delayed.
 * When set to true, UI operations will be queued in the `delayedUiOps` array
 * and executed later when `runDelayedUiOps` is called.
 * This is used before hydration to ensure UI operations are batched
 * and executed at the appropriate time.
 */
const shouldDelayUiOps = { value: true };
/**
 * An array of functions that will be executed later when `runDelayedUiOps` is called.
 * These functions contain UI operations that need to be delayed.
 */
const delayedUiOps = [];
/**
 * Runs a task either immediately or delays it based on the `shouldDelayUiOps` flag.
 * @param task - The function to execute.
 */
function runOrDelay(task) {
    if (shouldDelayUiOps.value) {
        delayedUiOps.push(task);
    }
    else {
        task();
    }
}
/**
 * Executes all delayed UI operations.
 */
function runDelayedUiOps() {
    const tasks = delayedUiOps.slice();
    delayedUiOps.length = 0;
    shouldDelayUiOps.value = false;
    for (const task of tasks) {
        task();
    }
}
/**
 * A proxy class designed for managing and executing reference-based tasks.
 * It delays the execution of tasks until hydration is complete.
 */
class RefProxy {
    refAttr;
    task;
    constructor(refAttr) {
        this.refAttr = refAttr;
        this.task = undefined;
        return new Proxy(this, {
            get: (target, prop, receiver) => {
                if (typeof prop === 'symbol'
                    || prop === 'then'
                    || prop in target
                    || typeof prop !== 'string') {
                    return Reflect.get(target, prop, receiver);
                }
                const forward = (method) => {
                    return (...args) => {
                        return new RefProxy(target.refAttr).setTask(method, args);
                    };
                };
                return forward(prop);
            },
        });
    }
    setTask(method, args) {
        this.task = (nodesRef) => {
            const nodesRefMethod = nodesRef[method];
            return nodesRefMethod.apply(nodesRef, args);
        };
        return this;
    }
    get selector() {
        const realRefId = hydrationMap.get(this.refAttr[0]) ?? this.refAttr[0];
        return `[react-ref-${realRefId}-${this.refAttr[1]}]`;
    }
    exec() {
        runOrDelay(() => {
            this.task(lynx.createSelectorQuery().select(this.selector)).exec();
        });
    }
}
/**
 * @internal
 */
export { RefProxy, runDelayedUiOps, shouldDelayUiOps };
//# sourceMappingURL=delay.js.map