"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Continuous = exports.makeSidepackedIntent = exports.makeStaticContinuousIntentsOf = exports.makeStaticIntent = void 0;
/**
 * Create a static intent.
 *
 * @param data - The data to wrap.
 * @returns A new static intent ready for use.
 */
function makeStaticIntent(data) {
    const intent = {
        $kind: "$static",
        $data: data,
    };
    return intent;
}
exports.makeStaticIntent = makeStaticIntent;
/**
 * Transform an array of data into an array of continuous static intents.
 *
 * @param elements - An array of data to wrap.
 * @returns A new static intent ready for use.
 */
function makeStaticContinuousIntentsOf(elements) {
    const intents = new Array();
    for (const element of elements) {
        intents.push(makeStaticIntent(Continuous.of(element)));
    }
    return intents;
}
exports.makeStaticContinuousIntentsOf = makeStaticContinuousIntentsOf;
/**
 * Create a sidepacked intent.
 *
 * @param data - The initial value to use before the provided intent is dispatched.
 * @param intent - The intent that JetEngine should resolve when rendered.
 * @returns A new sidepacked intent ready for use.
 */
function makeSidepackedIntent(initial, intent) {
    const sidepackedIntent = {
        $kind: "$sidepacked",
        $initial: initial,
        $intent: intent,
    };
    return sidepackedIntent;
}
exports.makeSidepackedIntent = makeSidepackedIntent;
// MARK: - Continuous
/**
 * A async iterable which allows an intent implementation to vend data
 * which changes over time, such as the state of a buy button,
 * or database-backed shelves on a page.
 *
 * Use `Continuous` to specify that an intent embedded in a model,
 * or passed to a view, vends data which changes over time instead
 * of being calculated once at the time the intent is dispatched.
 *
 * ```typescript
 * export interface Page extends PageModel {
 *   readonly shelves: Intent<Continuous<Shelf>>[];
 * }
 * ```
 *
 * A continuous async iterable can be created with a single element.
 * This allows a model built around continuous intents to still cleanly
 * represent data which will not change after being displayed the first time.
 *
 * ```typescript
 * const page: Page = {
 *   pageMetrics: notInstrumented(NotInstrumentedMetricsType.PageMetrics),
 *   shelves: [
 *     makeStaticIntent(Continuous.of(Shelf(...))),
 *   ]
 * };
 * ```
 * A continuous async iterable can be created with another `AsyncIterable`
 * as a backing data source:
 *
 * ```typescript
 * async function* timer(
 *   interval: number,
 *   start: number = 0,
 *   limit: number? = undefined,
 * ): AsyncIterator<number> {
 *   for (let next = start; next != limit; next++) {
 *     yield next;
 *     await setTimeout(interval);
 *   }
 * }
 *
 * const countToTen = Continuous.contentsOf(timer(1000, 0, 10));
 * ```
 *
 * A single element continuous async iterable can be stringified to JSON
 * as long the element itself has a valid JSON representation. This is
 * especially useful when combined with `StaticIntent`.
 *
 * ```typescript
 * const shelfIntent = makeStaticIntent(Continuous.of(Shelf(...)));
 * const jsonData = JSON.stringify(shelfIntent);
 * ```
 *
 * __Important__: A continuous async iterable which wraps another
 * async iterable cannot be directly JSON stringified.
 */
class Continuous {
    // MARK: - Constructors
    /**
     * Create a continuous async iterable with a single pre-determined element.
     *
     * @param element - A single element to yield from the new async iterable.
     * @returns A new continuous async iterable ready to use.
     */
    static of(element) {
        return new Continuous(new AsyncJust(element));
    }
    /**
     * Create a continuous async iterable by wrapping an async iterable.
     *
     * __Important__: A continuous async iterable which wraps another
     * async iterable cannot be directly JSON stringified.
     *
     * @param base - The async iterable to wrap.
     * @returns A new continuous async iterable ready to use.
     */
    static contentsOf(base) {
        return new Continuous(base);
    }
    /**
     * Construct a continuous async iterable by wrapping an async iterable.
     *
     * @param base - The async iterable to wrap.
     */
    constructor(base) {
        this.base = base;
        // Indicate to native that the true content of this object is in the base field under direct bridging where toJSON is not called.
        this["$wrappedField"] = "base";
    }
    // MARK: - JSON.stringify
    toJSON() {
        if (this.base instanceof AsyncJust) {
            return this.base.toJSON();
        }
        else {
            throw new TypeError("Continuous was not created with a single element");
        }
    }
    // MARK: - AsyncIterable
    async *[Symbol.asyncIterator]() {
        yield* this.base;
    }
}
exports.Continuous = Continuous;
/**
 * An asynchronous iterable which yields a single element.
 */
class AsyncJust {
    // MARK: - Constructors
    /**
     * Construct an async iterable containing just the given element.
     *
     * @param element - The only element to yield.
     */
    constructor(element) {
        this.element = element;
        // Indicate to native that the true content of this object is in the element field under direct bridging where toJSON is not called.
        this["$wrappedField"] = "element";
    }
    // MARK: - JSON.stringify
    toJSON() {
        return this.element;
    }
    // MARK: - AsyncIterable
    async *[Symbol.asyncIterator]() {
        yield this.element;
    }
}
//# sourceMappingURL=intent.js.map