/*
 * 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;

        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._cachedScrollTop = NaN;
                this.needsLayout();
            }
        } else {
            let rowPosition = rowIndex * this._rowHeight;
            let scrollableOffsetHeight = this._calculateOffsetHeight();
            let scrollTop = this._calculateScrollTop();
            let newScrollTop = NaN;
            if (rowPosition + this._rowHeight < scrollTop)
                newScrollTop = rowPosition;
            else if (rowPosition > scrollTop + scrollableOffsetHeight)
                newScrollTop = scrollTop + scrollableOffsetHeight - this._rowHeight;

            if (!isNaN(newScrollTop)) {
                this._scrollContainerElement.scrollTop = newScrollTop;
                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 = this._scrollContainerElement.realOffsetWidth;

        // 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;

        let scrollTop = this._calculateScrollTop();
        let scrollableOffsetHeight = this._calculateOffsetHeight();

        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();

        // If there are an odd number of rows hidden, the first visible row must be an even row.
        this._listElement.classList.toggle("even-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);
    }

    _calculateOffsetHeight()
    {
        if (isNaN(this._cachedHeight))
            this._cachedHeight = this._scrollContainerElement.realOffsetHeight;
        return this._cachedHeight;
    }

    _calculateScrollTop()
    {
        if (isNaN(this._cachedScrollTop))
            this._cachedScrollTop = this._scrollContainerElement.scrollTop;
        return this._cachedScrollTop;
    }
};

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