/*---------------------------------------------------------------------------------------------
 * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
 * See LICENSE.md in the project root for license terms and full copyright notice.
 *--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module StatusBar
 */
import { ConditionalBooleanValue, ConditionalStringValue, } from "@itwin/appui-abstract";
import { BeEvent } from "@itwin/core-bentley";
const isInstance = (args) => {
    return !Array.isArray(args);
};
/**
 * Controls status bar items.
 * @internal
 */
export class StatusBarItemsManager {
    _items = [];
    constructor(items) {
        if (items)
            this.loadItemsInternal(items, true, false);
    }
    /** Event raised when StatusBar items are changed.
     * @internal
     */
    onItemsChanged = new BeEvent();
    loadItemsInternal(items, processConditions, sendItemChanged) {
        if (processConditions && items) {
            const eventIds = StatusBarItemsManager.getSyncIdsOfInterest(items);
            if (0 !== eventIds.length) {
                const { itemsUpdated, updatedItems } = this.internalRefreshAffectedItems(items, new Set(eventIds));
                if (itemsUpdated)
                    items = updatedItems;
            }
        }
        this._items = items;
        if (sendItemChanged)
            this.onItemsChanged.raiseEvent({ items });
    }
    /** load items but do not fire onItemsChanged
     * @internal
     */
    loadItems(items) {
        this.loadItemsInternal(items, true, false);
    }
    /** Get an array of the StatusBar items  */
    get items() {
        return this._items;
    }
    set items(items) {
        if (items !== this._items)
            this.loadItemsInternal(items, true, true);
    }
    add(itemOrItems) {
        let itemsToAdd;
        if (isInstance(itemOrItems))
            itemsToAdd = [itemOrItems];
        else {
            itemsToAdd = itemOrItems.filter((itemToAdd, index) => itemOrItems.findIndex((item) => item.id === itemToAdd.id) === index);
        }
        itemsToAdd = itemsToAdd.filter((itemToAdd) => this._items.find((item) => item.id === itemToAdd.id) === undefined);
        if (itemsToAdd.length === 0)
            return;
        const items = [...this._items, ...itemsToAdd];
        this.items = items;
    }
    /** Remove StatusBar items based on id */
    remove(itemIdOrItemIds) {
        const items = this._items.filter((item) => {
            return isInstance(itemIdOrItemIds)
                ? item.id !== itemIdOrItemIds
                : !itemIdOrItemIds.find((itemId) => itemId === item.id);
        });
        this.items = items;
    }
    /** @internal */
    removeAll() {
        this._items = [];
    }
    static getSyncIdsOfInterest(items) {
        const eventIds = new Set();
        items.forEach((item) => {
            for (const [, entry] of Object.entries(item)) {
                if (entry instanceof ConditionalBooleanValue) {
                    entry.syncEventIds.forEach((eventId) => eventIds.add(eventId.toLowerCase()));
                }
                else if (entry instanceof ConditionalStringValue) {
                    entry.syncEventIds.forEach((eventId) => eventIds.add(eventId.toLowerCase()));
                }
            }
        });
        return [...eventIds.values()];
    }
    internalRefreshAffectedItems(items, eventIds) {
        if (0 === eventIds.size)
            return { itemsUpdated: false, updatedItems: [] };
        let updateRequired = false;
        const newItems = [];
        for (const item of items) {
            const updatedItem = { ...item };
            for (const [, entry] of Object.entries(updatedItem)) {
                if (entry instanceof ConditionalBooleanValue) {
                    if (ConditionalBooleanValue.refreshValue(entry, eventIds))
                        updateRequired = true;
                }
                else if (entry instanceof ConditionalStringValue) {
                    if (ConditionalStringValue.refreshValue(entry, eventIds))
                        updateRequired = true;
                }
            }
            newItems.push(updatedItem);
        }
        return { itemsUpdated: updateRequired, updatedItems: newItems };
    }
    refreshAffectedItems(eventIds) {
        if (0 === eventIds.size)
            return;
        const { itemsUpdated, updatedItems } = this.internalRefreshAffectedItems(this.items, eventIds);
        if (itemsUpdated)
            this.loadItemsInternal(updatedItems, false, true);
    }
}
//# sourceMappingURL=StatusBarItemsManager.js.map