/* @oracle/oraclejet-preact: undefined */
'use strict';

var jsxRuntime = require('preact/jsx-runtime');
var hooks = require('preact/hooks');
var Skeleton = require('./Skeleton-00d15f88.js');
var classNames = require('./classNames-c14c6ef3.js');
var PRIVATE_DataGrid_themes_DataGridCell_css = require('./PRIVATE_DataGrid/themes/DataGridCell.css.js');
var PRIVATE_DataGrid_themes_DataGrid_css = require('./PRIVATE_DataGrid/themes/DataGrid.css.js');

const getCellStyle = (cell, width, height) => {
    let styleString = `
    grid-row-start: ${cell.rowStart + 1};
    grid-row-end: ${cell.rowStart + cell.rowExtent + 1};
    grid-column-start: ${cell.columnStart + 1};
    grid-column-end: ${cell.columnStart + cell.columnExtent + 1};
  `;
    switch (cell.cellType) {
        case 'rowHeader':
        case 'rowHeaderSkeleton':
            styleString += `left: ${width * cell.level}px;`;
            break;
        case 'rowEndHeader':
        case 'rowEndHeaderSkeleton':
            styleString += `right: ${width * cell.level}px;`;
            break;
        case 'columnEndHeader':
        case 'columnEndHeaderSkeleton':
            styleString += `bottom: ${height * cell.level}px;`;
            break;
        case 'columnHeader':
        case 'columnHeaderSkeleton':
            styleString += `top: ${height * cell.level}px;`;
            break;
        case 'rowHeaderLabel':
        case 'columnHeaderLabel':
            styleString += `
        top: ${height * cell.rowStart}px;
        left: ${width * cell.columnStart}px;
      `;
            break;
        case 'rowEndHeaderLabel':
            styleString += `right: ${width * cell.level}px;`;
            break;
        case 'columnEndHeaderLabel':
            styleString += `bottom: ${height * cell.level}px;`;
            break;
    }
    return styleString.trim();
};
const getCellClasses = (cell) => {
    const baseClass = PRIVATE_DataGrid_themes_DataGridCell_css.dataGridCellStyles.base;
    const headerTypes = [
        'rowHeader',
        'rowEndHeader',
        'columnEndHeader',
        'columnHeader',
        'rowHeaderSkeleton',
        'rowEndHeaderSkeleton',
        'columnEndHeaderSkeleton',
        'columnHeaderSkeleton'
    ];
    const topLeftTypes = ['rowHeaderLabel', 'columnHeaderLabel', 'topLeftSpacer'];
    const topRightTypes = ['rowEndHeaderLabel', 'topRightSpacer'];
    const bottomLeftTypes = ['columnEndHeaderLabel', 'bottomLeftSpacer'];
    const bottomRightTypes = ['bottomRightSpacer'];
    const classes = [baseClass];
    if (headerTypes.includes(cell.cellType)) {
        classes.push(PRIVATE_DataGrid_themes_DataGridCell_css.dataGridCellStyles.header);
    }
    else if (topLeftTypes.includes(cell.cellType)) {
        classes.push(PRIVATE_DataGrid_themes_DataGridCell_css.dataGridCellStyles.topLeft);
    }
    else if (topRightTypes.includes(cell.cellType)) {
        classes.push(PRIVATE_DataGrid_themes_DataGridCell_css.dataGridCellStyles.topRight);
    }
    else if (bottomLeftTypes.includes(cell.cellType)) {
        classes.push(PRIVATE_DataGrid_themes_DataGridCell_css.dataGridCellStyles.bottomLeft);
    }
    else if (bottomRightTypes.includes(cell.cellType)) {
        classes.push(PRIVATE_DataGrid_themes_DataGridCell_css.dataGridCellStyles.bottomRight);
    }
    else if (cell.cellType === 'rowHeaderSpacer') {
        classes.push(PRIVATE_DataGrid_themes_DataGridCell_css.dataGridCellStyles.rhSpacer);
    }
    else if (cell.cellType === 'columnHeaderSpacer') {
        classes.push(PRIVATE_DataGrid_themes_DataGridCell_css.dataGridCellStyles.chSpacer);
    }
    if (cell.lastRow) {
        classes.push(PRIVATE_DataGrid_themes_DataGridCell_css.dataGridCellStyles.lastRow);
    }
    if (cell.lastColumn) {
        classes.push(PRIVATE_DataGrid_themes_DataGridCell_css.dataGridCellStyles.lastColumn);
    }
    if (cell.borderLeft) {
        classes.push(PRIVATE_DataGrid_themes_DataGridCell_css.dataGridCellStyles.borderLeft);
    }
    if (cell.borderTop) {
        classes.push(PRIVATE_DataGrid_themes_DataGridCell_css.dataGridCellStyles.borderTop);
    }
    return classNames.classNames(classes);
};
function DataGridCell({ cell, height, width }) {
    if (cell.cellType.includes('Skeleton')) {
        return (jsxRuntime.jsx("div", { style: getCellStyle(cell, width, height), class: getCellClasses(cell), children: jsxRuntime.jsx(Skeleton.Skeleton, { height: "6x", width: "16x" }) }));
    }
    return (jsxRuntime.jsx("div", { style: getCellStyle(cell, width, height), class: getCellClasses(cell), children: cell.data }));
}

/**
 * @license
 * Copyright (c) %FIRST_YEAR% %CURRENT_YEAR%, Oracle and/or its affiliates.
 * The Universal Permissive License (UPL), Version 1.0
 * as shown at https://oss.oracle.com/licenses/upl/
 * @ignore
 */
const _CELL_HEIGHT = 50;
const _CELL_WIDTH = 85;
const _ROW_CONST = 'row';
const _ROW_END_CONST = 'rowEnd';
const _COLUMN_CONST = 'column';
const _COLUMN_END_CONST = 'columnEnd';
const renderGrid = ({ ranges, totalColumnCount, totalRowCount, onLoadRange, height, width, cell, header }, skeletonList) => {
    // TODO: handle custom heights widths
    const getHeaderLevels = (header, type) => {
        const headerLevels = header?.[type]?.levels;
        let range;
        if (type === 'row') {
            range = ranges.rowHeaders;
        }
        else if (type === 'rowEnd') {
            range = ranges.rowEndHeaders;
        }
        else if (type === 'column') {
            range = ranges.columnHeaders;
        }
        else if (type === 'columnEnd') {
            range = ranges.columnEndHeaders;
        }
        return range && headerLevels && headerLevels > 0 ? headerLevels : 0;
    };
    const getHeaderLabels = (header, type) => {
        const headerLabels = header?.[type]?.label;
        return headerLabels && getHeaderLevels(header, type) > 0;
    };
    // Helper to check if both headers exist for a given pair
    const getHasBothHeaders = (header, _ROW_TYPES, colType) => getHeaderLevels(header, _ROW_TYPES) > 0 && getHeaderLevels(header, colType) > 0;
    // Helper to check if both labels exist for a given pair
    const getHasBothLabels = (header, _ROW_TYPES, colType) => getHeaderLabels(header, _ROW_TYPES) && getHeaderLabels(header, colType);
    // Determine if a top-left spacer is needed
    const hasBothHeaders = getHasBothHeaders(header, _ROW_CONST, _COLUMN_CONST);
    const hasBothLabels = getHasBothLabels(header, _ROW_CONST, _COLUMN_CONST);
    const isEmptyRowLabels = !getHeaderLabels(header, _ROW_CONST);
    const isEmptyColumnLabels = !getHeaderLabels(header, _COLUMN_CONST);
    const rowLevels = getHeaderLevels(header, _ROW_CONST);
    const columnLevels = getHeaderLevels(header, _COLUMN_CONST);
    const hasTopLeftSpacer = hasBothHeaders &&
        ((!hasBothLabels && isEmptyRowLabels && isEmptyColumnLabels) ||
            (hasBothLabels && rowLevels > columnLevels) ||
            (hasBothLabels && rowLevels > 1 && columnLevels > 1));
    // Determine if spacers are needed for other corners
    const hasTopRightSpacer = getHasBothHeaders(header, _ROW_END_CONST, _COLUMN_CONST) &&
        !getHeaderLabels(header, _ROW_END_CONST);
    const hasBottomLeftSpacer = getHasBothHeaders(header, _ROW_CONST, _COLUMN_END_CONST) &&
        !getHeaderLabels(header, _COLUMN_END_CONST);
    const hasBottomRightSpacer = getHasBothHeaders(header, _ROW_END_CONST, _COLUMN_END_CONST);
    // Check for header collision in the top-left corner
    const collision = getHasBothHeaders(header, _ROW_CONST, _COLUMN_CONST) &&
        getHasBothLabels(header, _ROW_CONST, _COLUMN_CONST) &&
        Math.min(getHeaderLevels(header, _ROW_CONST), getHeaderLevels(header, _COLUMN_CONST)) >= 1;
    // Check if row or column header spacers are needed
    const hasRowHeaderSpacer = (getHeaderLabels(header, _COLUMN_CONST) || getHeaderLabels(header, _COLUMN_END_CONST)) &&
        getHeaderLevels(header, _ROW_CONST) <= 0;
    const hasColumnHeaderSpacer = (getHeaderLabels(header, _ROW_CONST) || getHeaderLabels(header, _ROW_END_CONST)) &&
        getHeaderLevels(header, _COLUMN_CONST) <= 0;
    // TODO: handle unknown
    // Helper function to add header levels if they exist
    const addHeaderLevels = (header, type) => getHeaderLevels(header, type) > 0 ? getHeaderLevels(header, type) : 0;
    // Calculate total columns in the grid
    let gridTotalColumns = totalColumnCount === 'unknown' ? 0 : totalColumnCount;
    const dataRegionColumnCount = gridTotalColumns;
    // Adjust for row headers and row header spacer
    gridTotalColumns += addHeaderLevels(header, _ROW_CONST) + addHeaderLevels(header, _ROW_END_CONST);
    gridTotalColumns += hasRowHeaderSpacer ? 1 : 0;
    // Calculate total rows in the grid
    let gridTotalRows = totalRowCount === 'unknown' ? 0 : totalRowCount;
    const dataRegionRowCount = gridTotalRows;
    // Adjust for column headers, collisions, and column header spacer
    gridTotalRows +=
        addHeaderLevels(header, _COLUMN_CONST) + addHeaderLevels(header, _COLUMN_END_CONST);
    gridTotalRows += collision ? 1 : 0;
    gridTotalRows += hasColumnHeaderSpacer ? 1 : 0;
    // Calculate row starts
    const rowHeaderRowStart = getHeaderLevels(header, _COLUMN_CONST) + (collision || hasColumnHeaderSpacer ? 1 : 0);
    const rowEndHeaderRowStart = rowHeaderRowStart;
    const columnHeaderRowStart = 0;
    const columnEndHeaderRowStart = gridTotalRows - getHeaderLevels(header, _COLUMN_END_CONST);
    // Calculate column starts
    const columnHeaderColumnStart = getHeaderLevels(header, _ROW_CONST) + (hasRowHeaderSpacer ? 1 : 0);
    const columnEndHeaderColumnStart = columnHeaderColumnStart;
    const rowHeaderColumnStart = 0;
    const rowEndHeaderColumnStart = gridTotalColumns - getHeaderLevels(header, _ROW_END_CONST);
    // Merges overlapping or adjacent cell ranges in a grid in 2 dimensions.
    const mergeCellRanges = (ranges) => {
        if (!ranges || ranges.length === 0)
            return false;
        const mergedRanges = [];
        // Sort ranges by rowStart and then by columnStart
        ranges.sort((a, b) => a.rowStart === b.rowStart ? a.columnStart - b.columnStart : a.rowStart - b.rowStart);
        // Merge ranges
        for (const range of ranges) {
            const lastMerged = mergedRanges[mergedRanges.length - 1];
            if (!lastMerged ||
                lastMerged.rowStart + lastMerged.rowCount < range.rowStart ||
                lastMerged.columnStart + lastMerged.columnCount < range.columnStart) {
                mergedRanges.push(range);
            }
            else {
                // Extend the current merged range
                lastMerged.rowCount =
                    Math.max(lastMerged.rowStart + lastMerged.rowCount, range.rowStart + range.rowCount) -
                        lastMerged.rowStart;
                lastMerged.columnCount =
                    Math.max(lastMerged.columnStart + lastMerged.columnCount, range.columnStart + range.columnCount) - lastMerged.columnStart;
            }
        }
        return mergedRanges;
    };
    const mergedDataBody = mergeCellRanges(ranges.dataBody);
    let actualDataRows = 0;
    let actualDataCols = 0;
    if (mergedDataBody) {
        mergedDataBody.forEach((range) => {
            actualDataCols += range.columnCount;
            actualDataRows += range.rowCount;
        });
    }
    // 1D array of actual cells we need to render
    const grid = [];
    // Map of indices that we getHas seen
    const seenIndexMap = new Map();
    // Handle skipping cells for row extent
    const handleRowSkip = (rowIndex, columnIndex, rowExtent) => {
        for (let r = rowIndex; r < rowIndex + rowExtent; r++) {
            seenIndexMap.set(`${r},${columnIndex}`, { cellType: 'skip' });
        }
    };
    // Handle skipping cells for column extent
    const handleColumnSkip = (rowIndex, columnIndex, columnExtent) => {
        for (let c = columnIndex; c < columnIndex + columnExtent; c++) {
            seenIndexMap.set(`${rowIndex},${c}`, { cellType: 'skip' });
        }
    };
    // Calculates label extents and offsets
    const calculateLabelExtentsAndOffsets = (type, itemLevels, currentLevel) => {
        let rowExtent = 1, columnExtent = 1, rowOffset = 0, columnOffset = 0;
        const columnHeaderLevels = getHeaderLevels(header, _COLUMN_CONST);
        const rowHeaderLevels = getHeaderLevels(header, _ROW_CONST);
        switch (type) {
            case 'rowEndHeaderLabel':
                columnOffset = itemLevels - currentLevel - 1;
                rowExtent = collision ? columnHeaderLevels + 1 : columnHeaderLevels;
                break;
            case 'columnEndHeaderLabel':
                rowOffset = itemLevels - currentLevel - 1;
                columnExtent = rowHeaderLevels > 0 ? rowHeaderLevels : 1;
                break;
            case 'rowHeaderLabel':
                columnOffset = currentLevel;
                rowExtent = collision ? 1 : columnHeaderLevels;
                break;
            case 'columnHeaderLabel':
                rowOffset = currentLevel;
                columnExtent = collision ? 1 : rowHeaderLevels;
                break;
        }
        return { rowExtent, columnExtent, rowOffset, columnOffset };
    };
    // Walks ranges and adds appropriate cells to grid.
    const processLabelData = (item, rowAxisStart, columnAxisStart, type, isRow, isEnd) => {
        if (!item.label) {
            return;
        }
        for (let i = 0; i < item.levels; i++) {
            const labelData = item.label.data(i);
            const { rowExtent, columnExtent, rowOffset, columnOffset } = calculateLabelExtentsAndOffsets(type, item.levels, i);
            const rowIndex = rowAxisStart + rowOffset;
            const columnIndex = columnAxisStart + columnOffset;
            grid.push({
                cellType: type,
                rowStart: rowIndex,
                rowExtent: rowExtent,
                columnStart: columnIndex,
                columnExtent: columnExtent,
                data: labelData.data,
                borderTop: !isRow && isEnd ? i === item.levels - 1 : false,
                borderLeft: isRow && isEnd ? i === item.levels - 1 : false,
                level: i
            });
        }
    };
    // Renders row header labels
    if (ranges.rowHeaders && header?.row && header.row.label) {
        processLabelData(header.row, collision ? rowHeaderRowStart - 1 : columnHeaderRowStart, rowHeaderColumnStart, 'rowHeaderLabel', true, false);
    }
    // Renders column header labels
    if (ranges.columnHeaders && header?.column && header.column.label) {
        processLabelData(header.column, columnHeaderRowStart, collision ? columnHeaderColumnStart - 1 : rowHeaderColumnStart, 'columnHeaderLabel', false, false);
    }
    // Renders row end header labels
    if (ranges.rowEndHeaders && header?.rowEnd && header.rowEnd.label) {
        processLabelData(header.rowEnd, columnHeaderRowStart, rowEndHeaderColumnStart, 'rowEndHeaderLabel', true, true);
    }
    // Renders column end header labels
    if (ranges.columnEndHeaders && header?.columnEnd && header.columnEnd.label) {
        processLabelData(header.columnEnd, columnEndHeaderRowStart, rowHeaderColumnStart, 'columnEndHeaderLabel', false, true);
    }
    // Renders bottom left spacer
    if (hasBottomLeftSpacer) {
        const columnExtent = getHeaderLevels(header, _ROW_CONST) > 0 ? getHeaderLevels(header, _ROW_CONST) : 0;
        const rowExtent = getHeaderLevels(header, _COLUMN_END_CONST);
        const rowStart = columnEndHeaderRowStart;
        grid.push({
            cellType: 'bottomLeftSpacer',
            rowStart: rowStart,
            rowExtent: rowExtent,
            columnStart: rowHeaderColumnStart,
            columnExtent: columnExtent,
            borderRight: true,
            borderTop: true
        });
    }
    // Renders bottom right spacer
    if (hasBottomRightSpacer) {
        const columnExtent = getHeaderLevels(header, _ROW_END_CONST);
        const rowExtent = getHeaderLevels(header, _COLUMN_END_CONST);
        const rowStart = columnEndHeaderRowStart;
        const columnStart = gridTotalColumns - getHeaderLevels(header, _ROW_END_CONST);
        grid.push({
            cellType: 'bottomRightSpacer',
            rowStart: rowStart,
            rowExtent: rowExtent,
            columnStart: columnStart,
            columnExtent: columnExtent,
            borderTop: true,
            borderLeft: true
        });
    }
    // Renders top right spacer
    if (hasTopRightSpacer) {
        const columnExtent = getHeaderLevels(header, _ROW_END_CONST);
        let rowExtent = getHeaderLevels(header, _COLUMN_CONST) > 0 ? getHeaderLevels(header, _COLUMN_CONST) : 1;
        if (collision) {
            rowExtent += 1;
        }
        const rowStart = columnHeaderRowStart;
        const columnStart = rowEndHeaderColumnStart;
        grid.push({
            cellType: 'topRightSpacer',
            rowStart: rowStart,
            rowExtent: rowExtent,
            columnStart: columnStart,
            columnExtent: columnExtent,
            borderLeft: true
        });
    }
    // Renders top left spacer
    if (hasTopLeftSpacer) {
        const columnExtent = collision
            ? getHeaderLevels(header, _ROW_CONST) - 1
            : getHeaderLevels(header, _ROW_CONST);
        const rowExtent = getHeaderLevels(header, _COLUMN_CONST);
        const rowStart = 0;
        const columnStart = 0;
        grid.push({
            cellType: 'topLeftSpacer',
            rowStart: rowStart,
            rowExtent: rowExtent,
            columnStart: columnStart,
            columnExtent: columnExtent
        });
    }
    // Renders row heder spacer
    if (hasRowHeaderSpacer) {
        let rowStart = getHeaderLabels(header, _COLUMN_CONST)
            ? getHeaderLevels(header, _COLUMN_CONST)
            : 0;
        let rowExtent = gridTotalRows;
        if (getHeaderLabels(header, _COLUMN_CONST)) {
            rowExtent -= getHeaderLevels(header, _COLUMN_CONST);
        }
        if (getHeaderLabels(header, _COLUMN_END_CONST)) {
            rowExtent -= getHeaderLevels(header, _COLUMN_END_CONST);
        }
        if (hasColumnHeaderSpacer) {
            rowExtent -= 1;
            rowStart += 1;
        }
        grid.push({
            cellType: 'rowHeaderSpacer',
            rowStart: rowStart,
            rowExtent: rowExtent,
            columnStart: 0,
            columnExtent: 1,
            lastRow: getHeaderLabels(header, _COLUMN_END_CONST) ? true : false
        });
    }
    // Renders column heder spacer
    if (hasColumnHeaderSpacer) {
        const columnStart = getHeaderLabels(header, _ROW_CONST)
            ? getHeaderLevels(header, _ROW_CONST)
            : 0;
        let columnExtent = gridTotalColumns;
        if (getHeaderLabels(header, _ROW_CONST)) {
            columnExtent -= getHeaderLevels(header, _ROW_CONST);
        }
        if (getHeaderLabels(header, _ROW_END_CONST)) {
            columnExtent -= getHeaderLevels(header, _ROW_END_CONST);
        }
        grid.push({
            cellType: 'columnHeaderSpacer',
            rowStart: 0,
            rowExtent: 1,
            columnStart: columnStart,
            columnExtent: columnExtent,
            lastColumn: getHeaderLabels(header, _ROW_END_CONST) ? true : false
        });
    }
    // Calculates Header range bounds
    const getHeaderRangeBounds = (range, isRow, levels) => {
        if (isRow) {
            return {
                rowStart: range.rowStart,
                rowEnd: range.rowCount + range.rowStart,
                columnStart: 0,
                columnEnd: levels
            };
        }
        else {
            return {
                rowStart: 0,
                rowEnd: levels,
                columnStart: range.columnStart,
                columnEnd: range.columnCount + range.columnStart
            };
        }
    };
    // Calculates header offsets
    const getHeaderOffsets = (i, j, type, levels) => {
        let rowOffset = i;
        let columnOffset = j;
        if (type === 'rowEndHeader') {
            columnOffset = levels - j - 1;
        }
        else if (type === 'columnEndHeader') {
            rowOffset = levels - i - 1;
        }
        return { rowOffset, columnOffset };
    };
    // Walks ranges and adds appropriate header cells to grid
    const processHeaderData = (item, rangeArray, rowAxisStart, columnAxisStart, type, isRow, isEnd) => {
        rangeArray.forEach((range) => {
            const { rowStart, rowEnd, columnStart, columnEnd } = getHeaderRangeBounds(range, isRow, item.levels);
            for (let i = rowStart; i < rowEnd; i++) {
                for (let j = columnStart; j < columnEnd; j++) {
                    const { rowOffset, columnOffset } = getHeaderOffsets(i, j, type, item.levels);
                    const rowIndex = rowAxisStart + rowOffset;
                    const columnIndex = columnAxisStart + columnOffset;
                    const cellObject = seenIndexMap.get(`${rowIndex},${columnIndex}`);
                    if (cellObject?.cellType === 'skip') {
                        continue;
                    }
                    const headerData = item.data(isRow ? i : j, isRow ? j : i);
                    let extent = headerData.extent;
                    let depth = headerData.depth;
                    if (type === 'columnHeader' && i === item.levels - 1 && collision) {
                        depth += 1;
                    }
                    const maxExtent = isRow
                        ? range.rowStart + range.rowCount
                        : range.columnStart +
                            range.columnCount;
                    if ((isRow && i + extent > maxExtent) || (!isRow && j + extent > maxExtent)) {
                        extent = isRow ? maxExtent - i : maxExtent - j;
                    }
                    grid.push({
                        cellType: type,
                        rowStart: rowIndex,
                        rowExtent: isRow ? extent : depth,
                        columnStart: columnIndex,
                        columnExtent: isRow ? depth : extent,
                        data: headerData.data,
                        level: isRow ? j : i,
                        borderTop: !isRow && isEnd ? i === item.levels - 1 : false,
                        borderLeft: isRow && isEnd ? j === item.levels - 1 : false,
                        lastColumn: !isRow && j + extent === dataRegionColumnCount,
                        lastRow: isRow && i + extent === dataRegionRowCount
                    });
                    if (extent > 1) {
                        if (isRow) {
                            handleRowSkip(rowIndex, columnIndex, extent);
                        }
                        else {
                            handleColumnSkip(rowIndex, columnIndex, extent);
                        }
                    }
                    if (depth > 1) {
                        if (isRow) {
                            handleColumnSkip(rowIndex, columnIndex, depth);
                        }
                        else {
                            handleRowSkip(rowIndex, columnIndex, depth);
                        }
                    }
                }
            }
        });
    };
    // Merges overlapping ranges if it exists
    const mergeHeaderRanges = (ranges, getStart, getEnd) => {
        const mergedRanges = [];
        ranges.sort((a, b) => getStart(a) - getStart(b));
        for (let i = 0; i < ranges.length; i++) {
            if (!mergedRanges.length ||
                getEnd(mergedRanges[mergedRanges.length - 1]) < getStart(ranges[i])) {
                mergedRanges.push(ranges[i]);
            }
            else {
                // Merge ranges by extending the last range in mergedRanges
                const lastRange = mergedRanges[mergedRanges.length - 1];
                mergedRanges[mergedRanges.length - 1] = {
                    ...lastRange,
                    // Update the end of the merged range with the maximum value of the end
                    end: Math.max(getEnd(lastRange), getEnd(ranges[i]))
                };
            }
        }
        return mergedRanges;
    };
    // Renders row headers
    if (ranges.rowHeaders && header?.row) {
        const mergedRowRanges = mergeHeaderRanges(ranges.rowHeaders, (range) => range.rowStart, (range) => range.rowCount);
        processHeaderData(header.row, mergedRowRanges, rowHeaderRowStart, rowHeaderColumnStart, 'rowHeader', true, false);
    }
    // Renders rowEnd headers
    if (ranges.rowEndHeaders && header?.rowEnd) {
        const mergedRowEndRanges = mergeHeaderRanges(ranges.rowEndHeaders, (range) => range.rowStart, (range) => range.rowCount);
        processHeaderData(header.rowEnd, mergedRowEndRanges, rowEndHeaderRowStart, rowEndHeaderColumnStart, 'rowEndHeader', true, true);
    }
    // Renders column headers
    if (ranges.columnHeaders && header?.column) {
        const mergedColumnRanges = mergeHeaderRanges(ranges.columnHeaders, (range) => range.columnStart, (range) => range.columnCount);
        processHeaderData(header.column, mergedColumnRanges, columnHeaderRowStart, columnHeaderColumnStart, 'columnHeader', false, false);
    }
    // Renders column end headers
    if (ranges.columnEndHeaders && header?.columnEnd) {
        const mergedColumnEndRanges = mergeHeaderRanges(ranges.columnEndHeaders, (range) => range.columnStart, (range) => range.columnCount);
        processHeaderData(header.columnEnd, mergedColumnEndRanges, columnEndHeaderRowStart, columnEndHeaderColumnStart, 'columnEndHeader', false, true);
    }
    // makes sure we are in bounds of given range
    const getCellRangeBounds = (range) => ({
        rowStart: range.rowStart,
        rowEnd: range.rowCount + range.rowStart,
        columnStart: range.columnStart,
        columnEnd: range.columnCount + range.columnStart
    });
    // Makes sure cell range is valid
    const isValidCellRange = (range) => range?.rowCount != null &&
        range?.rowStart != null &&
        range?.columnCount != null &&
        range?.columnStart != null;
    // Makes sure we account for merged cells by adding to seenIndex
    const handleCellSkips = (rowStart, rowExtent, columnStart, columnExtent) => {
        for (let i = rowStart; i < rowStart + rowExtent; i++) {
            for (let j = columnStart; j < columnStart + columnExtent; j++) {
                seenIndexMap.set(`${i},${j}`, { cellType: 'skip' });
            }
        }
    };
    // Walks ranges and adds appropriate cells to grid
    const processCellData = (item, rangeArray) => {
        rangeArray.forEach((range) => {
            if (isValidCellRange(range)) {
                const { rowStart, rowEnd, columnStart, columnEnd } = getCellRangeBounds(range);
                for (let i = rowStart; i < rowEnd; i++) {
                    for (let j = columnStart; j < columnEnd; j++) {
                        const rowIndex = rowHeaderRowStart + i;
                        const columnIndex = columnHeaderColumnStart + j;
                        const cellObject = seenIndexMap.get(`${rowIndex},${columnIndex}`);
                        if (cellObject?.cellType === 'skip') {
                            continue;
                        }
                        const cellData = item.data(i, j);
                        const rowExtent = cellData.rowExtent;
                        const columnExtent = cellData.columnExtent;
                        grid.push({
                            cellType: 'cell',
                            rowStart: rowIndex,
                            rowExtent: rowExtent,
                            columnStart: columnIndex,
                            columnExtent: columnExtent,
                            data: cellData.data,
                            lastColumn: j + columnExtent === dataRegionColumnCount,
                            lastRow: i + rowExtent === dataRegionRowCount
                        });
                        if (rowExtent > 1 || columnExtent > 1) {
                            handleCellSkips(rowIndex, rowExtent, columnIndex, columnExtent);
                        }
                    }
                }
            }
        });
    };
    // Renders cells
    if (cell && mergedDataBody) {
        processCellData(cell, mergedDataBody);
    }
    skeletonList.forEach((skeletonCell) => {
        let rowIndex = skeletonCell.rowIndex ? skeletonCell.rowIndex : 0;
        let rowExtent = 1;
        const columnExtent = 1;
        let columnIndex = skeletonCell.columnIndex ? skeletonCell.columnIndex : 0;
        if (skeletonCell.type === 'columnHeaderSkeleton') {
            rowIndex = columnHeaderRowStart + skeletonCell.level;
            if (collision && skeletonCell.level + 1 === header?.column?.levels) {
                rowExtent = 2;
            }
            columnIndex = columnHeaderColumnStart + columnIndex;
        }
        else if (skeletonCell.type === 'columnEndHeaderSkeleton') {
            rowIndex =
                columnEndHeaderRowStart + getHeaderLevels(header, _COLUMN_END_CONST) - rowIndex - 1;
            columnIndex = columnEndHeaderColumnStart + columnIndex;
        }
        else if (skeletonCell.type === 'rowHeaderSkeleton') {
            columnIndex = rowHeaderColumnStart + skeletonCell.level;
            rowIndex = rowHeaderRowStart + rowIndex;
        }
        else if (skeletonCell.type === 'rowEndHeaderSkeleton') {
            columnIndex =
                rowEndHeaderColumnStart + getHeaderLevels(header, _ROW_END_CONST) - columnIndex - 1;
            rowIndex = rowEndHeaderRowStart + rowIndex;
        }
        else {
            rowIndex = rowHeaderRowStart + rowIndex;
            columnIndex = columnHeaderColumnStart + columnIndex;
        }
        grid.push({
            cellType: skeletonCell.type,
            rowStart: rowIndex,
            rowExtent: rowExtent,
            columnStart: columnIndex,
            columnExtent: columnExtent,
            level: skeletonCell.level,
            borderTop: skeletonCell.type === 'columnEndHeaderSkeleton' &&
                skeletonCell.level + 1 === header?.columnEnd?.levels
                ? true
                : false,
            borderLeft: skeletonCell.type === 'rowEndHeaderSkeleton' &&
                skeletonCell.level + 1 === header?.rowEnd?.levels
                ? true
                : false
        });
    });
    // need this in order to build
    onLoadRange({});
    // renders the style template strings for grid.
    const getGridStyle = () => {
        const rows = `grid-template-rows: ${Array(gridTotalRows).fill(`${_CELL_HEIGHT}px`).join(' ')};`;
        const columns = `grid-template-columns: ${Array(gridTotalColumns)
            .fill(`${_CELL_WIDTH}px`)
            .join(' ')};`;
        const dimensions = `width: ${width}px; height: ${height}px;`;
        return `${rows} ${columns} ${dimensions}`;
    };
    const classes = classNames.classNames([PRIVATE_DataGrid_themes_DataGrid_css.dataGridStyles.base]);
    return { grid, classes, style: getGridStyle(), cellHeight: _CELL_HEIGHT, cellWidth: _CELL_WIDTH };
};

/**
 * Component that renders a basic grid.
 */
const DataGrid = function DataGrid(props) {
    const [skeletonList, setSkeletonList] = hooks.useState([]);
    const { grid, classes, style, cellHeight, cellWidth } = renderGrid(props, skeletonList);
    const calculateViewportRange = (element, cellSize, totalCount, isVertical) => {
        const totalInViewPort = Math.round((isVertical ? element.offsetHeight : element.offsetWidth) / cellSize);
        const firstPosition = Math.round((isVertical ? element.scrollTop : element.scrollLeft) / cellSize);
        const buffer = Math.round(totalInViewPort / 2);
        const tempTopPosition = firstPosition - buffer;
        const topPosition = tempTopPosition > 0 ? tempTopPosition : 0;
        const tempBottomPosition = topPosition + totalInViewPort + buffer * 2;
        const bottomPosition = tempBottomPosition < totalCount ? tempBottomPosition : totalCount;
        return { topPosition, bottomPosition };
    };
    const generateSkeletonsForHeaders = (levels, ranges, topViewport, bottomViewport, type, tempSkeletonList, isRow = true) => {
        if (ranges && levels) {
            for (let level = 0; level < levels; level++) {
                const skeletonArray = new Array(bottomViewport).fill(null);
                ranges.forEach((range) => {
                    const start = isRow ? range.rowStart : range.columnStart;
                    const count = isRow ? range.rowCount : range.columnCount;
                    for (let i = start; i < start + count; i++) {
                        if (i < skeletonArray.length) {
                            skeletonArray[i] = true;
                        }
                    }
                });
                for (let i = topViewport; i < skeletonArray.length; i++) {
                    if (!skeletonArray[i]) {
                        tempSkeletonList.push({
                            type: `${type}Skeleton`,
                            [isRow ? 'rowIndex' : 'columnIndex']: i,
                            level: level
                        });
                    }
                }
            }
        }
    };
    hooks.useEffect(() => {
        const element = document.getElementById('dataGrid');
        const { topPosition: topRowOfViewPort, bottomPosition: bottomRowOfViewPort } = calculateViewportRange(element, cellHeight, props.totalRowCount, true);
        const { topPosition: topColumnOfViewPort, bottomPosition: bottomColumnOfViewPort } = calculateViewportRange(element, cellWidth, props.totalColumnCount, false);
        const tempSkeletonList = [];
        generateSkeletonsForHeaders(props.header?.row?.levels, props.ranges.rowHeaders, topRowOfViewPort, bottomRowOfViewPort, 'rowHeader', tempSkeletonList, true);
        generateSkeletonsForHeaders(props.header?.rowEnd?.levels, props.ranges.rowEndHeaders, topRowOfViewPort, bottomRowOfViewPort, 'rowEndHeader', tempSkeletonList, true);
        generateSkeletonsForHeaders(props.header?.column?.levels, props.ranges.columnHeaders, topColumnOfViewPort, bottomColumnOfViewPort, 'columnHeader', tempSkeletonList, false);
        generateSkeletonsForHeaders(props.header?.columnEnd?.levels, props.ranges.columnEndHeaders, topColumnOfViewPort, bottomColumnOfViewPort, 'columnEndHeader', tempSkeletonList, false);
        if (props.ranges.dataBody) {
            const skeletonArray = new Array(bottomColumnOfViewPort)
                .fill(null)
                .map(() => new Array(bottomRowOfViewPort).fill(null));
            props.ranges.dataBody.forEach((range) => {
                for (let i = range.columnStart; i < range.columnStart + range.columnCount; i++) {
                    if (i < skeletonArray.length) {
                        for (let j = range.rowStart; j < range.rowStart + range.rowCount; j++) {
                            if (j < skeletonArray[i].length) {
                                skeletonArray[i][j] = true;
                            }
                        }
                    }
                }
            });
            for (let i = topColumnOfViewPort; i < skeletonArray.length; i++) {
                for (let j = topRowOfViewPort; j < skeletonArray[i].length; j++) {
                    if (!skeletonArray[i][j]) {
                        tempSkeletonList.push({ type: 'cellSkeleton', columnIndex: i, rowIndex: j });
                    }
                }
            }
        }
        setSkeletonList(tempSkeletonList);
    }, [cellHeight, cellWidth, props]);
    return (jsxRuntime.jsx("div", { id: "dataGrid", role: 'application', class: classes, style: style, children: grid.map((gridCell) => (jsxRuntime.jsx(DataGridCell, { cell: gridCell, height: cellHeight, width: cellWidth }))) }));
};

exports.DataGrid = DataGrid;
//# sourceMappingURL=DataGrid-f10acae2.js.map
