// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
/**
 * returns an async iterator that iterates over results. It also has a `byPage`
 * method that returns pages of items at once.
 *
 * @param pagedResult - an object that specifies how to get pages.
 * @returns a paged async iterator that iterates over results.
 */
export function getPagedAsyncIterator(pagedResult) {
    const iter = getItemAsyncIterator(pagedResult);
    return {
        next() {
            return iter.next();
        },
        [Symbol.asyncIterator]() {
            return this;
        },
        byPage: pagedResult.byPage ??
            ((settings) => {
                const { continuationToken, maxPageSize } = settings ?? {};
                return getPageAsyncIterator(pagedResult, {
                    pageLink: continuationToken,
                    maxPageSize,
                });
            }),
    };
}
async function* getItemAsyncIterator(pagedResult) {
    const pages = getPageAsyncIterator(pagedResult);
    const firstVal = await pages.next();
    // if the result does not have an array shape, i.e. TPage = TElement, then we return it as is
    if (!Array.isArray(firstVal.value)) {
        // can extract elements from this page
        const { toElements } = pagedResult;
        if (toElements) {
            yield* toElements(firstVal.value);
            for await (const page of pages) {
                yield* toElements(page);
            }
        }
        else {
            yield firstVal.value;
            // `pages` is of type `AsyncIterableIterator<TPage>` but TPage = TElement in this case
            yield* pages;
        }
    }
    else {
        yield* firstVal.value;
        for await (const page of pages) {
            // pages is of type `AsyncIterableIterator<TPage>` so `page` is of type `TPage`. In this branch,
            // it must be the case that `TPage = TElement[]`
            yield* page;
        }
    }
}
async function* getPageAsyncIterator(pagedResult, options = {}) {
    const { pageLink, maxPageSize } = options;
    let response = await pagedResult.getPage(pageLink ?? pagedResult.firstPageLink, maxPageSize);
    if (!response) {
        return;
    }
    yield response.page;
    while (response.nextPageLink) {
        response = await pagedResult.getPage(response.nextPageLink, maxPageSize);
        if (!response) {
            return;
        }
        yield response.page;
    }
}
//# sourceMappingURL=getPagedAsyncIterator.js.map