<commit_before>// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * Updates listener.
 */
export interface CoreItemsListSourceListener<Item> {
    onItemsUpdated(items: Item[], hasMoreItems: boolean): void;
    onReset(): void;
}

/**
 * Items collection source data.
 */
export abstract class CoreItemsManagerSource<Item = unknown> {

    /**
     * Get a string to identify instances constructed with the given arguments as being reusable.
     *
     * @param args Constructor arguments.
     * @returns Id.
     */
    static getSourceId(...args: unknown[]): string {
        return args.map(argument => String(argument)).join('-');
    }

    private items: Item[] | null = null;
    private hasMoreItems = true;
    private listeners: CoreItemsListSourceListener<Item>[] = [];

    /**
     * Check whether any page has been loaded.
     *
     * @returns Whether any page has been loaded.
     */
    isLoaded(): boolean {
        return this.items !== null;
    }

    /**
     * Check whether there are more pages to be loaded.
     *
     * @return Whether there are more pages to be loaded.
     */
    isCompleted(): boolean {
        return !this.hasMoreItems;
    }

    /**
     * Get collection items.
     *
     * @returns Items.
     */
    getItems(): Item[] | null {
        return this.items;
    }

    /**
     * Get the count of pages that have been loaded.
     *
     * @returns Pages loaded.
     */
    getPagesLoaded(): number {
        if (this.items === null) {
            return 0;
        }

        return Math.ceil(this.items.length / this.getPageLength());
    }

    /**
     * Reset collection data.
     */
    reset(): void {
        this.items = null;
        this.hasMoreItems = true;

        this.listeners.forEach(listener => listener.onReset());
    }

    /**
     * Register a listener.
     *
     * @param listener Listener.
     * @returns Unsubscribe function.
     */
    addListener(listener: CoreItemsListSourceListener<Item>): () => void {
        this.listeners.push(listener);

        return () => this.removeListener(listener);
    }

    /**
     * Remove a listener.
     *
     * @param listener Listener.
     */
    removeListener(listener: CoreItemsListSourceListener<Item>): void {
        const index = this.listeners.indexOf(listener);

        if (index === -1) {
            return;
        }

        this.listeners.splice(index, 1);
    }

    /**
     * Reload the collection, this resets the data to the first page.
     */
    async reload(): Promise<void> {
        const { items, hasMoreItems } = await this.loadPageItems(0);

        this.setItems(items, hasMoreItems);
    }

    /**
     * Load items for the next page, if any.
     */
    async loadNextPage(): Promise<void> {
        if (!this.hasMoreItems) {
            return;
        }

        const { items, hasMoreItems } = await this.loadPageItems(this.getPagesLoaded());

        this.setItems((this.items ?? []).concat(items), hasMoreItems);
    }

    /**
     * Load page items.
     *
     * @param page Page number (starting at 0).
     * @return Page items data.
     */
    protected abstract loadPageItems(page: number): Promise<{ items: Item[]; hasMoreItems: boolean }>;

    /**
     * Get the length of each page in the collection.
     *
     * @return Page length.
     */
    protected abstract getPageLength(): number;

    /**
     * Update the collection items.
     *
     * @param items Items.<commit_msg>MOBILE-3926 core: Support non-paginated sources<commit_after>// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * Updates listener.
 */
export interface CoreItemsListSourceListener<Item> {
    onItemsUpdated(items: Item[], hasMoreItems: boolean): void;
    onReset(): void;
}

/**
 * Items collection source data.
 */
export abstract class CoreItemsManagerSource<Item = unknown> {

    /**
     * Get a string to identify instances constructed with the given arguments as being reusable.
     *
     * @param args Constructor arguments.
     * @returns Id.
     */
    static getSourceId(...args: unknown[]): string {
        return args.map(argument => String(argument)).join('-');
    }

    private items: Item[] | null = null;
    private hasMoreItems = true;
    private listeners: CoreItemsListSourceListener<Item>[] = [];

    /**
     * Check whether any page has been loaded.
     *
     * @returns Whether any page has been loaded.
     */
    isLoaded(): boolean {
        return this.items !== null;
    }

    /**
     * Check whether there are more pages to be loaded.
     *
     * @return Whether there are more pages to be loaded.
     */
    isCompleted(): boolean {
        return !this.hasMoreItems;
    }

    /**
     * Get collection items.
     *
     * @returns Items.
     */
    getItems(): Item[] | null {
        return this.items;
    }

    /**
     * Get the count of pages that have been loaded.
     *
     * @returns Pages loaded.
     */
    getPagesLoaded(): number {
        if (this.items === null) {
            return 0;
        }

        const pageLength = this.getPageLength();
        if (pageLength === null) {
            return 1;
        }

        return Math.ceil(this.items.length / pageLength);
    }

    /**
     * Reset collection data.
     */
    reset(): void {
        this.items = null;
        this.hasMoreItems = true;

        this.listeners.forEach(listener => listener.onReset());
    }

    /**
     * Register a listener.
     *
     * @param listener Listener.
     * @returns Unsubscribe function.
     */
    addListener(listener: CoreItemsListSourceListener<Item>): () => void {
        this.listeners.push(listener);

        return () => this.removeListener(listener);
    }

    /**
     * Remove a listener.
     *
     * @param listener Listener.
     */
    removeListener(listener: CoreItemsListSourceListener<Item>): void {
        const index = this.listeners.indexOf(listener);

        if (index === -1) {
            return;
        }

        this.listeners.splice(index, 1);
    }

    /**
     * Reload the collection, this resets the data to the first page.
     */
    async reload(): Promise<void> {
        const { items, hasMoreItems } = await this.loadPageItems(0);

        this.setItems(items, hasMoreItems);
    }

    /**
     * Load items for the next page, if any.
     */
    async loadNextPage(): Promise<void> {
        if (!this.hasMoreItems) {
            return;
        }

        const { items, hasMoreItems } = await this.loadPageItems(this.getPagesLoaded());

        this.setItems((this.items ?? []).concat(items), hasMoreItems);
    }

    /**
     * Load page items.
     *
     * @param page Page number (starting at 0).
     * @return Page items data.
     */
    protected abstract loadPageItems(page: number): Promise<{ items: Item[]; hasMoreItems: boolean }>;

    /**
     * Get the length of each page in the collection.
     *
     * @return Page length; null for collections that don't support pagination.
     */
    protected getPageLength(): number | null {
        return null;
    }

    /**
     * Update the collection items.
     *
     * @param items Items.
{'fraction_non_alphanumeric': 0.11844495579508296, 'fraction_numerical': 0.00375439021436357, 'mean_word_length': 2.1737125288239816, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6813365', 'n_tokens_mistral': 2326, 'n_tokens_neox': 2248, 'n_words': 720}