/**
 * DevExtreme (esm/__internal/grids/grid_core/master_detail/m_master_detail.js)
 * Version: 22.1.13
 * Build date: Fri Feb 09 2024
 *
 * Copyright (c) 2012 - 2024 Developer Express Inc. ALL RIGHTS RESERVED
 * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
 */
import $ from "../../../../core/renderer";
import {
    grep
} from "../../../../core/utils/common";
import {
    Deferred,
    when
} from "../../../../core/utils/deferred";
import {
    each
} from "../../../../core/utils/iterator";
import {
    getHeight,
    getWidth
} from "../../../../core/utils/size";
import {
    isDefined
} from "../../../../core/utils/type";
import gridCoreUtils from "../m_utils";
var MASTER_DETAIL_CELL_CLASS = "dx-master-detail-cell";
var MASTER_DETAIL_ROW_CLASS = "dx-master-detail-row";
var CELL_FOCUS_DISABLED_CLASS = "dx-cell-focus-disabled";
var ROW_LINES_CLASS = "dx-row-lines";
export var masterDetailModule = {
    defaultOptions: () => ({
        masterDetail: {
            enabled: false,
            autoExpandAll: false,
            template: null
        }
    }),
    extenders: {
        controllers: {
            columns: {
                _getExpandColumnsCore() {
                    var expandColumns = this.callBase();
                    if (this.option("masterDetail.enabled")) {
                        expandColumns.push({
                            type: "detailExpand",
                            cellTemplate: gridCoreUtils.getExpandCellTemplate()
                        })
                    }
                    return expandColumns
                }
            },
            data: function() {
                var initMasterDetail = function(that) {
                    that._expandedItems = [];
                    that._isExpandAll = that.option("masterDetail.autoExpandAll")
                };
                return {
                    init() {
                        initMasterDetail(this);
                        this.callBase()
                    },
                    expandAll(groupIndex) {
                        if (groupIndex < 0) {
                            this._isExpandAll = true;
                            this._expandedItems = [];
                            this.updateItems()
                        } else {
                            this.callBase.apply(this, arguments)
                        }
                    },
                    collapseAll(groupIndex) {
                        if (groupIndex < 0) {
                            this._isExpandAll = false;
                            this._expandedItems = [];
                            this.updateItems()
                        } else {
                            this.callBase.apply(this, arguments)
                        }
                    },
                    isRowExpanded(key) {
                        var expandIndex = gridCoreUtils.getIndexByKey(key, this._expandedItems);
                        if (Array.isArray(key)) {
                            return this.callBase.apply(this, arguments)
                        }
                        return !!(this._isExpandAll ^ (expandIndex >= 0 && this._expandedItems[expandIndex].visible))
                    },
                    _getRowIndicesForExpand(key) {
                        var rowIndex = this.getRowIndexByKey(key);
                        return [rowIndex, rowIndex + 1]
                    },
                    _changeRowExpandCore(key) {
                        var result;
                        if (Array.isArray(key)) {
                            result = this.callBase.apply(this, arguments)
                        } else {
                            var expandIndex = gridCoreUtils.getIndexByKey(key, this._expandedItems);
                            if (expandIndex >= 0) {
                                var {
                                    visible: visible
                                } = this._expandedItems[expandIndex];
                                this._expandedItems[expandIndex].visible = !visible
                            } else {
                                this._expandedItems.push({
                                    key: key,
                                    visible: true
                                })
                            }
                            this.updateItems({
                                changeType: "update",
                                rowIndices: this._getRowIndicesForExpand(key)
                            });
                            result = (new Deferred).resolve()
                        }
                        return result
                    },
                    _processDataItem(data, options) {
                        var dataItem = this.callBase.apply(this, arguments);
                        dataItem.isExpanded = this.isRowExpanded(dataItem.key);
                        if (void 0 === options.detailColumnIndex) {
                            options.detailColumnIndex = -1;
                            each(options.visibleColumns, (index, column) => {
                                if ("expand" === column.command && !isDefined(column.groupIndex)) {
                                    options.detailColumnIndex = index;
                                    return false
                                }
                                return
                            })
                        }
                        if (options.detailColumnIndex >= 0) {
                            dataItem.values[options.detailColumnIndex] = dataItem.isExpanded
                        }
                        return dataItem
                    },
                    _processItems(items, change) {
                        var that = this;
                        var {
                            changeType: changeType
                        } = change;
                        var result = [];
                        items = that.callBase.apply(that, arguments);
                        if ("loadingAll" === changeType) {
                            return items
                        }
                        if ("refresh" === changeType) {
                            that._expandedItems = grep(that._expandedItems, item => item.visible)
                        }
                        each(items, (index, item) => {
                            result.push(item);
                            var expandIndex = gridCoreUtils.getIndexByKey(item.key, that._expandedItems);
                            if ("data" === item.rowType && (item.isExpanded || expandIndex >= 0) && !item.isNewRow) {
                                result.push({
                                    visible: item.isExpanded,
                                    rowType: "detail",
                                    key: item.key,
                                    data: item.data,
                                    values: []
                                })
                            }
                        });
                        return result
                    },
                    optionChanged(args) {
                        var isEnabledChanged;
                        var isAutoExpandAllChanged;
                        if ("masterDetail" === args.name) {
                            args.name = "dataSource";
                            switch (args.fullName) {
                                case "masterDetail":
                                    var value = args.value || {};
                                    var previousValue = args.previousValue || {};
                                    isEnabledChanged = value.enabled !== previousValue.enabled;
                                    isAutoExpandAllChanged = value.autoExpandAll !== previousValue.autoExpandAll;
                                    break;
                                case "masterDetail.template":
                                    initMasterDetail(this);
                                    break;
                                case "masterDetail.enabled":
                                    isEnabledChanged = true;
                                    break;
                                case "masterDetail.autoExpandAll":
                                    isAutoExpandAllChanged = true
                            }
                            if (isEnabledChanged || isAutoExpandAllChanged) {
                                initMasterDetail(this)
                            }
                        }
                        this.callBase(args)
                    }
                }
            }(),
            resizing: {
                fireContentReadyAction() {
                    this.callBase.apply(this, arguments);
                    this._updateParentDataGrids(this.component.$element())
                },
                _updateParentDataGrids($element) {
                    var $masterDetailRow = $element.closest(".".concat(MASTER_DETAIL_ROW_CLASS));
                    if ($masterDetailRow.length) {
                        when(this._updateMasterDataGrid($masterDetailRow, $element)).done(() => {
                            this._updateParentDataGrids($masterDetailRow.parent())
                        })
                    }
                },
                _updateMasterDataGrid($masterDetailRow, $detailElement) {
                    var masterRowOptions = $($masterDetailRow).data("options");
                    var masterDataGrid = $($masterDetailRow).closest(".".concat(this.getWidgetContainerClass())).parent().data("dxDataGrid");
                    if (masterRowOptions && masterDataGrid) {
                        return this._updateMasterDataGridCore(masterDataGrid, masterRowOptions)
                    }
                },
                _updateMasterDataGridCore(masterDataGrid, masterRowOptions) {
                    var d = Deferred();
                    if (masterDataGrid.getView("rowsView").isFixedColumns()) {
                        this._updateFixedMasterDetailGrids(masterDataGrid, masterRowOptions.rowIndex, $(masterRowOptions.rowElement)).done(d.resolve)
                    } else {
                        if (true === masterDataGrid.option("scrolling.useNative")) {
                            masterDataGrid.updateDimensions().done(() => d.resolve(true));
                            return
                        }
                        var scrollable = masterDataGrid.getScrollable();
                        if (scrollable) {
                            null === scrollable || void 0 === scrollable ? void 0 : scrollable.update().done(() => d.resolve())
                        } else {
                            d.resolve()
                        }
                    }
                    return d.promise()
                },
                _updateFixedMasterDetailGrids(masterDataGrid, masterRowIndex, $detailElement) {
                    var d = Deferred();
                    var $rows = $(masterDataGrid.getRowElement(masterRowIndex));
                    var $tables = $(masterDataGrid.getView("rowsView").getTableElements());
                    var rowsNotEqual = 2 === (null === $rows || void 0 === $rows ? void 0 : $rows.length) && getHeight($rows.eq(0)) !== getHeight($rows.eq(1));
                    var tablesNotEqual = 2 === (null === $tables || void 0 === $tables ? void 0 : $tables.length) && getHeight($tables.eq(0)) !== getHeight($tables.eq(1));
                    if (rowsNotEqual || tablesNotEqual) {
                        var detailElementWidth = getWidth($detailElement);
                        masterDataGrid.updateDimensions().done(() => {
                            var isDetailHorizontalScrollCanBeShown = this.option("columnAutoWidth") && true === masterDataGrid.option("scrolling.useNative");
                            var isDetailGridWidthChanged = isDetailHorizontalScrollCanBeShown && detailElementWidth !== getWidth($detailElement);
                            if (isDetailHorizontalScrollCanBeShown && isDetailGridWidthChanged) {
                                this.updateDimensions().done(() => d.resolve(true))
                            } else {
                                d.resolve(true)
                            }
                        });
                        return d.promise()
                    }
                    return Deferred().resolve()
                },
                _toggleBestFitMode(isBestFit) {
                    this.callBase.apply(this, arguments);
                    if (this.option("masterDetail.template")) {
                        var $rowsTable = this._rowsView.getTableElement();
                        if ($rowsTable) {
                            $rowsTable.find(".dx-master-detail-cell").css("maxWidth", isBestFit ? 0 : "")
                        }
                    }
                }
            }
        },
        views: {
            rowsView: {
                _getCellTemplate(options) {
                    var {
                        column: column
                    } = options;
                    var editingController = this.getController("editing");
                    var isEditRow = editingController && editingController.isEditRow(options.rowIndex);
                    var template;
                    if ("detail" === column.command && !isEditRow) {
                        template = this.option("masterDetail.template") || {
                            allowRenderToDetachedContainer: false,
                            render: this._getDefaultTemplate(column)
                        }
                    } else {
                        template = this.callBase.apply(this, arguments)
                    }
                    return template
                },
                _isDetailRow: row => row && row.rowType && 0 === row.rowType.indexOf("detail"),
                _createRow(row) {
                    var $row = this.callBase.apply(this, arguments);
                    if (row && this._isDetailRow(row)) {
                        this.option("showRowLines") && $row.addClass(ROW_LINES_CLASS);
                        $row.addClass(MASTER_DETAIL_ROW_CLASS);
                        if (isDefined(row.visible)) {
                            $row.toggle(row.visible)
                        }
                    }
                    return $row
                },
                _renderCells($row, options) {
                    var {
                        row: row
                    } = options;
                    var $detailCell;
                    var visibleColumns = this._columnsController.getVisibleColumns();
                    if (row.rowType && this._isDetailRow(row)) {
                        if (this._needRenderCell(0, options.columnIndices)) {
                            $detailCell = this._renderCell($row, {
                                value: null,
                                row: row,
                                rowIndex: row.rowIndex,
                                column: {
                                    command: "detail"
                                },
                                columnIndex: 0,
                                change: options.change
                            });
                            $detailCell.addClass(CELL_FOCUS_DISABLED_CLASS).addClass(MASTER_DETAIL_CELL_CLASS).attr("colSpan", visibleColumns.length)
                        }
                    } else {
                        this.callBase.apply(this, arguments)
                    }
                }
            }
        }
    }
};
