// (C) 2021-2026 GoodData Corporation
import { cloneDeep, isEmpty } from "lodash-es";
import { objRefToString, } from "@gooddata/sdk-model";
import { DashboardLayoutBuilder } from "../../_staging/dashboard/flexibleLayout/builder/layout.js";
export class FluidLayoutCustomizer {
    logger;
    mutationContext;
    addItemOps = [];
    addSectionOps = [];
    constructor(logger, mutationContext) {
        this.logger = logger;
        this.mutationContext = mutationContext;
    }
    addItem(sectionIdx, itemIdx, item) {
        return this.addItemToPath([{ sectionIndex: sectionIdx, itemIndex: itemIdx }], item);
    }
    addItemToPath(itemPath, item) {
        if (!item.widget) {
            this.logger.warn(`Item to add to path ${itemPath} does not contain any widget. The item will not be added at all.`, item);
            return this;
        }
        this.addItemOps.push({
            itemPath,
            item: cloneDeep(item),
        });
        return this;
    }
    addSection(sectionIdx, section) {
        return this.addSectionToPath({ sectionIndex: sectionIdx }, section);
    }
    addSectionToPath(sectionPath, section) {
        if (isEmpty(section.items)) {
            this.logger.warn(`Section to add at path ${sectionPath} contains no items. The section will not be added at all.`, section);
            return this;
        }
        const itemsWithoutWidget = section.items.filter((item) => item.widget === undefined);
        if (!isEmpty(itemsWithoutWidget)) {
            this.logger.warn(`Section to add at path ${sectionPath} contains items that do not specify any widgets. The section will not be added at all.`, section);
            return this;
        }
        this.addSectionOps.push({
            sectionPath,
            section: cloneDeep(section),
        });
        return this;
    }
    applyTransformations = (layout) => {
        const builder = DashboardLayoutBuilder.for(layout);
        const layoutFacade = builder.facade();
        const { layouts } = this.mutationContext;
        this.addItemOps.forEach((op) => {
            const { itemPath, item } = op;
            const parentPath = itemPath.slice(0, -1);
            const lastPathItem = itemPath[itemPath.length - 1];
            const sectionIndex = lastPathItem.sectionIndex === -1
                ? layoutFacade.sections().count()
                : lastPathItem.sectionIndex;
            const sectionPath = {
                parent: parentPath,
                sectionIndex,
            };
            builder.modifySection(sectionPath, (sectionBuilder) => {
                sectionBuilder.addItem(item, lastPathItem.itemIndex === -1
                    ? sectionBuilder.facade().items().count()
                    : lastPathItem.itemIndex);
                if (item.widget) {
                    layouts[objRefToString(item.widget)] = "inserted";
                }
                return sectionBuilder;
            });
        });
        this.addSectionOps.forEach((op) => {
            const { sectionPath, section } = op;
            const resolvedSectionPath = {
                ...sectionPath,
                sectionIndex: sectionPath.sectionIndex === -1
                    ? layoutFacade.sections().count()
                    : sectionPath.sectionIndex,
            };
            builder.addSection(section, resolvedSectionPath);
            section.items.forEach((item) => {
                if (item.widget) {
                    layouts[objRefToString(item.widget)] = "inserted";
                }
            });
        });
        return builder.build();
    };
}
