// (C) 2019-2026 GoodData Corporation
import { difference } from "lodash-es";
import { invariant } from "ts-invariant";
import { resolveValueOrUpdateCallback } from "@gooddata/sdk-backend-base";
import { isDashboardLayoutSection, } from "@gooddata/sdk-model";
import { getItemIndex } from "../../../layout/coordinates.js";
import { DashboardLayoutItemBuilder } from "./item.js";
/**
 * @alpha
 */
export class DashboardLayoutSectionBuilder {
    sectionIndex;
    getSectionFacade;
    setLayout;
    constructor(sectionIndex, getSectionFacade, setLayout) {
        this.sectionIndex = sectionIndex;
        this.getSectionFacade = getSectionFacade;
        this.setLayout = setLayout;
    }
    /**
     * Creates an instance of DashboardLayoutSectionBuilder for particular layout item.
     */
    static for(layoutBuilder, sectionIndex) {
        invariant(isDashboardLayoutSection(layoutBuilder.facade().sections().section(sectionIndex)?.raw()), `Provided data must be IDashboardLayoutSection.`);
        return new DashboardLayoutSectionBuilder(sectionIndex, () => layoutBuilder.facade().section(sectionIndex), (layout) => layoutBuilder.setLayout(layout));
    }
    header(valueOrUpdateCallback) {
        return this.setSection((section) => ({
            ...section,
            header: resolveValueOrUpdateCallback(valueOrUpdateCallback, section.header),
        }));
    }
    createItem(xlSize, create = (v) => v, index = this.facade().items().count()) {
        const emptyItem = {
            type: "IDashboardLayoutItem",
            size: {
                xl: xlSize,
            },
        };
        this.setSection((section) => {
            const updatedItems = [...section.items];
            updatedItems.splice(index, 0, emptyItem);
            return {
                ...section,
                items: updatedItems,
            };
        });
        DashboardLayoutItemBuilder.for(this, index).modify(create);
        return this;
    }
    addItem(item, index = this.facade().items().count()) {
        this.setSection((section) => {
            const updatedItems = [...section.items];
            updatedItems.splice(index, 0, item);
            return {
                ...section,
                items: updatedItems,
            };
        });
        return this;
    }
    modifyItem(index, modify) {
        const itemFacade = this.facade().items().item(index);
        invariant(itemFacade, `Cannot modify the item - item at index ${index} does not exist.`);
        DashboardLayoutItemBuilder.for(this, index).modify(modify);
        return this;
    }
    removeItem(index) {
        const itemFacade = this.facade().items().item(index);
        invariant(itemFacade, `Cannot remove the item - item at index ${index} does not exist.`);
        return this.setSection((section) => {
            const updatedItems = [...section.items];
            updatedItems.splice(index, 1);
            return {
                ...section,
                items: updatedItems,
            };
        });
    }
    moveItem(fromIndex, toIndex) {
        const itemFacade = this.facade().item(fromIndex);
        invariant(itemFacade, `Cannot move the item - item at index ${fromIndex} does not exist.`);
        const maxToIndex = Math.min(toIndex, this.facade().items().count() - 1);
        this.removeItem(fromIndex);
        this.createItem(itemFacade.sizeForScreen("xl"), (c) => c.setItem(itemFacade.raw()), maxToIndex);
        return this;
    }
    removeItems(selector = (items) => items.all()) {
        const itemsToRemove = selector(this.facade().items());
        if (Array.isArray(itemsToRemove)) {
            this.setSection((section) => {
                const updatedItems = difference(section.items, itemsToRemove.map((r) => r.raw()));
                return {
                    ...section,
                    items: updatedItems,
                };
            });
        }
        else if (itemsToRemove) {
            this.removeItem(getItemIndex(itemsToRemove.index()));
        }
        return this;
    }
    removeEmptyItems = () => {
        return this.removeItems((items) => items.filter((item) => item.isEmpty()));
    };
    modifyItems(modify, selector = (items) => items.all()) {
        const itemsToModify = selector(this.facade().items());
        if (Array.isArray(itemsToModify)) {
            itemsToModify.forEach((item) => {
                this.modifyItem(getItemIndex(item.index()), modify);
            });
        }
        else if (itemsToModify) {
            this.modifyItem(getItemIndex(itemsToModify.index()), modify);
        }
        return this;
    }
    setSection(valueOrUpdateCallback) {
        this.setLayout((layout) => {
            const updatedRows = [...layout.sections];
            updatedRows[this.sectionIndex] = resolveValueOrUpdateCallback(valueOrUpdateCallback, this.build());
            return {
                ...layout,
                sections: updatedRows,
            };
        });
        return this;
    }
    facade() {
        return this.getSectionFacade();
    }
    modify(modifications) {
        modifications(this, this.facade());
        return this;
    }
    build() {
        return this.facade().raw();
    }
}
//# sourceMappingURL=section.js.map