/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module Views
 */
import { Id64, ObservableSet } from "@itwin/core-bentley";
import { ElementState } from "./EntityState";
/** A set of Categories to be displayed in a [[ViewState]].
 * Elements belonging to categories not specified in the category selector will not be drawn in the view.
 * By default, geometry belonging to any [[SubCategory]] of a visible Category is also visible in the view,
 * unless the [[SubCategoryAppearance]] or [[SubCategoryOverride]] specifies that it should be invisible.
 * @note To change the set of categories visible in a [[ViewState]] currently associated with a [[Viewport]],
 * use [[ViewState.changeCategoryDisplay]] to ensure the view updates appropriately on screen.
 * @see [[Category]]
 * @public
 * @extensions
 */
export class CategorySelectorState extends ElementState {
    static get className() { return "CategorySelector"; }
    constructor(props, iModel) {
        super(props, iModel);
        this._categories = new ObservableSet();
        if (props.categories)
            props.categories.forEach((cat) => this.categories.add(cat));
    }
    get categories() {
        return this._categories;
    }
    set categories(categories) {
        this._categories.clear();
        for (const category of categories)
            this._categories.add(category);
    }
    /** @internal */
    get observableCategories() {
        return this._categories;
    }
    toJSON() {
        const val = super.toJSON();
        val.categories = [];
        this.categories.forEach((cat) => val.categories.push(cat));
        return val;
    }
    /** Returns true if this category selector is logically equivalent to the specified category selector.
     * Two category selectors are logically equivalent if they have the same name and Id and contain the same set of category Ids.
     */
    equalState(other) {
        if (this.categories.size !== other.categories.size || this.name !== other.name || this.id !== other.id)
            return false;
        for (const cat of this.categories)
            if (!other.categories.has(cat))
                return false;
        return true;
    }
    /** The name of this CategorySelector */
    get name() { return this.code.value; }
    /** Determine whether this CategorySelector includes the specified categoryId string */
    has(id) { return this.categories.has(id); }
    /** Determine whether this CategorySelector includes the specified category */
    isCategoryViewed(categoryId) { return this.has(categoryId); }
    /** Add one or more categories to this CategorySelector */
    addCategories(arg) {
        for (const id of Id64.iterable(arg))
            this.categories.add(id);
    }
    /** Remove one or more categories from this CategorySelector */
    dropCategories(arg) {
        for (const id of Id64.iterable(arg))
            this.categories.delete(id);
    }
    /** Add or remove categories from this CategorySelector.
     * @param arg The categories to add or remove
     * @param add If true, categories will be added; otherwise they will be removed.
     */
    changeCategoryDisplay(arg, add) {
        if (add)
            this.addCategories(arg);
        else
            this.dropCategories(arg);
    }
}
//# sourceMappingURL=CategorySelectorState.js.map