import { Host, h } from "@stencil/core";
import { getScrollOffsetFromStart } from "../../utils/scroll";
export class PdsTable {
    constructor() {
        this.scrollContainer = null;
        this._responsiveHandleScroll = null;
        this._responsiveHandleResize = null;
        this._responsiveResizeObserver = null;
        this._teardownResponsive = null;
        /**
         * Hides the select-all checkbox in the table header while keeping individual row checkboxes functional.
         * Only applies when `selectable` is true.
         * @defaultValue false
         */
        this.disableSelectAll = false;
        /**
         * Adds divider borders between table rows. The last row will not have a bottom border.
         * @defaultValue false
         */
        this.rowDividers = false;
        /**
         * The direction to sort the default column on initial load.
         * Only applies if `defaultSortColumn` is set.
         * @defaultValue 'asc'
         */
        this.defaultSortDirection = 'asc';
        /**
         * The name of the column being sorted.
         * @defaultValue null
         */
        this.sortingColumn = null;
        /**
         * The direction of sorting.
         * @defaultValue 'asc'
         */
        this.sortingDirection = 'asc';
    }
    componentDidLoad() {
        if (this.responsive) {
            this.setupResponsiveScrolling();
        }
        // Apply default sort if specified
        // Use requestAnimationFrame to defer until child components are fully initialized
        if (this.defaultSortColumn) {
            requestAnimationFrame(() => {
                void this.applyDefaultSort().catch((err) => {
                    console.warn('Failed to apply default sort.', err);
                });
            });
        }
    }
    /**
     * Applies the default sort configuration on initial load.
     * Finds the matching column header and activates its sort state.
     * @private
     */
    async applyDefaultSort() {
        var _a;
        // Normalize direction to handle invalid HTML attribute values
        const direction = this.defaultSortDirection === 'desc' ? 'desc' : 'asc';
        // Find the matching sortable header cell
        const columnHeaderCells = Array.from(this.el.querySelectorAll('pds-table-head-cell[sortable]'));
        const matchingCell = columnHeaderCells.find((cell) => { var _a; return ((_a = cell.textContent) !== null && _a !== void 0 ? _a : '').trim() === this.defaultSortColumn; });
        if (matchingCell) {
            const columnName = ((_a = matchingCell.textContent) !== null && _a !== void 0 ? _a : '').trim();
            // Sort the table data
            this.sortTable(columnName, direction);
            this.sortingColumn = columnName;
            this.sortingDirection = direction;
            // Activate the visual state on the header cell
            await matchingCell.setActiveSort(direction);
        }
        else {
            console.warn(`Default sort column "${this.defaultSortColumn}" not found.`);
        }
    }
    disconnectedCallback() {
        if (this._teardownResponsive) {
            this._teardownResponsive();
            this._teardownResponsive = null;
        }
    }
    /**
     * Sets up responsive scrolling behavior for the table.
     *
     * This method creates a horizontal scrolling system where:
     * - The table content can scroll horizontally when it exceeds the container width
     * - Scroll shadows appear at the inline-start/end edges to indicate scrollable content
     * - Fixed columns remain sticky during horizontal scrolling
     * - Shadows respect border-radius and don't appear when there's nothing to scroll
     *
     * Architecture:
     * - Host element: Contains everything, respects parent constraints
     * - Container element: Handles horizontal scrolling (overflow-x: auto)
     * - Shadow elements: Positioned fixed relative to host, show scroll indicators
     *
     * @private
     */
    setupResponsiveScrolling() {
        var _a, _b, _c;
        const container = (_a = this.el.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('.pds-table-responsive-container');
        const leftShadow = (_b = this.el.shadowRoot) === null || _b === void 0 ? void 0 : _b.querySelector('.scroll-shadow-left');
        const rightShadow = (_c = this.el.shadowRoot) === null || _c === void 0 ? void 0 : _c.querySelector('.scroll-shadow-right');
        if (!container || !leftShadow || !rightShadow)
            return;
        // Store container reference for cleanup
        this.scrollContainer = container;
        /**
         * Updates the visibility of scroll shadows based on current scroll position.
         * Inline-start shadow: shows when scrolled away from start (hidden if fixedColumn is enabled)
         * Inline-end shadow: shows when there is content to scroll and not at the end
         */
        this._responsiveHandleScroll = () => {
            if (!this.scrollContainer)
                return;
            const { scrollWidth, clientWidth } = this.scrollContainer;
            const maxScroll = scrollWidth - clientWidth;
            const scrollOffset = getScrollOffsetFromStart(this.scrollContainer);
            // Inline-start shadow when scrolled away from start, but not if there's a fixed column
            leftShadow.style.opacity = (scrollOffset > 0 && !this.fixedColumn) ? '1' : '0';
            // Inline-end shadow when there is content to scroll and not at the end
            rightShadow.style.opacity = (maxScroll > 0 && scrollOffset < maxScroll - 1) ? '1' : '0';
        };
        // Add scroll event listener to container element
        this.scrollContainer.addEventListener('scroll', this._responsiveHandleScroll, { passive: true });
        // Add resize observer to update shadows when container size changes
        if (typeof window !== 'undefined' && window.ResizeObserver) {
            try {
                this._responsiveResizeObserver = new ResizeObserver(() => {
                    var _a;
                    (_a = this._responsiveHandleScroll) === null || _a === void 0 ? void 0 : _a.call(this);
                });
                this._responsiveResizeObserver.observe(this.scrollContainer);
            }
            catch (error) {
                // ResizeObserver not available in some environments (e.g., tests)
                // Fall back to window resize listener only
            }
        }
        // Listen for window resize as fallback
        if (typeof window !== 'undefined') {
            this._responsiveHandleResize = () => {
                var _a;
                (_a = this._responsiveHandleScroll) === null || _a === void 0 ? void 0 : _a.call(this);
            };
            window.addEventListener('resize', this._responsiveHandleResize);
        }
        // Create teardown function for cleanup
        this._teardownResponsive = () => {
            if (this.scrollContainer && this._responsiveHandleScroll) {
                this.scrollContainer.removeEventListener('scroll', this._responsiveHandleScroll);
                this.scrollContainer = null;
            }
            if (this._responsiveResizeObserver) {
                this._responsiveResizeObserver.disconnect();
                this._responsiveResizeObserver = null;
            }
            if (typeof window !== 'undefined' && this._responsiveHandleResize) {
                window.removeEventListener('resize', this._responsiveHandleResize);
                this._responsiveHandleResize = null;
            }
            this._responsiveHandleScroll = null;
        };
        // Initial check after setup
        this._responsiveHandleScroll();
    }
    classNames() {
        const classNames = ['pds-table'];
        if (this.compact) {
            classNames.push('is-compact');
        }
        if (this.responsive) {
            classNames.push('is-responsive');
        }
        return classNames.join('  ');
    }
    sortTable(column, direction) {
        const tableBody = this.el.querySelector('pds-table-body');
        // Return early if no table body exists
        if (!tableBody)
            return;
        // Get the rows in the table body
        const tableRows = Array.from(tableBody.querySelectorAll('pds-table-row'));
        // Find the column index based on the column name
        const columnHeaderCells = Array.from(this.el.querySelectorAll('pds-table-head-cell[sortable]'));
        const columnHeaderCell = columnHeaderCells.find((cell) => cell.innerText.trim() === column);
        if (!columnHeaderCell) {
            console.warn(`Column "${column}" not found.`);
            return;
        }
        const columnIndex = columnHeaderCells.indexOf(columnHeaderCell);
        // Sort the rows based on the content of the specified column
        tableRows.sort((a, b) => {
            const valueA = a.querySelector(`pds-table-cell:nth-child(${columnIndex + 1})`).textContent.trim();
            const valueB = b.querySelector(`pds-table-cell:nth-child(${columnIndex + 1})`).textContent.trim();
            if (direction === 'asc') {
                return valueA.localeCompare(valueB, undefined, { sensitivity: 'base' });
            }
            else {
                return valueB.localeCompare(valueA, undefined, { sensitivity: 'base' });
            }
        });
        // Clear and append the sorted rows back to the table body
        tableBody.innerHTML = '';
        tableRows.forEach((row) => {
            tableBody.appendChild(row);
        });
    }
    handleTableSort(event) {
        if (event.defaultPrevented)
            return;
        const { direction } = event.detail;
        this.sortTable(event.detail.column, direction);
        this.sortingColumn = event.detail.column;
        this.sortingDirection = direction;
    }
    handleTableSelectAll(event) {
        if (event.defaultPrevented)
            return;
        const pdsTableBody = this.el.querySelector('pds-table-body');
        const tableRows = Array.from(pdsTableBody.querySelectorAll('pds-table-row'));
        tableRows.forEach((row) => {
            row.isSelected = event.detail.isSelected;
        });
    }
    async handleTableSelect(event) {
        if (event.defaultPrevented)
            return;
        const allTableRows = this.el.querySelectorAll('pds-table-row');
        const allSelectedRows = Array.from(allTableRows).every((row) => row.isSelected);
        const noneSelectedRows = Array.from(allTableRows).every((row) => !row.isSelected);
        const pdsTableHead = this.el.querySelector('pds-table-head');
        if (!pdsTableHead)
            return;
        const headerCheckbox = pdsTableHead.shadowRoot.querySelector('pds-checkbox');
        if (headerCheckbox) {
            headerCheckbox.checked = allSelectedRows;
            headerCheckbox.indeterminate = !allSelectedRows && !noneSelectedRows;
        }
    }
    render() {
        if (this.responsive) {
            return (h(Host, { class: "pds-table is-responsive pds-table-responsive-host", id: this.componentId, role: "grid", selectable: this.selectable, tabindex: "0", part: "table responsive-table" }, h("div", { class: "scroll-shadow-left", part: "scroll-shadow-left" }), h("div", { class: "scroll-shadow-right", part: "scroll-shadow-right" }), h("div", { class: "pds-table-responsive-container", part: "responsive-container" }, h("div", { class: "pds-table-responsive-wrapper", part: "responsive-wrapper" }, h("div", { class: this.classNames(), part: "table-inner" }, h("slot", null))))));
        }
        return (h(Host, { class: this.classNames(), id: this.componentId, role: "grid", selectable: this.selectable, tabindex: "0", part: "table" }, h("slot", null)));
    }
    static get is() { return "pds-table"; }
    static get encapsulation() { return "shadow"; }
    static get originalStyleUrls() {
        return {
            "$": ["pds-table.scss"]
        };
    }
    static get styleUrls() {
        return {
            "$": ["pds-table.css"]
        };
    }
    static get properties() {
        return {
            "compact": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Determines if the table displays with reduced table cell padding."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "compact"
            },
            "componentId": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": true,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "A unique identifier used for the table `id` attribute."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "component-id"
            },
            "responsive": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Enables the table to be responsive by horizontally scrolling on smaller screens."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "responsive"
            },
            "fixedColumn": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Determines if the should display a fixed first column."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "fixed-column"
            },
            "selectable": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [],
                    "text": "Determines if the table displays checkboxes for selectable rows."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "selectable"
            },
            "disableSelectAll": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "defaultValue",
                            "text": "false"
                        }],
                    "text": "Hides the select-all checkbox in the table header while keeping individual row checkboxes functional.\nOnly applies when `selectable` is true."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "disable-select-all",
                "defaultValue": "false"
            },
            "rowDividers": {
                "type": "boolean",
                "mutable": false,
                "complexType": {
                    "original": "boolean",
                    "resolved": "boolean",
                    "references": {}
                },
                "required": false,
                "optional": false,
                "docs": {
                    "tags": [{
                            "name": "defaultValue",
                            "text": "false"
                        }],
                    "text": "Adds divider borders between table rows. The last row will not have a bottom border."
                },
                "getter": false,
                "setter": false,
                "reflect": true,
                "attribute": "row-dividers",
                "defaultValue": "false"
            },
            "defaultSortColumn": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "string",
                    "resolved": "string",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [],
                    "text": "The name of the column to sort by on initial load.\nMust match the text content of a sortable column header."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "default-sort-column"
            },
            "defaultSortDirection": {
                "type": "string",
                "mutable": false,
                "complexType": {
                    "original": "'asc' | 'desc'",
                    "resolved": "\"asc\" | \"desc\"",
                    "references": {}
                },
                "required": false,
                "optional": true,
                "docs": {
                    "tags": [{
                            "name": "defaultValue",
                            "text": "'asc'"
                        }],
                    "text": "The direction to sort the default column on initial load.\nOnly applies if `defaultSortColumn` is set."
                },
                "getter": false,
                "setter": false,
                "reflect": false,
                "attribute": "default-sort-direction",
                "defaultValue": "'asc'"
            }
        };
    }
    static get states() {
        return {
            "sortingColumn": {},
            "sortingDirection": {}
        };
    }
    static get events() {
        return [{
                "method": "pdsTableSelectAll",
                "name": "pdsTableSelectAll",
                "bubbles": true,
                "cancelable": true,
                "composed": true,
                "docs": {
                    "tags": [],
                    "text": "Event that is emitted when the select all checkbox is clicked, carrying the selected value."
                },
                "complexType": {
                    "original": "{ isSelected: boolean }",
                    "resolved": "{ isSelected: boolean; }",
                    "references": {}
                }
            }];
    }
    static get elementRef() { return "el"; }
    static get listeners() {
        return [{
                "name": "pdsTableSort",
                "method": "handleTableSort",
                "target": undefined,
                "capture": false,
                "passive": false
            }, {
                "name": "pdsTableSelectAll",
                "method": "handleTableSelectAll",
                "target": undefined,
                "capture": false,
                "passive": false
            }, {
                "name": "pdsTableRowSelected",
                "method": "handleTableSelect",
                "target": undefined,
                "capture": false,
                "passive": false
            }];
    }
}
//# sourceMappingURL=pds-table.js.map
