/*
 * Copyright (C) 2008-2018 Apple Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
 * THE POSSIBILITY OF SUCH DAMAGE.
 */

WI.Table = class Table extends WI.View
{
    constructor(identifier, dataSource, delegate, rowHeight)
    {
        super();

        console.assert(typeof identifier === "string");
        console.assert(dataSource);
        console.assert(delegate);
        console.assert(rowHeight > 0);

        this._identifier = identifier;
        this._dataSource = dataSource;
        this._delegate = delegate;
        this._rowHeight = rowHeight;

        // FIXME: Should be able to horizontally scroll non-locked table contents.
        // To do this smoothly (without tearing) will require synchronous scroll events, or
        // synchronized scrolling between multiple elements, or making `position: sticky`
        // respect different vertical / horizontal scroll containers.

        this.element.classList.add("table", identifier);
        this.element.tabIndex = 0;
        this.element.addEventListener("keydown", this._handleKeyDown.bind(this));

        this._headerElement = this.element.appendChild(document.createElement("div"));
        this._headerElement.className = "header";

        let scrollHandler = this._handleScroll.bind(this);
        this._scrollContainerElement = this.element.appendChild(document.createElement("div"));
        this._scrollContainerElement.className = "data-container";
        this._scrollContainerElement.addEventListener("scroll", scrollHandler);
        this._scrollContainerElement.addEventListener("mousewheel", scrollHandler);
        this._scrollContainerElement.addEventListener("mousedown", this._handleMouseDown.bind(this));
        if (this._delegate.tableCellContextMenuClicked)
            this._scrollContainerElement.addEventListener("contextmenu", this._handleContextMenu.bind(this));

        this._topSpacerElement = this._scrollContainerElement.appendChild(document.createElement("div"));
        this._topSpacerElement.className = "spacer";

        this._listElement = this._scrollContainerElement.appendChild(document.createElement("ul"));
        this._listElement.className = "data-list";

        this._bottomSpacerElement = this._scrollContainerElement.appendChild(document.createElement("div"));
        this._bottomSpacerElement.className = "spacer";

        this._fillerRow = this._listElement.appendChild(document.createElement("li"));
        this._fillerRow.className = "filler";

        this._resizersElement = this._element.appendChild(document.createElement("div"));
        this._resizersElement.className = "resizers";

        this._cachedRows = new Map;

        this._columnSpecs = new Map;
        this._columnOrder = [];
        this._visibleColumns = [];
        this._hiddenColumns = [];

        this._widthGeneration = 1;
        this._columnWidths = null; // Calculated in _resizeColumnsAndFiller.
        this._fillerHeight = 0; // Calculated in _resizeColumnsAndFiller.

        this._selectionController = new WI.SelectionController(this, (a, b) => this._indexForRepresentedObject(a) - this._indexForRepresentedObject(b));

        this._resizers = [];
        this._currentResizer = null;
        this._resizeLeftColumns = null;
        this._resizeRightColumns = null;
        this._resizeOriginalColumnWidths = null;
        this._lastColumnIndexToAcceptRemainderPixel = 0;

        this._sortOrderSetting = new WI.Setting(this._identifier + "-sort-order", WI.Table.SortOrder.Indeterminate);
        this._sortColumnIdentifierSetting = new WI.Setting(this._identifier + "-sort", null);
        this._columnVisibilitySetting = new WI.Setting(this._identifier + "-column-visibility", {});

        this._sortOrder = this._sortOrderSetting.value;
        this._sortColumnIdentifier = this._sortColumnIdentifierSetting.value;

        this._cachedWidth = NaN;
        this._cachedHeight = NaN;
        this._cachedScrollTop = NaN;
        this._previousCachedWidth = NaN;
        this._previousRevealedRowCount = NaN;
        this._topSpacerHeight = NaN;
        this._bottomSpacerHeight = NaN;
        this._visibleRowIndexStart = NaN;
        this._visibleRowIndexEnd = NaN;

        console.assert(this._dataSource.tableNumberOfRows, "Table data source must implement tableNumberOfRows.");
        console.assert(this._dataSource.tableIndexForRepresentedObject, "Table data source must implement tableIndexForRepresentedObject.");
        console.assert(this._dataSource.tableRepresentedObjectForIndex, "Table data source must implement tableRepresentedObjectForIndex.");

        console.assert(this._delegate.tablePopulateCell, "Table delegate must implement tablePopulateCell.");
    }

    // Public

    get identifier() { return this._identifier; }
    get dataSource() { return this._dataSource; }
    get delegate() { return this._delegate; }
    get rowHeight() { return this._rowHeight; }

    get selectedRow()
    {
        let item = this._selectionController.lastSelectedItem;
        let index = this._indexForRepresentedObject(item);
        return index >= 0 ? index : NaN;
    }

    get selectedRows()
    {
        let rowIndexes = [];
        for (let item of this._selectionController.selectedItems)
            rowIndexes.push(this._indexForRepresentedObject(item));
        return rowIndexes;
    }

    get scrollContainer() { return this._scrollContainerElement; }

    get numberOfRows()
    {
        return this._dataSource.tableNumberOfRows(this);
    }

    get sortOrder()
    {
        return this._sortOrder;
    }

    set sortOrder(sortOrder)
    {
        if (sortOrder === this._sortOrder && this.didInitialLayout)
            return;

        console.assert(sortOrder === WI.Table.SortOrder.Indeterminate || sortOrder === WI.Table.SortOrder.Ascending || sortOrder === WI.Table.SortOrder.Descending);

        this._sortOrder = sortOrder;
        this._sortOrderSetting.value = sortOrder;

        if (this._sortColumnIdentifier) {
            let column = this._columnSpecs.get(this._sortColumnIdentifier);
            let columnIndex = this._visibleColumns.indexOf(column);
            if (columnIndex !== -1) {
                let headerCell = this._headerElement.children[columnIndex];
                headerCell.classList.toggle("sort-ascending", this._sortOrder === WI.Table.SortOrder.Ascending);
                headerCell.classList.toggle("sort-descending", this._sortOrder === WI.Table.SortOrder.Descending);
            }

            if (this._dataSource.tableSortChanged)
                this._dataSource.tableSortChanged(this);
        }
    }

    get sortColumnIdentifier()
    {
        return this._sortColumnIdentifier;
    }

    set sortColumnIdentifier(columnIdentifier)
    {
        if (columnIdentifier === this._sortColumnIdentifier && this.didInitialLayout)
            return;

        let column = this._columnSpecs.get(columnIdentifier);

        console.assert(column, "Column not found.", columnIdentifier);
        if (!column)
            return;

        console.assert(column.sortable, "Column is not sortable.", columnIdentifier);
        if (!column.sortable)
            return;

        let oldSortColumnIdentifier = this._sortColumnIdentifier;
        this._sortColumnIdentifier = columnIdentifier;
        this._sortColumnIdentifierSetting.value = columnIdentifier;

        if (oldSortColumnIdentifier) {
            let oldColumn = this._columnSpecs.get(oldSortColumnIdentifier);
            let oldColumnIndex = this._visibleColumns.indexOf(oldColumn);
            if (oldColumnIndex !== -1) {
                let headerCell = this._headerElement.children[oldColumnIndex];
                headerCell.classList.remove("sort-ascending", "sort-descending");
            }
        }

        if (this._sortColumnIdentifier) {
            let newColumnIndex = this._visibleColumns.indexOf(column);
            if (newColumnIndex !== -1) {
                let headerCell = this._headerElement.children[newColumnIndex];
                headerCell.classList.toggle("sort-ascending", this._sortOrder === WI.Table.SortOrder.Ascending);
                headerCell.classList.toggle("sort-descending", this._sortOrder === WI.Table.SortOrder.Descending);
            } else
                this._sortColumnIdentifier = null;
        }

        if (this._dataSource.tableSortChanged)
            this._dataSource.tableSortChanged(this);
    }

    get allowsMultipleSelection()
    {
        return this._selectionController.allowsMultipleSelection;
    }

    set allowsMultipleSelection(flag)
    {
        this._selectionController.allowsMultipleSelection = flag;
    }

    get columns()
    {
        return Array.from(this._columnSpecs.values());
    }

    isRowSelected(rowIndex)
    {
        return this._selectionController.hasSelectedItem(this._representedObjectForIndex(rowIndex));
    }

    reloadData()
    {
        this._cachedRows.clear();

        this._selectionController.reset();

        this._previousRevealedRowCount = NaN;
        this.needsLayout();
    }

    reloadDataAddedToEndOnly()
    {
        this._previousRevealedRowCount = NaN;
        this.needsLayout();
    }

    reloadRow(rowIndex)
    {
        // Visible row, repopulate the cell.
        if (this._isRowVisible(rowIndex)) {
            let row = this._cachedRows.get(rowIndex);
            if (!row)
                return;
            this._populateRow(row);
            return;
        }

        // Non-visible row, will populate when it becomes visible.
        this._cachedRows.delete(rowIndex);
    }

    reloadVisibleColumnCells(column)
    {
        let columnIndex = this._visibleColumns.indexOf(column);
        if (columnIndex === -1)
            return;

        let numberOfRows = Math.min(this._visibleRowIndexEnd, this.numberOfRows);
        for (let rowIndex = this._visibleRowIndexStart; rowIndex < numberOfRows; ++rowIndex) {
            let row = this._cachedRows.get(rowIndex);
            if (!row)
                continue;
            let cell = row.children[columnIndex];
            if (!cell)
                continue;
            this._delegate.tablePopulateCell(this, cell, column, rowIndex);
        }
    }

    reloadCell(rowIndex, columnIdentifier)
    {
        let column = this._columnSpecs.get(columnIdentifier);
        let columnIndex = this._visibleColumns.indexOf(column);
        if (columnIndex === -1)
            return;

        // Visible row, repopulate the cell.
        if (this._isRowVisible(rowIndex)) {
            let row = this._cachedRows.get(rowIndex);
            if (!row)
                return;
            let cell = row.children[columnIndex];
            if (!cell)
                return;
            this._delegate.tablePopulateCell(this, cell, column, rowIndex);
            return;
        }

        // Non-visible row, will populate when it becomes visible.
        this._cachedRows.delete(rowIndex);
    }

    selectRow(rowIndex, extendSelection = false)
    {
        this._selectionController.selectItem(this._representedObjectForIndex(rowIndex), extendSelection);
    }

    deselectRow(rowIndex)
    {
        this._selectionController.deselectItem(this._representedObjectForIndex(rowIndex));
    }

    selectAll()
    {
        this._selectionController.selectAll();
    }

    deselectAll()
    {
        this._selectionController.deselectAll();
    }

    removeRow(rowIndex)
    {
        console.assert(rowIndex >= 0 && rowIndex < this.numberOfRows);

        if (this.isRowSelected(rowIndex))
            this.deselectRow(rowIndex);

        this._removeRows(new Set([this._representedObjectForIndex(rowIndex)]));
    }

    removeSelectedRows()
    {
        let selectedItems = this._selectionController.selectedItems;
        if (!selectedItems.size)
            return;

        // Change the selection before removing rows. This matches the behavior
        // of macOS Finder (in list and column modes) when removing selected items.
        this._selectionController.removeSelectedItems();

        this._removeRows(selectedItems);
    }

    revealRow(rowIndex)
    {
        console.assert(rowIndex >= 0 && rowIndex < this.numberOfRows);
        if (rowIndex < 0 || rowIndex >= this.numberOfRows)
            return;

        // Force our own scroll update because we may have scrolled.
        this._cachedScrollTop = NaN;

        if (this._isRowVisible(rowIndex)) {
            let row = this._cachedRows.get(rowIndex);
            console.assert(row, "Visible rows should always be in the cache.");
            if (row)
                row.scrollIntoViewIfNeeded(false);
            this.needsLayout();
        } else {
            this._scrollContainerElement.scrollTop = rowIndex * this._rowHeight;
            this.updateLayout();
        }
    }

    columnWithIdentifier(identifier)
    {
        return this._columnSpecs.get(identifier);
    }

    cellForRowAndColumn(rowIndex, column)
    {
        if (!this._isRowVisible(rowIndex))
            return null;

        let row = this._cachedRows.get(rowIndex);
        if (!row)
            return null;

        let columnIndex = this._visibleColumns.indexOf(column);
        if (columnIndex === -1)
            return null;

        return row.children[columnIndex];
    }

    addColumn(column)
    {
        this._columnSpecs.set(column.identifier, column);
        this._columnOrder.push(column.identifier);

        if (column.hidden) {
            this._hiddenColumns.push(column);
            column.width = NaN;
        } else {
            this._visibleColumns.push(column);
            this._headerElement.appendChild(this._createHeaderCell(column));
            this._fillerRow.appendChild(this._createFillerCell(column));
            if (column.headerView)
                this.addSubview(column.headerView);
        }

        // Restore saved user-specified column visibility.
        let savedColumnVisibility = this._columnVisibilitySetting.value;
        if (column.identifier in savedColumnVisibility) {
            let visible = savedColumnVisibility[column.identifier];
            if (visible)
                this.showColumn(column);
            else
                this.hideColumn(column);
        }

        this.reloadData();
    }

    showColumn(column)
    {
        console.assert(this._columnSpecs.get(column.identifier) === column, "Column not in this table.");
        console.assert(!column.locked, "Locked columns should always be shown.");
        if (column.locked)
            return;

        if (!column.hidden)
            return;

        column.hidden = false;

        let columnIndex = this._hiddenColumns.indexOf(column);
        this._hiddenColumns.splice(columnIndex, 1);

        let newColumnIndex = this._indexToInsertColumn(column);
        this._visibleColumns.insertAtIndex(column, newColumnIndex);

        // Save user preference for this column to be visible.
        let savedColumnVisibility = this._columnVisibilitySetting.value;
        if (savedColumnVisibility[column.identifier] !== true) {
            let copy = Object.shallowCopy(savedColumnVisibility);
            if (column.defaultHidden)
                copy[column.identifier] = true;
            else
                delete copy[column.identifier];
            this._columnVisibilitySetting.value = copy;
        }

        this._headerElement.insertBefore(this._createHeaderCell(column), this._headerElement.children[newColumnIndex]);
        this._fillerRow.insertBefore(this._createFillerCell(column), this._fillerRow.children[newColumnIndex]);

        if (column.headerView)
            this.addSubview(column.headerView);

        if (this._sortColumnIdentifier === column.identifier) {
            let headerCell = this._headerElement.children[newColumnIndex];
            headerCell.classList.toggle("sort-ascending", this._sortOrder === WI.Table.SortOrder.Ascending);
            headerCell.classList.toggle("sort-descending", this._sortOrder === WI.Table.SortOrder.Descending);
        }

        // We haven't yet done any layout, nothing to do.
        if (!this._columnWidths)
            return;

        // To avoid recreating all the cells in the row we create empty cells,
        // size them, and then populate them. We always populate a cell after
        // it has been sized.
        let cellsToPopulate = [];
        for (let row of this._listElement.children) {
            if (row !== this._fillerRow) {
                let unpopulatedCell = this._createCell(column, newColumnIndex);
                cellsToPopulate.push(unpopulatedCell);
                row.insertBefore(unpopulatedCell, row.children[newColumnIndex]);
            }
        }

        // Re-layout all columns to make space.
        this._widthGeneration++;
        this._columnWidths = null;
        this._resizeColumnsAndFiller();

        // Now populate only the new cells for this column.
        for (let cell of cellsToPopulate)
            this._delegate.tablePopulateCell(this, cell, column, cell.parentElement.__index);

        // Now populate columns that may be sensitive to resizes.
        for (let visibleColumn of this._visibleColumns) {
            if (visibleColumn !== column) {
                if (visibleColumn.needsReloadOnResize)
                    this.reloadVisibleColumnCells(visibleColumn);
            }
        }
    }

    hideColumn(column)
    {
        console.assert(this._columnSpecs.get(column.identifier) === column, "Column not in this table.");
        console.assert(!column.locked, "Locked columns should always be shown.");
        if (column.locked)
            return;

        console.assert(column.hideable, "Column is not hideable so should always be shown.");
        if (!column.hideable)
            return;

        if (column.hidden)
            return;

        column.hidden = true;

        this._hiddenColumns.push(column);

        let columnIndex = this._visibleColumns.indexOf(column);
        this._visibleColumns.splice(columnIndex, 1);

        // Save user preference for this column to be hidden.
        let savedColumnVisibility = this._columnVisibilitySetting.value;
        if (savedColumnVisibility[column.identifier] !== false) {
            let copy = Object.shallowCopy(savedColumnVisibility);
            if (column.defaultHidden)
                delete copy[column.identifier];
            else
                copy[column.identifier] = false;
            this._columnVisibilitySetting.value = copy;
        }

        this._headerElement.removeChild(this._headerElement.children[columnIndex]);
        this._fillerRow.removeChild(this._fillerRow.children[columnIndex]);

        if (column.headerView)
            this.removeSubview(column.headerView);

        // We haven't yet done any layout, nothing to do.
        if (!this._columnWidths)
            return;

        for (let row of this._listElement.children) {
            if (row !== this._fillerRow)
                row.removeChild(row.children[columnIndex]);
        }

        // Re-layout all columns to make space.
        this._widthGeneration++;
        this._columnWidths = null;
        this._resizeColumnsAndFiller();

        // Now populate columns that may be sensitive to resizes.
        for (let visibleColumn of this._visibleColumns) {
            if (visibleColumn.needsReloadOnResize)
                this.reloadVisibleColumnCells(visibleColumn);
        }
    }

    restoreScrollPosition()
    {
        if (this._cachedScrollTop && !this._scrollContainerElement.scrollTop)
            this._scrollContainerElement.scrollTop = this._cachedScrollTop;
    }

    // Protected

    initialLayout()
    {
        this.sortOrder = this._sortOrderSetting.value;

        let restoreSortColumnIdentifier = this._sortColumnIdentifierSetting.value;
        if (!this._columnSpecs.has(restoreSortColumnIdentifier))
            this._sortColumnIdentifierSetting.value = null;
        else
            this.sortColumnIdentifier = restoreSortColumnIdentifier;
    }

    layout()
    {
        this._updateVisibleRows();
        this._resizeColumnsAndFiller();
    }

    sizeDidChange()
    {
        super.sizeDidChange();

        this._previousCachedWidth = this._cachedWidth;
        this._cachedWidth = NaN;
        this._cachedHeight = NaN;
    }

    // SelectionController delegate

    selectionControllerSelectionDidChange(controller, deselectedItems, selectedItems)
    {
        for (let item of deselectedItems) {
            let rowIndex = this._indexForRepresentedObject(item);
            let row = this._cachedRows.get(rowIndex);
            if (row)
                row.classList.toggle("selected", false);
        }

        for (let item of selectedItems) {
            let rowIndex = this._indexForRepresentedObject(item);
            let row = this._cachedRows.get(rowIndex);
            if (row)
                row.classList.toggle("selected", true);
        }

        if (this._selectionController.lastSelectedItem) {
            let rowIndex = this._indexForRepresentedObject(this._selectionController.lastSelectedItem);
            this.revealRow(rowIndex);
        }

        if (this._delegate.tableSelectionDidChange)
            this._delegate.tableSelectionDidChange(this);
    }

    selectionControllerFirstSelectableItem(controller)
    {
        return this._representedObjectForIndex(0);
    }

    selectionControllerLastSelectableItem(controller)
    {
        return this._representedObjectForIndex(this.numberOfRows - 1);
    }

    selectionControllerPreviousSelectableItem(controller, item)
    {
        let index = this._indexForRepresentedObject(item);
        console.assert(index >= 0 && index < this.numberOfRows);

        return index > 0 ? this._representedObjectForIndex(index - 1) : null;
    }

    selectionControllerNextSelectableItem(controller, item)
    {
        let index = this._indexForRepresentedObject(item);
        console.assert(index >= 0 && index < this.numberOfRows);

        return index < this.numberOfRows - 1 ? this._representedObjectForIndex(index + 1) : null;
    }

    // Resizer delegate

    resizerDragStarted(resizer)
    {
        console.assert(!this._currentResizer, resizer, this._currentResizer);

        let resizerIndex = this._resizers.indexOf(resizer);

        this._currentResizer = resizer;
        this._resizeLeftColumns = this._visibleColumns.slice(0, resizerIndex + 1).reverse(); // Reversed to simplify iteration.
        this._resizeRightColumns = this._visibleColumns.slice(resizerIndex + 1);
        this._resizeOriginalColumnWidths = [].concat(this._columnWidths);
    }

    resizerDragging(resizer, positionDelta)
    {
        console.assert(resizer === this._currentResizer, resizer, this._currentResizer);
        if (resizer !== this._currentResizer)
            return;

        if (WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL)
            positionDelta = -positionDelta;

        // Completely recalculate columns from the original sizes based on the new mouse position.
        this._columnWidths = [].concat(this._resizeOriginalColumnWidths);

        if (!positionDelta) {
            this._applyColumnWidths();
            return;
        }

        let delta = Math.abs(positionDelta);
        let leftDirection = positionDelta > 0;
        let rightDirection = !leftDirection;

        let columnWidths = this._columnWidths;
        let visibleColumns = this._visibleColumns;

        function growableSize(column) {
            let width = columnWidths[visibleColumns.indexOf(column)];
            if (column.maxWidth)
                return column.maxWidth - width;
            return Infinity;
        }

        function shrinkableSize(column) {
            let width = columnWidths[visibleColumns.indexOf(column)];
            if (column.minWidth)
                return width - column.minWidth;
            return width;
        }

        function canGrow(column) {
            return growableSize(column) > 0;
        }

        function canShrink(column) {
            return shrinkableSize(column) > 0;
        }

        function columnToResize(columns, isShrinking) {
            // First find a flexible column we can resize.
            for (let column of columns) {
                if (!column.flexible)
                    continue;
                if (isShrinking ? canShrink(column) : canGrow(column))
                    return column;
            }

            // Failing that see if we can resize the immediately neighbor.
            let immediateColumn = columns[0];
            if ((isShrinking && canShrink(immediateColumn)) || (!isShrinking && canGrow(immediateColumn)))
                return immediateColumn;

            // Bail. There isn't anything obvious in the table that can resize.
            return null;
        }

        while (delta > 0) {
            let leftColumn = columnToResize(this._resizeLeftColumns, leftDirection);
            let rightColumn = columnToResize(this._resizeRightColumns, rightDirection);
            if (!leftColumn || !rightColumn) {
                // No more left or right column to grow or shrink.
                break;
            }

            let incrementalDelta = Math.min(delta,
                leftDirection ? shrinkableSize(leftColumn) : shrinkableSize(rightColumn),
                leftDirection ? growableSize(rightColumn) : growableSize(leftColumn));

            let leftIndex = this._visibleColumns.indexOf(leftColumn);
            let rightIndex = this._visibleColumns.indexOf(rightColumn);

            if (leftDirection) {
                this._columnWidths[leftIndex] -= incrementalDelta;
                this._columnWidths[rightIndex] += incrementalDelta;
            } else {
                this._columnWidths[leftIndex] += incrementalDelta;
                this._columnWidths[rightIndex] -= incrementalDelta;
            }

            delta -= incrementalDelta;
        }

        // We have new column widths.
        this._widthGeneration++;

        this._applyColumnWidths();
        this._positionHeaderViews();
    }

    resizerDragEnded(resizer)
    {
        console.assert(resizer === this._currentResizer, resizer, this._currentResizer);
        if (resizer !== this._currentResizer)
            return;

        this._currentResizer = null;
        this._resizeLeftColumns = null;
        this._resizeRightColumns = null;
        this._resizeOriginalColumnWidths = null;

        this._positionResizerElements();
        this._positionHeaderViews();
    }

    // Private

    _createHeaderCell(column)
    {
        let cell = document.createElement("span");
        cell.classList.add("cell", column.identifier);
        cell.textContent = column.name;

        if (column.align)
            cell.classList.add("align-" + column.align);
        if (column.sortable) {
            cell.classList.add("sortable");
            cell.addEventListener("click", this._handleHeaderCellClicked.bind(this, column));
        }

        cell.addEventListener("contextmenu", this._handleHeaderContextMenu.bind(this, column));

        return cell;
    }

    _createFillerCell(column)
    {
        let cell = document.createElement("span");
        cell.classList.add("cell", column.identifier);
        return cell;
    }

    _createCell(column, columnIndex)
    {
        let cell = document.createElement("span");
        cell.classList.add("cell", column.identifier);
        if (column.align)
            cell.classList.add("align-" + column.align);
        if (this._columnWidths)
            cell.style.width = this._columnWidths[columnIndex] + "px";
        return cell;
    }

    _getOrCreateRow(rowIndex)
    {
        let cachedRow = this._cachedRows.get(rowIndex);
        if (cachedRow)
            return cachedRow;

        let row = document.createElement("li");
        row.__index = rowIndex;
        row.__widthGeneration = 0;
        if (this.isRowSelected(rowIndex))
            row.classList.add("selected");

        this._cachedRows.set(rowIndex, row);
        return row;
    }

    _populatedCellForColumnAndRow(column, columnIndex, rowIndex)
    {
        console.assert(rowIndex !== undefined, "Tried to populate a row that did not know its index. Is this the filler row?");

        let cell = this._createCell(column, columnIndex);
        this._delegate.tablePopulateCell(this, cell, column, rowIndex);
        return cell;
    }

    _populateRow(row)
    {
        row.removeChildren();

        let rowIndex = row.__index;
        for (let i = 0; i < this._visibleColumns.length; ++i) {
            let column = this._visibleColumns[i];
            let cell = this._populatedCellForColumnAndRow(column, i, rowIndex);
            row.appendChild(cell);
        }
    }

    _resizeColumnsAndFiller()
    {
        if (isNaN(this._cachedWidth) || !this._cachedWidth)
            this._cachedWidth = Math.floor(this._scrollContainerElement.getBoundingClientRect().width);

        // Not visible yet.
        if (!this._cachedWidth)
            return;

        let availableWidth = this._cachedWidth;
        let availableHeight = this._cachedHeight;

        let contentHeight = this.numberOfRows * this._rowHeight;
        this._fillerHeight = Math.max(availableHeight - contentHeight, 0);

        // No change to layout metrics so no resizing is needed.
        if (this._columnWidths && this._cachedWidth === this._previousCachedWidth) {
            this._updateFillerRowWithNewHeight();
            this._applyColumnWidthsToColumnsIfNeeded();
            return;
        }

        this._previousCachedWidth = this._cachedWidth;

        let lockedWidth = 0;
        let lockedColumnCount = 0;
        let totalMinimumWidth = 0;

        for (let column of this._visibleColumns) {
            if (column.locked) {
                lockedWidth += column.width;
                lockedColumnCount++;
                totalMinimumWidth += column.width;
            } else if (column.minWidth)
                totalMinimumWidth += column.minWidth;
        }

        let flexibleWidth = availableWidth - lockedWidth;
        let flexibleColumnCount = this._visibleColumns.length - lockedColumnCount;

        // NOTE: We will often distribute pixels evenly across flexible columns in the table.
        // If `availableWidth < totalMinimumWidth` than the table is too small for the minimum
        // sizes of all the columns and we will start crunching the table (removing pixels from
        // all flexible columns). This would be the appropriate time to introduce horizontal
        // scrolling. For now we just remove pixels evenly.
        //
        // When distributing pixels, always start from the last column to accept remainder
        // pixels so we don't always add from one side / to one column.
        function distributeRemainingPixels(remainder, shrinking) {
            // No pixels to distribute.
            if (!remainder)
                return;

            let indexToStartAddingRemainderPixels = (this._lastColumnIndexToAcceptRemainderPixel + 1) % this._visibleColumns.length;

            // Handle tables that are too small or too large. If the size constraints
            // cause the columns to be too small or large. A second pass will do the
            // expanding or crunching ignoring constraints.
            let ignoreConstraints = false;

            while (remainder > 0) {
                let initialRemainder = remainder;

                for (let i = indexToStartAddingRemainderPixels; i < this._columnWidths.length; ++i) {
                    let column = this._visibleColumns[i];
                    if (column.locked)
                        continue;

                    if (shrinking) {
                        if (ignoreConstraints || (column.minWidth && this._columnWidths[i] > column.minWidth)) {
                            this._columnWidths[i]--;
                            remainder--;
                        }
                    } else {
                        if (ignoreConstraints || (column.maxWidth && this._columnWidths[i] < column.maxWidth)) {
                            this._columnWidths[i]++;
                            remainder--;
                        } else if (!column.maxWidth) {
                            this._columnWidths[i]++;
                            remainder--;
                        }
                    }

                    if (!remainder) {
                        this._lastColumnIndexToAcceptRemainderPixel = i;
                        break;
                    }
                }

                if (remainder === initialRemainder && !indexToStartAddingRemainderPixels) {
                    // We have remaining pixels. Start crunching if we need to.
                    if (ignoreConstraints)
                        break;
                    ignoreConstraints = true;
                }

                indexToStartAddingRemainderPixels = 0;
            }

            console.assert(!remainder, "Should not have undistributed pixels.");
        }

        // Two kinds of layouts. Autosize or Resize.
        if (!this._columnWidths) {
            // Autosize: Flex all the flexes evenly and trickle out any remaining pixels.
            this._columnWidths = [];
            this._lastColumnIndexToAcceptRemainderPixel = 0;

            let bestFitWidth = 0;
            let bestFitColumnCount = 0;

            function bestFit(callback) {
                while (true) {
                    let remainingFlexibleColumnCount = flexibleColumnCount - bestFitColumnCount;
                    if (!remainingFlexibleColumnCount)
                        return;

                    // Fair size to give each flexible column.
                    let remainingFlexibleWidth = flexibleWidth - bestFitWidth;
                    let flexWidth = Math.floor(remainingFlexibleWidth / remainingFlexibleColumnCount);

                    let didPerformBestFit = false;
                    for (let i = 0; i < this._visibleColumns.length; ++i) {
                        // Already best fit this column.
                        if (this._columnWidths[i])
                            continue;

                        let column = this._visibleColumns[i];
                        console.assert(column.flexible, "Non-flexible columns should have been sized earlier", column);

                        // Attempt best fit.
                        let bestWidth = callback(column, flexWidth);
                        if (bestWidth === -1)
                            continue;

                        this._columnWidths[i] = bestWidth;
                        bestFitWidth += bestWidth;
                        bestFitColumnCount++;
                        didPerformBestFit = true;
                    }
                    if (!didPerformBestFit)
                        return;

                    // Repeat with a new flex size now that we have fewer flexible columns.
                }
            }

            // Fit the locked columns.
            for (let i = 0; i < this._visibleColumns.length; ++i) {
                let column = this._visibleColumns[i];
                if (column.locked)
                    this._columnWidths[i] = column.width;
            }

            // Best fit with the preferred initial width for flexible columns.
            bestFit.call(this, (column, width) => {
                if (!column.preferredInitialWidth || width <= column.preferredInitialWidth)
                    return -1;
                return column.preferredInitialWidth;
            });

            // Best fit max size flexible columns. May make more pixels available for other columns.
            bestFit.call(this, (column, width) => {
                if (!column.maxWidth || width <= column.maxWidth)
                    return -1;
                return column.maxWidth;
            });

            // Best fit min size flexible columns. May make less pixels available for other columns.
            bestFit.call(this, (column, width) => {
                if (!column.minWidth || width >= column.minWidth)
                    return -1;
                return column.minWidth;
            });

            // Best fit the remaining flexible columns with the fair remaining size.
            bestFit.call(this, (column, width) => width);

            // Distribute any remaining pixels evenly.
            let remainder = availableWidth - (lockedWidth + bestFitWidth);
            let shrinking = remainder < 0;
            distributeRemainingPixels.call(this, Math.abs(remainder), shrinking);
        } else {
            // Resize: Distribute pixels evenly across flex columns.
            console.assert(this._columnWidths.length === this._visibleColumns.length, "Number of columns should not change in a resize.");

            let originalTotalColumnWidth = 0;
            for (let width of this._columnWidths)
                originalTotalColumnWidth += width;

            let remainder = Math.abs(availableWidth - originalTotalColumnWidth);
            let shrinking = availableWidth < originalTotalColumnWidth;
            distributeRemainingPixels.call(this, remainder, shrinking);
        }

        // We have new column widths.
        this._widthGeneration++;

        // Apply widths.

        this._updateFillerRowWithNewHeight();
        this._applyColumnWidths();
        this._positionResizerElements();
        this._positionHeaderViews();
    }

    _updateVisibleRows()
    {
        let rowHeight = this._rowHeight;
        let updateOffsetThreshold = rowHeight * 10;
        let overflowPadding = updateOffsetThreshold * 3;

        if (isNaN(this._cachedScrollTop))
            this._cachedScrollTop = this._scrollContainerElement.scrollTop;

        if (isNaN(this._cachedHeight) || !this._cachedHeight)
            this._cachedHeight = Math.floor(this._scrollContainerElement.getBoundingClientRect().height);

        let scrollTop = this._cachedScrollTop;
        let scrollableOffsetHeight = this._cachedHeight;

        let visibleRowCount = Math.ceil((scrollableOffsetHeight + (overflowPadding * 2)) / rowHeight);
        let currentTopMargin = this._topSpacerHeight;
        let currentBottomMargin = this._bottomSpacerHeight;
        let currentTableBottom = currentTopMargin + (visibleRowCount * rowHeight);

        let belowTopThreshold = !currentTopMargin || scrollTop > currentTopMargin + updateOffsetThreshold;
        let aboveBottomThreshold = !currentBottomMargin || scrollTop + scrollableOffsetHeight < currentTableBottom - updateOffsetThreshold;

        if (belowTopThreshold && aboveBottomThreshold && !isNaN(this._previousRevealedRowCount))
            return;

        let numberOfRows = this.numberOfRows;
        this._previousRevealedRowCount = numberOfRows;

        // Scroll back up if the number of rows was reduced such that the existing
        // scroll top value is larger than it could otherwise have been. We only
        // need to do this adjustment if there are more rows than would fit on screen,
        // because when the filler row activates it will reset our scroll.
        if (scrollTop) {
            let rowsThatCanFitOnScreen = Math.ceil(scrollableOffsetHeight / rowHeight);
            if (numberOfRows >= rowsThatCanFitOnScreen) {
                let maximumScrollTop = Math.max(0, (numberOfRows * rowHeight) - scrollableOffsetHeight);
                if (scrollTop > maximumScrollTop) {
                    this._scrollContainerElement.scrollTop = maximumScrollTop;
                    this._cachedScrollTop = maximumScrollTop;
                }
            }
        }

        let topHiddenRowCount = Math.max(0, Math.floor((scrollTop - overflowPadding) / rowHeight));
        let bottomHiddenRowCount = Math.max(0, this._previousRevealedRowCount - topHiddenRowCount - visibleRowCount);

        let marginTop = topHiddenRowCount * rowHeight;
        let marginBottom = bottomHiddenRowCount * rowHeight;

        if (this._topSpacerHeight !== marginTop) {
            this._topSpacerHeight = marginTop;
            this._topSpacerElement.style.height = marginTop + "px";
        }

        if (this._bottomDataTableMarginElement !== marginBottom) {
            this._bottomSpacerHeight = marginBottom;
            this._bottomSpacerElement.style.height = marginBottom + "px";
        }

        this._visibleRowIndexStart = topHiddenRowCount;
        this._visibleRowIndexEnd = this._visibleRowIndexStart + visibleRowCount;

        // Completely remove all rows and add new ones.
        this._listElement.removeChildren();
        this._listElement.classList.toggle("odd-first-zebra-stripe", !!(topHiddenRowCount % 2));

        for (let i = this._visibleRowIndexStart; i < this._visibleRowIndexEnd && i < numberOfRows; ++i) {
            let row = this._getOrCreateRow(i);
            this._listElement.appendChild(row);
        }

        this._listElement.appendChild(this._fillerRow);
    }

    _updateFillerRowWithNewHeight()
    {
        if (!this._fillerHeight) {
            this._scrollContainerElement.classList.remove("not-scrollable");
            this._fillerRow.remove();
            return;
        }

        this._scrollContainerElement.classList.add("not-scrollable");

        // In the event that we just made the table not scrollable then the number
        // of rows can fit on screen. Reset the scroll top.
        if (this._cachedScrollTop) {
            this._scrollContainerElement.scrollTop = 0;
            this._cachedScrollTop = 0;
        }

        // Extend past edge some reasonable amount. At least 200px.
        const paddingPastTheEdge = 200;
        this._fillerHeight += paddingPastTheEdge;

        for (let cell of this._fillerRow.children)
            cell.style.height = this._fillerHeight + "px";

        if (!this._fillerRow.parentElement)
            this._listElement.appendChild(this._fillerRow);
    }

    _applyColumnWidths()
    {
        for (let i = 0; i < this._headerElement.children.length; ++i)
            this._headerElement.children[i].style.width = this._columnWidths[i] + "px";

        for (let row of this._listElement.children) {
            for (let i = 0; i < row.children.length; ++i)
                row.children[i].style.width = this._columnWidths[i] + "px";
            row.__widthGeneration = this._widthGeneration;
        }

        // Update Table Columns after cells since events may respond to this.
        for (let i = 0; i < this._visibleColumns.length; ++i)
            this._visibleColumns[i].width = this._columnWidths[i];

        // Create missing cells after we've sized.
        for (let row of this._listElement.children) {
            if (row !== this._fillerRow) {
                if (row.children.length !== this._visibleColumns.length)
                    this._populateRow(row);
            }
        }
    }

    _applyColumnWidthsToColumnsIfNeeded()
    {
        // Apply and create missing cells only if row needs a width update.
        for (let row of this._listElement.children) {
            if (row.__widthGeneration !== this._widthGeneration) {
                for (let i = 0; i < row.children.length; ++i)
                    row.children[i].style.width = this._columnWidths[i] + "px";
                if (row !== this._fillerRow) {
                    if (row.children.length !== this._visibleColumns.length)
                        this._populateRow(row);
                }
                row.__widthGeneration = this._widthGeneration;
            }
        }
    }

    _positionResizerElements()
    {
        console.assert(this._visibleColumns.length === this._columnWidths.length);

        // Create the appropriate number of resizers.
        let resizersNeededCount = this._visibleColumns.length - 1;
        if (this._resizers.length !== resizersNeededCount) {
            if (this._resizers.length < resizersNeededCount) {
                do {
                    let resizer = new WI.Resizer(WI.Resizer.RuleOrientation.Vertical, this);
                    this._resizers.push(resizer);
                    this._resizersElement.appendChild(resizer.element);
                } while (this._resizers.length < resizersNeededCount);
            } else {
                do {
                    let resizer = this._resizers.pop();
                    this._resizersElement.removeChild(resizer.element);
                } while (this._resizers.length > resizersNeededCount);
            }
        }

        // Position them.
        const columnResizerAdjustment = 3;
        let positionAttribute = WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL ? "right" : "left";
        let totalWidth = 0;
        for (let i = 0; i < resizersNeededCount; ++i) {
            totalWidth += this._columnWidths[i];
            this._resizers[i].element.style[positionAttribute] = (totalWidth - columnResizerAdjustment) + "px";
        }
    }

    _positionHeaderViews()
    {
        if (!this.subviews.length)
            return;

        let offset = 0;
        let updates = [];
        for (let i = 0; i < this._visibleColumns.length; ++i) {
            let column = this._visibleColumns[i];
            let width = this._columnWidths[i];
            if (column.headerView)
                updates.push({headerView: column.headerView, offset, width});
            offset += width;
        }

        let styleProperty = WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL ? "right" : "left";
        for (let {headerView, offset, width} of updates) {
            headerView.element.style.setProperty(styleProperty, offset + "px");
            headerView.element.style.width = width + "px";
            headerView.updateLayout(WI.View.LayoutReason.Resize);
        }
    }

    _isRowVisible(rowIndex)
    {
        if (!this._previousRevealedRowCount)
            return false;

        return rowIndex >= this._visibleRowIndexStart && rowIndex <= this._visibleRowIndexEnd;
    }

    _indexToInsertColumn(column)
    {
        let currentVisibleColumnIndex = 0;

        for (let columnIdentifier of this._columnOrder) {
            if (columnIdentifier === column.identifier)
                return currentVisibleColumnIndex;
            if (columnIdentifier === this._visibleColumns[currentVisibleColumnIndex].identifier) {
                currentVisibleColumnIndex++;
                if (currentVisibleColumnIndex >= this._visibleColumns.length)
                    break;
            }
        }

        return currentVisibleColumnIndex;
    }

    _handleScroll(event)
    {
        if (event.type === "mousewheel" && !event.wheelDeltaY)
            return;

        this._cachedScrollTop = NaN;
        this.needsLayout();
    }

    _handleKeyDown(event)
    {
        this._selectionController.handleKeyDown(event);
    }

    _handleMouseDown(event)
    {
        let cell = event.target.closest(".cell");
        if (!cell)
            return;

        let row = cell.parentElement;
        if (row === this._fillerRow)
            return;

        let rowIndex = row.__index;

        // Before checking if multiple selection is allowed, check if clicking the
        // row would cause it to be selected, and whether it is allowed by the delegate.
        if (!this.isRowSelected(rowIndex) && this._delegate.tableShouldSelectRow) {
            let columnIndex = Array.from(row.children).indexOf(cell);
            let column = this._visibleColumns[columnIndex];
            if (!this._delegate.tableShouldSelectRow(this, cell, column, rowIndex))
                return;
        }

        this._selectionController.handleItemMouseDown(this._representedObjectForIndex(rowIndex), event);
    }

    _handleContextMenu(event)
    {
        let cell = event.target.closest(".cell");
        if (!cell)
            return;

        let row = cell.parentElement;
        if (row === this._fillerRow)
            return;

        let columnIndex = Array.from(row.children).indexOf(cell);
        let column = this._visibleColumns[columnIndex];
        let rowIndex = row.__index;

        this._delegate.tableCellContextMenuClicked(this, cell, column, rowIndex, event);
    }

    _handleHeaderCellClicked(column, event)
    {
        let sortOrder = this._sortOrder;
        if (sortOrder === WI.Table.SortOrder.Indeterminate)
            sortOrder = WI.Table.SortOrder.Descending;
        else if (this._sortColumnIdentifier === column.identifier)
            sortOrder = sortOrder === WI.Table.SortOrder.Ascending ? WI.Table.SortOrder.Descending : WI.Table.SortOrder.Ascending;

        this.sortColumnIdentifier = column.identifier;
        this.sortOrder = sortOrder;
    }

    _handleHeaderContextMenu(column, event)
    {
        let contextMenu = WI.ContextMenu.createFromEvent(event);

        if (column.sortable) {
            if (this.sortColumnIdentifier !== column.identifier || this.sortOrder !== WI.Table.SortOrder.Ascending) {
                contextMenu.appendItem(WI.UIString("Sort Ascending"), () => {
                    this.sortColumnIdentifier = column.identifier;
                    this.sortOrder = WI.Table.SortOrder.Ascending;
                });
            }

            if (this.sortColumnIdentifier !== column.identifier || this.sortOrder !== WI.Table.SortOrder.Descending) {
                contextMenu.appendItem(WI.UIString("Sort Descending"), () => {
                    this.sortColumnIdentifier = column.identifier;
                    this.sortOrder = WI.Table.SortOrder.Descending;
                });
            }
        }

        contextMenu.appendSeparator();

        let didAppendHeaderItem = false;

        for (let [columnIdentifier, column] of this._columnSpecs) {
            if (column.locked)
                continue;
            if (!column.hideable)
                continue;

            // Add a header item before the list of toggleable columns.
            if (!didAppendHeaderItem) {
                const disabled = true;
                contextMenu.appendItem(WI.UIString("Displayed Columns"), () => {}, disabled);
                didAppendHeaderItem = true;
            }

            let checked = !column.hidden;
            contextMenu.appendCheckboxItem(column.name, () => {
                if (column.hidden)
                    this.showColumn(column);
                else
                    this.hideColumn(column);
            }, checked);
        }
    }

    _removeRows(representedObjects)
    {
        let removed = 0;

        let adjustRowAtIndex = (index) => {
            let row = this._cachedRows.get(index);
            if (row) {
                this._cachedRows.delete(index);
                row.__index -= removed;
                this._cachedRows.set(row.__index, row);
            }
        };

        let rowIndexes = [];
        for (let object of representedObjects)
            rowIndexes.push(this._indexForRepresentedObject(object));

        rowIndexes.sort((a, b) => a - b);

        let lastIndex = rowIndexes.lastValue;
        for (let index = rowIndexes[0]; index <= lastIndex; ++index) {
            if (rowIndexes.binaryIndexOf(index) >= 0) {
                let row = this._cachedRows.get(index);
                if (row) {
                    this._cachedRows.delete(index);
                    row.remove();
                }
                removed++;
                continue;
            }

            if (removed)
                adjustRowAtIndex(index);
        }

        if (!removed)
            return;

        for (let index = lastIndex + 1; index < this.numberOfRows; ++index)
            adjustRowAtIndex(index);


        this._selectionController.didRemoveItems(representedObjects);

        if (this._delegate.tableDidRemoveRows)
            this._delegate.tableDidRemoveRows(this, rowIndexes);
    }

    _indexForRepresentedObject(object)
    {
        return this.dataSource.tableIndexForRepresentedObject(this, object);
    }

    _representedObjectForIndex(index)
    {
        return this.dataSource.tableRepresentedObjectForIndex(this, index);
    }
};

WI.Table.SortOrder = {
    Indeterminate: "table-sort-order-indeterminate",
    Ascending: "table-sort-order-ascending",
    Descending: "table-sort-order-descending",
};
