/*
Copyright 2024 New Vector Ltd.
Copyright 2022 The Matrix.org Foundation C.I.C.

SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/

import type { Room } from "matrix-js-sdk/src/matrix";
import type { EventEmitter } from "events";
import { type ITagMap, type ListAlgorithm, type SortAlgorithm } from "./algorithms/models";
import { type RoomUpdateCause } from "./models";
import { type TagID } from "../room-list-v3/skip-list/tag";
import { type IFilterCondition } from "./filters/IFilterCondition";

export enum RoomListStoreEvent {
    // The event/channel which is called when the room lists have been changed.
    ListsUpdate = "lists_update",
    // The event which is called when the room list is loading.
    // Called with the (tagId, bool) which is true when the list is loading, else false.
    ListsLoading = "lists_loading",
}

export interface RoomListStore extends EventEmitter {
    /**
     * Gets an ordered set of rooms for the all known tags.
     * @returns {ITagMap} The cached list of rooms, ordered,
     * for each tag. May be empty, but never null/undefined.
     */
    get orderedLists(): ITagMap;

    /**
     * Return the total number of rooms in this list. Prefer this method to
     * RoomListStore.orderedLists[tagId].length because the client may not
     * be aware of all the rooms in this list (e.g in Sliding Sync).
     * @param tagId the tag to get the room count for.
     * @returns the number of rooms in this list, or 0 if the list is unknown.
     */
    getCount(tagId: TagID): number;

    /**
     * Set the sort algorithm for the specified tag.
     * @param tagId the tag to set the algorithm for
     * @param sort the sort algorithm to set to
     */
    setTagSorting(tagId: TagID, sort: SortAlgorithm): void;

    /**
     * Get the sort algorithm for the specified tag.
     * @param tagId tag to get the sort algorithm for
     * @returns the sort algorithm
     */
    getTagSorting(tagId: TagID): SortAlgorithm | null;

    /**
     * Set the list algorithm for the specified tag.
     * @param tagId the tag to set the algorithm for
     * @param order the list algorithm to set to
     */
    setListOrder(tagId: TagID, order: ListAlgorithm): void;

    /**
     * Get the list algorithm for the specified tag.
     * @param tagId tag to get the list algorithm for
     * @returns the list algorithm
     */
    getListOrder(tagId: TagID): ListAlgorithm | null;

    /**
     * Regenerates the room whole room list, discarding any previous results.
     *
     * Note: This is only exposed externally for the tests. Do not call this from within
     * the app.
     * @param params.trigger Set to false to prevent a list update from being sent. Should only
     * be used if the calling code will manually trigger the update.
     */
    regenerateAllLists(params: { trigger: boolean }): void;

    /**
     * Adds a filter condition to the room list store. Filters may be applied async,
     * and thus might not cause an update to the store immediately.
     * @param {IFilterCondition} filter The filter condition to add.
     */
    addFilter(filter: IFilterCondition): Promise<void>;

    /**
     * Removes a filter condition from the room list store. If the filter was
     * not previously added to the room list store, this will no-op. The effects
     * of removing a filter may be applied async and therefore might not cause
     * an update right away.
     * @param {IFilterCondition} filter The filter condition to remove.
     */
    removeFilter(filter: IFilterCondition): void;

    /**
     * Manually update a room with a given cause. This should only be used if the
     * room list store would otherwise be incapable of doing the update itself. Note
     * that this may race with the room list's regular operation.
     * @param {Room} room The room to update.
     * @param {RoomUpdateCause} cause The cause to update for.
     */
    manualRoomUpdate(room: Room, cause: RoomUpdateCause): Promise<void>;
}
