export var RenderingState;
(function (RenderingState) {
    RenderingState[RenderingState["Idle"] = 0] = "Idle";
    RenderingState[RenderingState["Rendering"] = 1] = "Rendering";
})(RenderingState || (RenderingState = {}));
export const renderFn = Symbol('renderFn');
/**
 * A class that manages rendering of the application screen.
 */
export class Renderer {
    /**
     * The root element where the activity or fragment will be rendered.
     */
    renderRoot = null;
    /**
     * @type A promise resolved when the render finished.
     */
    get updateComplete() {
        return this.#updateComplete;
    }
    /**
     * Sets the root element where the application will be rendered.
     * @param renderRoot The root element or its selector.
     */
    setRenderRoot(renderRoot) {
        if (typeof renderRoot === 'string') {
            this.renderRoot = document.querySelector(renderRoot);
        }
        else {
            this.renderRoot = renderRoot;
        }
    }
    /**
     * Requests an update of the application UI. This will call the `render()` method
     * and update the DOM.
     */
    requestUpdate() {
        if (this.#renderingState !== RenderingState.Idle) {
            // An update is already scheduled.
            return;
        }
        this.#renderingState = RenderingState.Rendering;
        if (!this.#hasPendingUpdatePromise) {
            this.#setUpdatePromise();
        }
        requestAnimationFrame(() => {
            this[renderFn]();
            this.#renderingState = RenderingState.Idle;
        });
    }
    firstRenderedFlag = false;
    /**
     * Determines whether the initial render had run and the `onFirstRender()`
     * function was called.
     */
    get firstRendered() {
        return this.firstRenderedFlag;
    }
    /**
     * A flag used to determine in which rendering state the UI is.
     */
    #renderingState = RenderingState.Idle;
    /**
     * A flag that helps to determine whether the `updateComplete` is setup.
     */
    #hasPendingUpdatePromise = false;
    /**
     * A hidden value for the `updateComplete` getter.
     */
    #updateComplete;
    /**
     * The resolver to call when the update completes.
     */
    #updateResolver;
    #setUpdatePromise() {
        this.#updateComplete = new Promise((resolve) => {
            this.#updateResolver = resolve;
            this.#hasPendingUpdatePromise = true;
        });
    }
    resolveUpdatePromise() {
        if (!this.#hasPendingUpdatePromise) {
            return;
        }
        this.#hasPendingUpdatePromise = false;
        const resolver = this.#updateResolver;
        if (resolver) {
            resolver();
        }
    }
}
//# sourceMappingURL=Renderer.js.map