// (C) 2021-2026 GoodData Corporation
import { walkLayout } from "@gooddata/sdk-backend-spi";
import { isInsightWidget, isInsightWidgetDefinition, isKpiWidget, isKpiWidgetDefinition, isObjRef, objRefToString, } from "@gooddata/sdk-model";
import { DashboardCustomizationLogger } from "./customizationLogging.js";
import { DefaultDashboardContentCustomizer } from "./dashboardContentCustomizer.js";
import { DefaultFilterBarCustomizer } from "./filterBarCustomizer.js";
import { DefaultFiltersCustomizer } from "./filtersCustomizer.js";
import { DefaultInsightCustomizer } from "./insightCustomizer.js";
import { DefaultLayoutCustomizer } from "./layoutCustomizer.js";
import { DefaultLoadingCustomizer } from "./loadingCustomizer.js";
import { DefaultRichTextCustomizer } from "./richTextCustomizer.js";
import { DefaultTitleCustomizer } from "./titleCustomizer.js";
import { DefaultTopBarCustomizer } from "./topBarCustomizer.js";
import { createCustomizerMutationsContext } from "./types.js";
import { DefaultVisualizationSwitcherCustomizer } from "./visualizationSwitcherCustomizer.js";
import { DefaultWidgetCustomizer } from "./widgetCustomizer.js";
/**
 * @internal
 */
export class DashboardCustomizationBuilder {
    mutations = createCustomizerMutationsContext();
    logger = new DashboardCustomizationLogger();
    insightCustomizer = new DefaultInsightCustomizer(this.logger, this.mutations);
    widgetCustomizer = new DefaultWidgetCustomizer(this.logger);
    layoutCustomizer = new DefaultLayoutCustomizer(this.logger, this.mutations);
    filterBarCustomizer = new DefaultFilterBarCustomizer(this.logger, this.mutations);
    filtersCustomizer = new DefaultFiltersCustomizer(this.logger, this.mutations);
    richTextCustomizer = new DefaultRichTextCustomizer(this.logger, this.mutations);
    visualizationSwitcherCustomizer = new DefaultVisualizationSwitcherCustomizer(this.logger, this.mutations);
    dashboardContentCustomizer = new DefaultDashboardContentCustomizer(this.logger, this.mutations);
    topBarCustomizer = new DefaultTopBarCustomizer(this.logger, this.mutations);
    titleCustomizer = new DefaultTitleCustomizer(this.logger, this.mutations);
    loadingCustomizer = new DefaultLoadingCustomizer(this.logger, this.mutations);
    widgetOverlays = {};
    sealCustomizers = () => {
        this.insightCustomizer.sealCustomizer();
        this.widgetCustomizer.sealCustomizer();
        this.filtersCustomizer.sealCustomizer();
        this.layoutCustomizer.sealCustomizer();
        this.dashboardContentCustomizer.sealCustomizer();
        this.topBarCustomizer.sealCustomizer();
        this.titleCustomizer.sealCustomizer();
        this.loadingCustomizer.sealCustomizer();
        this.richTextCustomizer.sealCustomizer();
        this.visualizationSwitcherCustomizer.sealCustomizer();
    };
    setWidgetOverlays = (widgetOverlays) => {
        this.widgetOverlays = widgetOverlays || {};
    };
    insightWidgets = () => {
        return this.insightCustomizer;
    };
    customWidgets = () => {
        return this.widgetCustomizer;
    };
    dashboard = () => {
        return this.dashboardContentCustomizer;
    };
    topBar = () => {
        return this.topBarCustomizer;
    };
    title = () => {
        return this.titleCustomizer;
    };
    loading = () => {
        return this.loadingCustomizer;
    };
    layout = () => {
        return this.layoutCustomizer;
    };
    filterBar = () => {
        return this.filterBarCustomizer;
    };
    filters = () => {
        return this.filtersCustomizer;
    };
    richTextWidgets = () => {
        return this.richTextCustomizer;
    };
    visualizationSwitcherWidgets = () => {
        return this.visualizationSwitcherCustomizer;
    };
    onBeforePluginRegister = (plugin) => {
        this.logger.setCurrentPlugin(plugin);
        this.logger.debug("Starting registration.");
    };
    onAfterPluginRegister = () => {
        this.logger.debug("Registration finished.");
        this.logger.setCurrentPlugin(undefined);
    };
    onPluginRegisterError = (error) => {
        this.logger.error("Plugin register() method threw and exception. Plugin may be partially registered.", error);
        this.logger.setCurrentPlugin(undefined);
    };
    build = () => {
        const filterBarCustomizerResult = this.filterBarCustomizer.getCustomizerResult();
        const topBarCustomizerResult = this.topBarCustomizer.getCustomizerResult();
        const titleCustomizerResult = this.titleCustomizer.getCustomizerResult();
        const layoutCustomizerResult = this.layoutCustomizer.getCustomizerResult();
        const loadingCustomizerResult = this.loadingCustomizer.getCustomizerResult();
        const props = {
            InsightComponentProvider: this.insightCustomizer.getInsightProvider(),
            InsightBodyComponentProvider: this.insightCustomizer.getInsightBodyComponentProvider(),
            DashboardContentComponentProvider: this.dashboardContentCustomizer.getDashboardContentProvider(),
            WidgetComponentProvider: this.widgetCustomizer.getWidgetComponentProvider(),
            DashboardAttributeFilterComponentProvider: this.filtersCustomizer
                .attribute()
                .getAttributeFilterProvider(),
            DashboardDateFilterComponentProvider: this.filtersCustomizer.date().getDateFilterProvider(),
            DashboardMeasureValueFilterComponentProvider: this.filtersCustomizer
                .measureValue()
                .getMeasureValueFilterProvider(),
            DashboardFilterGroupComponentProvider: this.filtersCustomizer
                .filterGroup()
                .getFilterGroupProvider(),
            RichTextComponentProvider: this.richTextCustomizer.getRichTextComponentProvider(),
            VisualizationSwitcherComponentProvider: this.visualizationSwitcherCustomizer.getVisualizationSwitcherComponentProvider(),
            VisualizationSwitcherToolbarComponentProvider: this.visualizationSwitcherCustomizer.getVisualizationSwitcherToolbarComponentProvider(),
            customizationFns: {
                existingDashboardTransformFn: this.layoutCustomizer.getExistingDashboardTransformFn(),
                existingExportTransformFn: this.layoutCustomizer.getExistingLayoutTransformFn(),
            },
            widgetsOverlayFn: this.getWidgetsOverlayFn(),
            // only set the value if there is anything to set
            ...(filterBarCustomizerResult.FilterBarComponent
                ? { FilterBarComponent: filterBarCustomizerResult.FilterBarComponent }
                : {}),
            ...(topBarCustomizerResult.TopBarComponent
                ? { TopBarComponent: topBarCustomizerResult.TopBarComponent }
                : {}),
            ...(titleCustomizerResult.TitleComponent
                ? { TitleComponent: titleCustomizerResult.TitleComponent }
                : {}),
            ...(layoutCustomizerResult.LayoutComponent
                ? { LayoutComponent: layoutCustomizerResult.LayoutComponent }
                : {}),
            ...(loadingCustomizerResult.LoadingComponent
                ? { LoadingComponent: loadingCustomizerResult.LoadingComponent }
                : {}),
        };
        this.sealCustomizers();
        return props;
    };
    getWidgetsOverlayFn() {
        return (dashboard) => {
            const overlays = { ...this.widgetOverlays };
            const { insight, kpi, layouts } = this.mutations;
            const { layout } = dashboard;
            const firstTabLayout = dashboard.tabs?.[0]?.layout;
            const layoutToTransform = firstTabLayout ?? layout;
            walkLayout(layoutToTransform, {
                itemCallback: (item) => {
                    if ((isInsightWidget(item.widget) || isInsightWidgetDefinition(item.widget)) &&
                        isObjRef(item.widget) &&
                        insight.length > 0) {
                        mergeOverlays(overlays, objRefToString(item.widget), true, "modifiedByPlugin");
                    }
                    if ((isKpiWidget(item.widget) || isKpiWidgetDefinition(item.widget)) &&
                        isObjRef(item.widget) &&
                        kpi.length > 0) {
                        mergeOverlays(overlays, objRefToString(item.widget), true, "modifiedByPlugin");
                    }
                },
            });
            Object.keys(layouts).forEach((ref) => {
                if (layouts[ref] === "inserted") {
                    mergeOverlays(overlays, ref, true, "insertedByPlugin");
                }
            });
            return overlays;
        };
    }
}
function mergeOverlays(overlays, ref, showOverlay, modification) {
    const current = overlays[ref];
    const created = {
        showOverlay,
        modification,
    };
    overlays[ref] = {
        ...created,
        ...(current || {}),
    };
}
