/*
 * Copyright (C) 2008 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. ``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
 * 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.
 */

/**
 * @unrestricted
 * @template NODE_TYPE
 */
export default class DataGridImpl extends Common.Object {
  /**
   * @param {!Array.<!DataGrid.DataGrid.ColumnDescriptor>} columnsArray
   * @param {function(!NODE_TYPE, string, string, string)=} editCallback
   * @param {function(!NODE_TYPE)=} deleteCallback
   * @param {function()=} refreshCallback
   */
  constructor(columnsArray, editCallback, deleteCallback, refreshCallback) {
    super();
    this.element = createElementWithClass('div', 'data-grid');
    UI.appendStyle(this.element, 'data_grid/dataGrid.css');
    this.element.tabIndex = 0;
    this.element.addEventListener('keydown', this._keyDown.bind(this), false);
    this.element.addEventListener('contextmenu', this._contextMenu.bind(this), true);

    this._editCallback = editCallback;
    this._deleteCallback = deleteCallback;
    this._refreshCallback = refreshCallback;

    const headerContainer = this.element.createChild('div', 'header-container');
    /** @type {!Element} */
    this._headerTable = headerContainer.createChild('table', 'header');
    /** @type {!Object.<string, !Element>} */
    this._headerTableHeaders = {};
    /** @type {!Element} */
    this._scrollContainer = this.element.createChild('div', 'data-container');
    /** @type {!Element} */
    this._dataTable = this._scrollContainer.createChild('table', 'data');

    // FIXME: Add a createCallback which is different from editCallback and has different
    // behavior when creating a new node.
    if (editCallback) {
      this._dataTable.addEventListener('dblclick', this._ondblclick.bind(this), false);
    }
    this._dataTable.addEventListener('mousedown', this._mouseDownInDataTable.bind(this));
    this._dataTable.addEventListener('click', this._clickInDataTable.bind(this), true);

    /** @type {boolean} */
    this._inline = false;

    /** @type {!Array.<!DataGrid.DataGrid.ColumnDescriptor>} */
    this._columnsArray = [];
    /** @type {!Object.<string, !DataGrid.DataGrid.ColumnDescriptor>} */
    this._columns = {};
    /** @type {!Array.<!DataGrid.DataGrid.ColumnDescriptor>} */
    this._visibleColumnsArray = columnsArray;

    columnsArray.forEach(column => this._innerAddColumn(column));

    /** @type {?string} */
    this._cellClass = null;

    /** @type {!Element} */
    this._headerTableColumnGroup = this._headerTable.createChild('colgroup');
    /** @type {!Element} */
    this._headerTableBody = this._headerTable.createChild('tbody');
    /** @type {!Element} */
    this._headerRow = this._headerTableBody.createChild('tr');

    /** @type {!Element} */
    this._dataTableColumnGroup = this._dataTable.createChild('colgroup');
    /**
     * @protected
     * @type {!Element}
     */
    this.dataTableBody = this._dataTable.createChild('tbody');
    /** @type {!Element} */
    this._topFillerRow = this.dataTableBody.createChild('tr', 'data-grid-filler-row revealed');
    /** @type {!Element} */
    this._bottomFillerRow = this.dataTableBody.createChild('tr', 'data-grid-filler-row revealed');

    this.setVerticalPadding(0, 0);
    this._refreshHeader();

    /** @type {boolean} */
    this._editing = false;
    /** @type {?NODE_TYPE} */
    this.selectedNode = null;
    /** @type {boolean} */
    this.expandNodesWhenArrowing = false;
    this.setRootNode(/** @type {!NODE_TYPE} */ (new DataGridNode()));

    this.setHasSelection(false);

    /** @type {number} */
    this.indentWidth = 15;
    /** @type {!Array.<!Element|{__index: number, __position: number}>} */
    this._resizers = [];
    /** @type {boolean} */
    this._columnWidthsInitialized = false;
    /** @type {number} */
    this._cornerWidth = CornerWidth;
    /** @type {!ResizeMethod} */
    this._resizeMethod = ResizeMethod.Nearest;

    /** @type {?function(!UI.ContextSubMenu)} */
    this._headerContextMenuCallback = null;
    /** @type {?function(!UI.ContextMenu, !NODE_TYPE)} */
    this._rowContextMenuCallback = null;
  }

  /**
   * @return {!NODE_TYPE}
   */
  _firstSelectableNode() {
    let firstSelectableNode = this._rootNode;
    while (firstSelectableNode && !firstSelectableNode.selectable) {
      firstSelectableNode = firstSelectableNode.traverseNextNode(true);
    }
    return firstSelectableNode;
  }

  /**
   * @return {!NODE_TYPE}
   */
  _lastSelectableNode() {
    let lastSelectableNode = this._rootNode;
    let iterator = this._rootNode;
    while (iterator) {
      if (iterator.selectable) {
        lastSelectableNode = iterator;
      }
      iterator = iterator.traverseNextNode(true);
    }
    return lastSelectableNode;
  }

  /**
   * @param {!Element} element
   * @param {string} newText
   * @param {boolean} longText
   */
  static setElementText(element, newText, longText) {
    if (longText && newText.length > 1000) {
      element.textContent = newText.trimEndWithMaxLength(1000);
      element.title = newText;
      element[DataGrid._longTextSymbol] = newText;
    } else {
      element.textContent = newText;
      element.title = '';
      element[DataGrid._longTextSymbol] = undefined;
    }
  }

  /**
   * @param {boolean} isStriped
   */
  setStriped(isStriped) {
    this.element.classList.toggle('striped-data-grid', isStriped);
  }

  /**
   * @param {boolean} focusable
   */
  setFocusable(focusable) {
    this.element.tabIndex = focusable ? 0 : -1;
  }

  /**
   * @param {boolean} hasSelected
   */
  setHasSelection(hasSelected) {
    // 'no-selection' class causes datagrid to have a focus-indicator border
    this.element.classList.toggle('no-selection', !hasSelected);
  }

  /**
   * @return {!Element}
   */
  headerTableBody() {
    return this._headerTableBody;
  }

  /**
   * @param {!DataGrid.DataGrid.ColumnDescriptor} column
   * @param {number=} position
   */
  _innerAddColumn(column, position) {
    const columnId = column.id;
    if (columnId in this._columns) {
      this._innerRemoveColumn(columnId);
    }

    if (position === undefined) {
      position = this._columnsArray.length;
    }

    this._columnsArray.splice(position, 0, column);
    this._columns[columnId] = column;
    if (column.disclosure) {
      this.disclosureColumnId = columnId;
    }

    const cell = createElement('th');
    cell.className = columnId + '-column';
    cell[DataGrid._columnIdSymbol] = columnId;
    this._headerTableHeaders[columnId] = cell;

    const div = createElement('div');
    if (column.titleDOMFragment) {
      div.appendChild(column.titleDOMFragment);
    } else {
      div.textContent = column.title;
    }
    cell.appendChild(div);

    if (column.sort) {
      cell.classList.add(column.sort);
      this._sortColumnCell = cell;
    }

    if (column.sortable) {
      cell.addEventListener('click', this._clickInHeaderCell.bind(this), false);
      cell.classList.add('sortable');
      const icon = UI.Icon.create('', 'sort-order-icon');
      cell.createChild('div', 'sort-order-icon-container').appendChild(icon);
      cell[DataGrid._sortIconSymbol] = icon;
    }
  }

  /**
   * @param {!DataGrid.DataGrid.ColumnDescriptor} column
   * @param {number=} position
   */
  addColumn(column, position) {
    this._innerAddColumn(column, position);
  }

  /**
   * @param {string} columnId
   */
  _innerRemoveColumn(columnId) {
    const column = this._columns[columnId];
    if (!column) {
      return;
    }
    delete this._columns[columnId];
    const index = this._columnsArray.findIndex(columnConfig => columnConfig.id === columnId);
    this._columnsArray.splice(index, 1);
    const cell = this._headerTableHeaders[columnId];
    if (cell.parentElement) {
      cell.parentElement.removeChild(cell);
    }
    delete this._headerTableHeaders[columnId];
  }

  /**
   * @param {string} columnId
   */
  removeColumn(columnId) {
    this._innerRemoveColumn(columnId);
  }

  /**
   * @param {string} cellClass
   */
  setCellClass(cellClass) {
    this._cellClass = cellClass;
  }

  _refreshHeader() {
    this._headerTableColumnGroup.removeChildren();
    this._dataTableColumnGroup.removeChildren();
    this._headerRow.removeChildren();
    this._topFillerRow.removeChildren();
    this._bottomFillerRow.removeChildren();

    for (let i = 0; i < this._visibleColumnsArray.length; ++i) {
      const column = this._visibleColumnsArray[i];
      const columnId = column.id;
      const headerColumn = this._headerTableColumnGroup.createChild('col');
      const dataColumn = this._dataTableColumnGroup.createChild('col');
      if (column.width) {
        headerColumn.style.width = column.width;
        dataColumn.style.width = column.width;
      }
      this._headerRow.appendChild(this._headerTableHeaders[columnId]);
      const topFillerRowCell = this._topFillerRow.createChild('th', 'top-filler-td');
      topFillerRowCell.textContent = column.title;
      topFillerRowCell.scope = 'col';
      this._bottomFillerRow.createChild('td', 'bottom-filler-td')[DataGrid._columnIdSymbol] = columnId;
    }

    this._headerRow.createChild('th', 'corner');
    const topFillerRowCornerCell = this._topFillerRow.createChild('th', 'corner');
    topFillerRowCornerCell.classList.add('top-filler-td');
    topFillerRowCornerCell.scope = 'col';
    this._bottomFillerRow.createChild('td', 'corner').classList.add('bottom-filler-td');
    this._headerTableColumnGroup.createChild('col', 'corner');
    this._dataTableColumnGroup.createChild('col', 'corner');
  }

  /**
   * @param {number} top
   * @param {number} bottom
   * @protected
   */
  setVerticalPadding(top, bottom) {
    const topPx = top + 'px';
    const bottomPx = (top || bottom) ? bottom + 'px' : 'auto';
    if (this._topFillerRow.style.height === topPx && this._bottomFillerRow.style.height === bottomPx) {
      return;
    }
    this._topFillerRow.style.height = topPx;
    this._bottomFillerRow.style.height = bottomPx;
    this.dispatchEventToListeners(Events.PaddingChanged);
  }

  /**
   * @param {!NODE_TYPE} rootNode
   * @protected
   */
  setRootNode(rootNode) {
    if (this._rootNode) {
      this._rootNode.removeChildren();
      this._rootNode.dataGrid = null;
      this._rootNode._isRoot = false;
    }
    /** @type {!NODE_TYPE} */
    this._rootNode = rootNode;
    rootNode._isRoot = true;
    rootNode.setHasChildren(false);
    rootNode._expanded = true;
    rootNode._revealed = true;
    rootNode.selectable = false;
    rootNode.dataGrid = this;
  }

  /**
   * @return {!NODE_TYPE}
   */
  rootNode() {
    return this._rootNode;
  }

  /**
   * @param {!Event} event
   */
  _ondblclick(event) {
    if (this._editing || this._editingNode) {
      return;
    }

    const columnId = this.columnIdFromNode(/** @type {!Node} */ (event.target));
    if (!columnId || !this._columns[columnId].editable) {
      return;
    }
    this._startEditing(/** @type {!Node} */ (event.target));
  }

  /**
   * @param {!DataGridNode} node
   * @param {number} cellIndex
   */
  _startEditingColumnOfDataGridNode(node, cellIndex) {
    this._editing = true;
    /** @type {?DataGridNode} */
    this._editingNode = node;
    this._editingNode.select();

    const element = this._editingNode._element.children[cellIndex];
    UI.InplaceEditor.startEditing(element, this._startEditingConfig(element));
    element.getComponentSelection().selectAllChildren(element);
  }

  /**
   * @param {!DataGridNode} node
   * @param {string} columnIdentifier
   */
  startEditingNextEditableColumnOfDataGridNode(node, columnIdentifier) {
    const column = this._columns[columnIdentifier];
    const cellIndex = this._visibleColumnsArray.indexOf(column);
    const nextEditableColumn = this._nextEditableColumn(cellIndex);
    if (nextEditableColumn !== -1) {
      this._startEditingColumnOfDataGridNode(node, nextEditableColumn);
    }
  }

  /**
   * @param {!Node} target
   */
  _startEditing(target) {
    const element = /** @type {?Element} */ (target.enclosingNodeOrSelfWithNodeName('td'));
    if (!element) {
      return;
    }

    this._editingNode = this.dataGridNodeFromNode(target);
    if (!this._editingNode) {
      if (!this.creationNode) {
        return;
      }
      this._editingNode = this.creationNode;
    }

    // Force editing the 1st column when editing the creation node
    if (this._editingNode.isCreationNode) {
      this._startEditingColumnOfDataGridNode(this._editingNode, this._nextEditableColumn(-1));
      return;
    }

    this._editing = true;
    if (element[DataGrid._longTextSymbol]) {
      element.textContent = element[DataGrid._longTextSymbol];
    }
    UI.InplaceEditor.startEditing(element, this._startEditingConfig(element));

    element.getComponentSelection().selectAllChildren(element);
  }

  renderInline() {
    this.element.classList.add('inline');
    this._cornerWidth = 0;
    this._inline = true;
    this.updateWidths();
  }

  /**
   * @param {!Element} element
   * @return {!UI.InplaceEditor.Config}
   */
  _startEditingConfig(element) {
    return new UI.InplaceEditor.Config(this._editingCommitted.bind(this), this._editingCancelled.bind(this));
  }

  /**
   * @param {!Element} element
   * @param {string} newText
   * @param {string} oldText
   * @param {string|undefined} context
   * @param {string} moveDirection
   */
  _editingCommitted(element, newText, oldText, context, moveDirection) {
    const columnId = this.columnIdFromNode(element);
    if (!columnId) {
      this._editingCancelled(element);
      return;
    }
    const column = this._columns[columnId];
    const cellIndex = this._visibleColumnsArray.indexOf(column);
    const textBeforeEditing = /** @type {string} */ (this._editingNode.data[columnId] || '');
    const currentEditingNode = this._editingNode;

    /**
     * @param {boolean} wasChange
     * @this {DataGrid.DataGrid}
     */
    function moveToNextIfNeeded(wasChange) {
      if (!moveDirection) {
        return;
      }

      if (moveDirection === 'forward') {
        const firstEditableColumn = this._nextEditableColumn(-1);
        if (currentEditingNode.isCreationNode && cellIndex === firstEditableColumn && !wasChange) {
          return;
        }

        const nextEditableColumn = this._nextEditableColumn(cellIndex);
        if (nextEditableColumn !== -1) {
          this._startEditingColumnOfDataGridNode(currentEditingNode, nextEditableColumn);
          return;
        }

        const nextDataGridNode = currentEditingNode.traverseNextNode(true, null, true);
        if (nextDataGridNode) {
          this._startEditingColumnOfDataGridNode(nextDataGridNode, firstEditableColumn);
          return;
        }
        if (currentEditingNode.isCreationNode && wasChange) {
          this.addCreationNode(false);
          this._startEditingColumnOfDataGridNode(this.creationNode, firstEditableColumn);
          return;
        }
        return;
      }

      if (moveDirection === 'backward') {
        const prevEditableColumn = this._nextEditableColumn(cellIndex, true);
        if (prevEditableColumn !== -1) {
          this._startEditingColumnOfDataGridNode(currentEditingNode, prevEditableColumn);
          return;
        }

        const lastEditableColumn = this._nextEditableColumn(this._visibleColumnsArray.length, true);
        const nextDataGridNode = currentEditingNode.traversePreviousNode(true, true);
        if (nextDataGridNode) {
          this._startEditingColumnOfDataGridNode(nextDataGridNode, lastEditableColumn);
        }
        return;
      }
    }

    // Show trimmed text after editing.
    DataGrid.DataGrid.setElementText(element, newText, !!column.longText);

    if (textBeforeEditing === newText) {
      this._editingCancelled(element);
      moveToNextIfNeeded.call(this, false);
      return;
    }

    // Update the text in the datagrid that we typed
    this._editingNode.data[columnId] = newText;

    // Make the callback - expects an editing node (table row), the column number that is being edited,
    // the text that used to be there, and the new text.
    this._editCallback(this._editingNode, columnId, textBeforeEditing, newText);

    if (this._editingNode.isCreationNode) {
      this.addCreationNode(false);
    }

    this._editingCancelled(element);
    moveToNextIfNeeded.call(this, true);
  }

  /**
   * @param {!Element} element
   */
  _editingCancelled(element) {
    this._editing = false;
    this._editingNode = null;
  }

  /**
   * @param {number} cellIndex
   * @param {boolean=} moveBackward
   * @return {number}
   */
  _nextEditableColumn(cellIndex, moveBackward) {
    const increment = moveBackward ? -1 : 1;
    const columns = this._visibleColumnsArray;
    for (let i = cellIndex + increment; (i >= 0) && (i < columns.length); i += increment) {
      if (columns[i].editable) {
        return i;
      }
    }
    return -1;
  }

  /**
   * @return {?string}
   */
  sortColumnId() {
    if (!this._sortColumnCell) {
      return null;
    }
    return this._sortColumnCell[DataGrid._columnIdSymbol];
  }

  /**
   * @return {?string}
   */
  sortOrder() {
    if (!this._sortColumnCell || this._sortColumnCell.classList.contains(Order.Ascending)) {
      return Order.Ascending;
    }
    if (this._sortColumnCell.classList.contains(Order.Descending)) {
      return Order.Descending;
    }
    return null;
  }

  /**
   * @return {boolean}
   */
  isSortOrderAscending() {
    return !this._sortColumnCell || this._sortColumnCell.classList.contains(Order.Ascending);
  }

  /**
   * @param {!Array.<number>} widths
   * @param {number} minPercent
   * @param {number=} maxPercent
   * @return {!Array.<number>}
   */
  _autoSizeWidths(widths, minPercent, maxPercent) {
    if (minPercent) {
      minPercent = Math.min(minPercent, Math.floor(100 / widths.length));
    }
    let totalWidth = 0;
    for (let i = 0; i < widths.length; ++i) {
      totalWidth += widths[i];
    }
    let totalPercentWidth = 0;
    for (let i = 0; i < widths.length; ++i) {
      let width = Math.round(100 * widths[i] / totalWidth);
      if (minPercent && width < minPercent) {
        width = minPercent;
      } else if (maxPercent && width > maxPercent) {
        width = maxPercent;
      }
      totalPercentWidth += width;
      widths[i] = width;
    }
    let recoupPercent = totalPercentWidth - 100;

    while (minPercent && recoupPercent > 0) {
      for (let i = 0; i < widths.length; ++i) {
        if (widths[i] > minPercent) {
          --widths[i];
          --recoupPercent;
          if (!recoupPercent) {
            break;
          }
        }
      }
    }

    while (maxPercent && recoupPercent < 0) {
      for (let i = 0; i < widths.length; ++i) {
        if (widths[i] < maxPercent) {
          ++widths[i];
          ++recoupPercent;
          if (!recoupPercent) {
            break;
          }
        }
      }
    }

    return widths;
  }

  /**
   * The range of |minPercent| and |maxPercent| is [0, 100].
   * @param {number} minPercent
   * @param {number=} maxPercent
   * @param {number=} maxDescentLevel
   */
  autoSizeColumns(minPercent, maxPercent, maxDescentLevel) {
    let widths = [];
    for (let i = 0; i < this._columnsArray.length; ++i) {
      widths.push((this._columnsArray[i].title || '').length);
    }

    maxDescentLevel = maxDescentLevel || 0;
    const children = this._enumerateChildren(this._rootNode, [], maxDescentLevel + 1);
    for (let i = 0; i < children.length; ++i) {
      const node = children[i];
      for (let j = 0; j < this._columnsArray.length; ++j) {
        const text = String(node.data[this._columnsArray[j].id]);
        if (text.length > widths[j]) {
          widths[j] = text.length;
        }
      }
    }

    widths = this._autoSizeWidths(widths, minPercent, maxPercent);

    for (let i = 0; i < this._columnsArray.length; ++i) {
      this._columnsArray[i].weight = widths[i];
    }
    this._columnWidthsInitialized = false;
    this.updateWidths();
  }

  /**
   * @param {!DataGridNode} rootNode
   * @param {!Array<!DataGridNode>} result
   * @param {number} maxLevel
   * @return {!Array<!NODE_TYPE>}
   */
  _enumerateChildren(rootNode, result, maxLevel) {
    if (!rootNode._isRoot) {
      result.push(rootNode);
    }
    if (!maxLevel) {
      return [];
    }
    for (let i = 0; i < rootNode.children.length; ++i) {
      this._enumerateChildren(rootNode.children[i], result, maxLevel - 1);
    }
    return result;
  }

  onResize() {
    this.updateWidths();
  }

  // Updates the widths of the table, including the positions of the column
  // resizers.
  //
  // IMPORTANT: This function MUST be called once after the element of the
  // DataGrid is attached to its parent element and every subsequent time the
  // width of the parent element is changed in order to make it possible to
  // resize the columns.
  //
  // If this function is not called after the DataGrid is attached to its
  // parent element, then the DataGrid's columns will not be resizable.
  updateWidths() {
    // Do not attempt to use offsetes if we're not attached to the document tree yet.
    if (!this._columnWidthsInitialized && this.element.offsetWidth) {
      // Give all the columns initial widths now so that during a resize,
      // when the two columns that get resized get a percent value for
      // their widths, all the other columns already have percent values
      // for their widths.

      // Use container size to avoid changes of table width caused by change of column widths.
      const tableWidth = this.element.offsetWidth - this._cornerWidth;
      const cells = this._headerTableBody.rows[0].cells;
      const numColumns = cells.length - 1;  // Do not process corner column.
      for (let i = 0; i < numColumns; i++) {
        const column = this._visibleColumnsArray[i];
        if (!column.weight) {
          column.weight = 100 * cells[i].offsetWidth / tableWidth || 10;
        }
      }
      this._columnWidthsInitialized = true;
    }
    this._applyColumnWeights();
  }

  /**
   * @param {string} columnId
   * @returns {number}
   */
  indexOfVisibleColumn(columnId) {
    return this._visibleColumnsArray.findIndex(column => column.id === columnId);
  }

  /**
   * @param {string} name
   */
  setName(name) {
    this._columnWeightsSetting = Common.settings.createSetting('dataGrid-' + name + '-columnWeights', {});
    this._loadColumnWeights();
  }

  _loadColumnWeights() {
    if (!this._columnWeightsSetting) {
      return;
    }
    const weights = this._columnWeightsSetting.get();
    for (let i = 0; i < this._columnsArray.length; ++i) {
      const column = this._columnsArray[i];
      const weight = weights[column.id];
      if (weight) {
        column.weight = weight;
      }
    }
    this._applyColumnWeights();
  }

  _saveColumnWeights() {
    if (!this._columnWeightsSetting) {
      return;
    }
    const weights = {};
    for (let i = 0; i < this._columnsArray.length; ++i) {
      const column = this._columnsArray[i];
      weights[column.id] = column.weight;
    }
    this._columnWeightsSetting.set(weights);
  }

  wasShown() {
    this._loadColumnWeights();
  }

  willHide() {
  }

  _applyColumnWeights() {
    let tableWidth = this.element.offsetWidth - this._cornerWidth;
    if (tableWidth <= 0) {
      return;
    }

    let sumOfWeights = 0.0;
    const fixedColumnWidths = [];
    for (let i = 0; i < this._visibleColumnsArray.length; ++i) {
      const column = this._visibleColumnsArray[i];
      if (column.fixedWidth) {
        const width = this._headerTableColumnGroup.children[i][DataGrid._preferredWidthSymbol] ||
            this._headerTableBody.rows[0].cells[i].offsetWidth;
        fixedColumnWidths[i] = width;
        tableWidth -= width;
      } else {
        sumOfWeights += this._visibleColumnsArray[i].weight;
      }
    }
    let sum = 0;
    let lastOffset = 0;

    for (let i = 0; i < this._visibleColumnsArray.length; ++i) {
      const column = this._visibleColumnsArray[i];
      let width;
      if (column.fixedWidth) {
        width = fixedColumnWidths[i];
      } else {
        sum += column.weight;
        const offset = (sum * tableWidth / sumOfWeights) | 0;
        width = offset - lastOffset;
        lastOffset = offset;
      }
      this._setPreferredWidth(i, width);
    }

    this._positionResizers();
  }

  /**
   * @param {!Object.<string, boolean>} columnsVisibility
   */
  setColumnsVisiblity(columnsVisibility) {
    this._visibleColumnsArray = [];
    for (let i = 0; i < this._columnsArray.length; ++i) {
      const column = this._columnsArray[i];
      if (columnsVisibility[column.id]) {
        this._visibleColumnsArray.push(column);
      }
    }
    this._refreshHeader();
    this._applyColumnWeights();
    const nodes = this._enumerateChildren(this.rootNode(), [], -1);
    for (let i = 0; i < nodes.length; ++i) {
      nodes[i].refresh();
    }
  }

  get scrollContainer() {
    return this._scrollContainer;
  }

  _positionResizers() {
    const headerTableColumns = this._headerTableColumnGroup.children;
    const numColumns = headerTableColumns.length - 1;  // Do not process corner column.
    const left = [];
    const resizers = this._resizers;

    while (resizers.length > numColumns - 1) {
      resizers.pop().remove();
    }

    for (let i = 0; i < numColumns - 1; i++) {
      // Get the width of the cell in the first (and only) row of the
      // header table in order to determine the width of the column, since
      // it is not possible to query a column for its width.
      left[i] = (left[i - 1] || 0) + this._headerTableBody.rows[0].cells[i].offsetWidth;
    }

    // Make n - 1 resizers for n columns.
    for (let i = 0; i < numColumns - 1; i++) {
      let resizer = resizers[i];
      if (!resizer) {
        // This is the first call to updateWidth, so the resizers need
        // to be created.
        resizer = createElement('div');
        resizer.__index = i;
        resizer.classList.add('data-grid-resizer');
        // This resizer is associated with the column to its right.
        UI.installDragHandle(
            resizer, this._startResizerDragging.bind(this), this._resizerDragging.bind(this),
            this._endResizerDragging.bind(this), 'col-resize');
        this.element.appendChild(resizer);
        resizers.push(resizer);
      }
      if (resizer.__position !== left[i]) {
        resizer.__position = left[i];
        resizer.style.left = left[i] + 'px';
      }
    }
  }

  addCreationNode(hasChildren) {
    if (this.creationNode) {
      this.creationNode.makeNormal();
    }

    const emptyData = {};
    for (const column in this._columns) {
      emptyData[column] = null;
    }
    this.creationNode = new DataGrid.CreationDataGridNode(emptyData, hasChildren);
    this.rootNode().appendChild(this.creationNode);
  }

  /**
   * @param {!Event} event
   * @suppressGlobalPropertiesCheck
   */
  _keyDown(event) {
    if (event.shiftKey || event.metaKey || event.ctrlKey || this._editing || UI.isEditing()) {
      return;
    }

    let handled = false;
    let nextSelectedNode;
    if (!this.selectedNode) {
      // Select the first or last node based on the arrow key direction
      if (event.key === 'ArrowUp' && !event.altKey) {
        nextSelectedNode = this._lastSelectableNode();
      } else if (event.key === 'ArrowDown' && !event.altKey) {
        nextSelectedNode = this._firstSelectableNode();
      }
      handled = nextSelectedNode ? true : false;
    } else if (event.key === 'ArrowUp' && !event.altKey) {
      nextSelectedNode = this.selectedNode.traversePreviousNode(true);
      while (nextSelectedNode && !nextSelectedNode.selectable) {
        nextSelectedNode = nextSelectedNode.traversePreviousNode(true);
      }
      handled = nextSelectedNode ? true : false;
    } else if (event.key === 'ArrowDown' && !event.altKey) {
      nextSelectedNode = this.selectedNode.traverseNextNode(true);
      while (nextSelectedNode && !nextSelectedNode.selectable) {
        nextSelectedNode = nextSelectedNode.traverseNextNode(true);
      }
      handled = nextSelectedNode ? true : false;
    } else if (event.key === 'ArrowLeft') {
      if (this.selectedNode.expanded) {
        if (event.altKey) {
          this.selectedNode.collapseRecursively();
        } else {
          this.selectedNode.collapse();
        }
        handled = true;
      } else if (this.selectedNode.parent && !this.selectedNode.parent._isRoot) {
        handled = true;
        if (this.selectedNode.parent.selectable) {
          nextSelectedNode = this.selectedNode.parent;
          handled = nextSelectedNode ? true : false;
        } else if (this.selectedNode.parent) {
          this.selectedNode.parent.collapse();
        }
      }
    } else if (event.key === 'ArrowRight') {
      if (!this.selectedNode.revealed) {
        this.selectedNode.reveal();
        handled = true;
      } else if (this.selectedNode.hasChildren()) {
        handled = true;
        if (this.selectedNode.expanded) {
          nextSelectedNode = this.selectedNode.children[0];
          handled = nextSelectedNode ? true : false;
        } else {
          if (event.altKey) {
            this.selectedNode.expandRecursively();
          } else {
            this.selectedNode.expand();
          }
        }
      }
    } else if (event.keyCode === 8 || event.keyCode === 46) {
      if (this._deleteCallback) {
        handled = true;
        this._deleteCallback(this.selectedNode);
      }
    } else if (isEnterKey(event)) {
      if (this._editCallback) {
        handled = true;
        this._startEditing(this.selectedNode._element.children[this._nextEditableColumn(-1)]);
      } else {
        this.dispatchEventToListeners(Events.OpenedNode, this.selectedNode);
      }
    }

    if (nextSelectedNode) {
      nextSelectedNode.reveal();
      nextSelectedNode.select();
    }

    if ((event.key === 'ArrowUp' || event.key === 'ArrowDown' || event.key === 'ArrowLeft' ||
         event.key === 'ArrowRight') &&
        document.activeElement !== this.element) {
      // crbug.com/1005449
      // navigational keys pressed but current DataGrid panel has lost focus;
      // re-focus to ensure subsequent keydowns can be registered within this DataGrid
      this.element.focus();
    }

    if (handled) {
      event.consume(true);
    }
  }

  /**
   * @param {?NODE_TYPE} root
   * @param {boolean} onlyAffectsSubtree
   */
  updateSelectionBeforeRemoval(root, onlyAffectsSubtree) {
    let ancestor = this.selectedNode;
    while (ancestor && ancestor !== root) {
      ancestor = ancestor.parent;
    }
    // Selection is not in the subtree being deleted.
    if (!ancestor) {
      return;
    }

    let nextSelectedNode;
    // Skip subtree being deleted when looking for the next selectable node.
    for (ancestor = root; ancestor && !ancestor.nextSibling; ancestor = ancestor.parent) {
    }
    if (ancestor) {
      nextSelectedNode = ancestor.nextSibling;
    }
    while (nextSelectedNode && !nextSelectedNode.selectable) {
      nextSelectedNode = nextSelectedNode.traverseNextNode(true);
    }

    if (!nextSelectedNode || nextSelectedNode.isCreationNode) {
      nextSelectedNode = root.traversePreviousNode(true);
      while (nextSelectedNode && !nextSelectedNode.selectable) {
        nextSelectedNode = nextSelectedNode.traversePreviousNode(true);
      }
    }
    if (nextSelectedNode) {
      nextSelectedNode.reveal();
      nextSelectedNode.select();
    } else {
      this.selectedNode.deselect();
    }
  }

  /**
   * @param {!Node} target
   * @return {?NODE_TYPE}
   */
  dataGridNodeFromNode(target) {
    const rowElement = target.enclosingNodeOrSelfWithNodeName('tr');
    return rowElement && rowElement._dataGridNode;
  }

  /**
   * @param {!Node} target
   * @return {?string}
   */
  columnIdFromNode(target) {
    const cellElement = target.enclosingNodeOrSelfWithNodeName('td');
    return cellElement && cellElement[DataGrid._columnIdSymbol];
  }

  /**
   * @param {!Event} event
   */
  _clickInHeaderCell(event) {
    const cell = event.target.enclosingNodeOrSelfWithNodeName('th');
    if (!cell) {
      return;
    }
    this._sortByColumnHeaderCell(cell);
  }

  /**
   * @param {!Node} cell
   */
  _sortByColumnHeaderCell(cell) {
    if ((cell[DataGrid._columnIdSymbol] === undefined) || !cell.classList.contains('sortable')) {
      return;
    }

    let sortOrder = Order.Ascending;
    if ((cell === this._sortColumnCell) && this.isSortOrderAscending()) {
      sortOrder = Order.Descending;
    }

    if (this._sortColumnCell) {
      this._sortColumnCell.classList.remove(Order.Ascending, Order.Descending);
    }
    this._sortColumnCell = cell;

    cell.classList.add(sortOrder);
    const icon = cell[DataGrid._sortIconSymbol];
    icon.setIconType(sortOrder === Order.Ascending ? 'smallicon-triangle-up' : 'smallicon-triangle-down');

    this.dispatchEventToListeners(Events.SortingChanged);
  }

  /**
   * @param {string} columnId
   * @param {!Order} sortOrder
   */
  markColumnAsSortedBy(columnId, sortOrder) {
    if (this._sortColumnCell) {
      this._sortColumnCell.classList.remove(Order.Ascending, Order.Descending);
    }
    this._sortColumnCell = this._headerTableHeaders[columnId];
    this._sortColumnCell.classList.add(sortOrder);
  }

  /**
   * @param {string} columnId
   * @return {!Element}
   */
  headerTableHeader(columnId) {
    return this._headerTableHeaders[columnId];
  }

  /**
   * @param {!Event} event
   */
  _mouseDownInDataTable(event) {
    const target = /** @type {!Node} */ (event.target);
    const gridNode = this.dataGridNodeFromNode(target);
    if (!gridNode || !gridNode.selectable || gridNode.isEventWithinDisclosureTriangle(event)) {
      return;
    }

    const columnId = this.columnIdFromNode(target);
    if (columnId && this._columns[columnId].nonSelectable) {
      return;
    }

    if (event.metaKey) {
      if (gridNode.selected) {
        gridNode.deselect();
      } else {
        gridNode.select();
      }
    } else {
      gridNode.select();
      this.dispatchEventToListeners(Events.OpenedNode, gridNode);
    }
  }

  /**
   * @param {?function(!UI.ContextSubMenu)} callback
   */
  setHeaderContextMenuCallback(callback) {
    this._headerContextMenuCallback = callback;
  }

  /**
   * @param {?function(!UI.ContextMenu, !NODE_TYPE)} callback
   */
  setRowContextMenuCallback(callback) {
    this._rowContextMenuCallback = callback;
  }

  /**
   * @param {!Event} event
   */
  _contextMenu(event) {
    const contextMenu = new UI.ContextMenu(event);
    const target = /** @type {!Node} */ (event.target);

    const sortableVisibleColumns = this._visibleColumnsArray.filter(column => {
      return (column.sortable && column.title);
    });

    const sortableHiddenColumns = this._columnsArray.filter(
        column => sortableVisibleColumns.indexOf(column) === -1 && column.allowInSortByEvenWhenHidden);

    const sortableColumns = [...sortableVisibleColumns, ...sortableHiddenColumns];
    if (sortableColumns.length > 0) {
      const sortMenu = contextMenu.defaultSection().appendSubMenuItem(ls`Sort By`);
      for (const column of sortableColumns) {
        const headerCell = this._headerTableHeaders[column.id];
        sortMenu.defaultSection().appendItem(
            /** @type {string} */ (column.title), this._sortByColumnHeaderCell.bind(this, headerCell));
      }
    }

    if (this._headerContextMenuCallback) {
      if (target.isSelfOrDescendant(this._headerTableBody)) {
        this._headerContextMenuCallback(contextMenu);
        contextMenu.show();
        return;
      } else {
        // Add header context menu to a subsection available from the body
        const headerSubMenu = contextMenu.defaultSection().appendSubMenuItem(ls`Header Options`);
        this._headerContextMenuCallback(headerSubMenu);
      }
    }

    const isContextMenuKey = (event.button === 0);
    const gridNode = isContextMenuKey ? this.selectedNode : this.dataGridNodeFromNode(target);
    if (isContextMenuKey && this.selectedNode) {
      const boundingRowRect = this.selectedNode.existingElement().getBoundingClientRect();
      if (boundingRowRect) {
        const x = (boundingRowRect.right + boundingRowRect.left) / 2;
        const y = (boundingRowRect.bottom + boundingRowRect.top) / 2;
        contextMenu.setX(x);
        contextMenu.setY(y);
      }
    }
    if (this._refreshCallback && (!gridNode || gridNode !== this.creationNode)) {
      contextMenu.defaultSection().appendItem(Common.UIString('Refresh'), this._refreshCallback.bind(this));
    }

    if (gridNode && gridNode.selectable && !gridNode.isEventWithinDisclosureTriangle(event)) {
      if (this._editCallback) {
        if (gridNode === this.creationNode) {
          contextMenu.defaultSection().appendItem(Common.UIString('Add new'), this._startEditing.bind(this, target));
        } else if (isContextMenuKey) {
          const firstEditColumnIndex = this._nextEditableColumn(-1);
          if (firstEditColumnIndex > -1) {
            const firstColumn = this._visibleColumnsArray[firstEditColumnIndex];
            if (firstColumn && firstColumn.editable) {
              contextMenu.defaultSection().appendItem(
                  ls`Edit "${firstColumn.title}"`,
                  this._startEditingColumnOfDataGridNode.bind(this, gridNode, firstEditColumnIndex));
            }
          }
        } else {
          const columnId = this.columnIdFromNode(target);
          if (columnId && this._columns[columnId].editable) {
            contextMenu.defaultSection().appendItem(
                Common.UIString('Edit "%s"', this._columns[columnId].title), this._startEditing.bind(this, target));
          }
        }
      }
      if (this._deleteCallback && gridNode !== this.creationNode) {
        contextMenu.defaultSection().appendItem(Common.UIString('Delete'), this._deleteCallback.bind(this, gridNode));
      }
      if (this._rowContextMenuCallback) {
        this._rowContextMenuCallback(contextMenu, gridNode);
      }
    }

    contextMenu.show();
  }

  /**
   * @param {!Event} event
   */
  _clickInDataTable(event) {
    const gridNode = this.dataGridNodeFromNode(/** @type {!Node} */ (event.target));
    if (!gridNode || !gridNode.hasChildren() || !gridNode.isEventWithinDisclosureTriangle(event)) {
      return;
    }

    if (gridNode.expanded) {
      if (event.altKey) {
        gridNode.collapseRecursively();
      } else {
        gridNode.collapse();
      }
    } else {
      if (event.altKey) {
        gridNode.expandRecursively();
      } else {
        gridNode.expand();
      }
    }
  }

  /**
   * @param {!ResizeMethod} method
   */
  setResizeMethod(method) {
    this._resizeMethod = method;
  }

  /**
   * @param {!Event} event
   * @return {boolean}
   */
  _startResizerDragging(event) {
    this._currentResizer = event.target;
    return true;
  }

  _endResizerDragging() {
    this._currentResizer = null;
    this._saveColumnWeights();
  }

  /**
   * @param {!Event} event
   */
  _resizerDragging(event) {
    const resizer = this._currentResizer;
    if (!resizer) {
      return;
    }

    // Constrain the dragpoint to be within the containing div of the
    // datagrid.
    let dragPoint = event.clientX - this.element.totalOffsetLeft();
    const firstRowCells = this._headerTableBody.rows[0].cells;
    let leftEdgeOfPreviousColumn = 0;
    // Constrain the dragpoint to be within the space made up by the
    // column directly to the left and the column directly to the right.
    let leftCellIndex = resizer.__index;
    let rightCellIndex = leftCellIndex + 1;
    for (let i = 0; i < leftCellIndex; i++) {
      leftEdgeOfPreviousColumn += firstRowCells[i].offsetWidth;
    }

    // Differences for other resize methods
    if (this._resizeMethod === ResizeMethod.Last) {
      rightCellIndex = this._resizers.length;
    } else if (this._resizeMethod === ResizeMethod.First) {
      leftEdgeOfPreviousColumn += firstRowCells[leftCellIndex].offsetWidth - firstRowCells[0].offsetWidth;
      leftCellIndex = 0;
    }

    const rightEdgeOfNextColumn =
        leftEdgeOfPreviousColumn + firstRowCells[leftCellIndex].offsetWidth + firstRowCells[rightCellIndex].offsetWidth;

    // Give each column some padding so that they don't disappear.
    const leftMinimum = leftEdgeOfPreviousColumn + ColumnResizePadding;
    const rightMaximum = rightEdgeOfNextColumn - ColumnResizePadding;
    if (leftMinimum > rightMaximum) {
      return;
    }

    dragPoint = Number.constrain(dragPoint, leftMinimum, rightMaximum);

    const position = (dragPoint - CenterResizerOverBorderAdjustment);
    resizer.__position = position;
    resizer.style.left = position + 'px';

    this._setPreferredWidth(leftCellIndex, dragPoint - leftEdgeOfPreviousColumn);
    this._setPreferredWidth(rightCellIndex, rightEdgeOfNextColumn - dragPoint);

    const leftColumn = this._visibleColumnsArray[leftCellIndex];
    const rightColumn = this._visibleColumnsArray[rightCellIndex];
    if (leftColumn.weight || rightColumn.weight) {
      const sumOfWeights = leftColumn.weight + rightColumn.weight;
      const delta = rightEdgeOfNextColumn - leftEdgeOfPreviousColumn;
      leftColumn.weight = (dragPoint - leftEdgeOfPreviousColumn) * sumOfWeights / delta;
      rightColumn.weight = (rightEdgeOfNextColumn - dragPoint) * sumOfWeights / delta;
    }

    this._positionResizers();
    event.preventDefault();
  }

  /**
   * @param {number} columnIndex
   * @param {number} width
   */
  _setPreferredWidth(columnIndex, width) {
    const pxWidth = width + 'px';
    this._headerTableColumnGroup.children[columnIndex][DataGrid._preferredWidthSymbol] = width;
    this._headerTableColumnGroup.children[columnIndex].style.width = pxWidth;
    this._dataTableColumnGroup.children[columnIndex].style.width = pxWidth;
  }

  /**
   * @param {string} columnId
   * @return {number}
   */
  columnOffset(columnId) {
    if (!this.element.offsetWidth) {
      return 0;
    }
    for (let i = 1; i < this._visibleColumnsArray.length; ++i) {
      if (columnId === this._visibleColumnsArray[i].id) {
        if (this._resizers[i - 1]) {
          return this._resizers[i - 1].__position;
        }
      }
    }
    return 0;
  }

  /**
   * @return {!DataGridWidget}
   */
  asWidget() {
    if (!this._dataGridWidget) {
      this._dataGridWidget = new DataGridWidget(this);
    }
    return this._dataGridWidget;
  }

  topFillerRowElement() {
    return this._topFillerRow;
  }
}

// Keep in sync with .data-grid col.corner style rule.
export const CornerWidth = 14;


/** @enum {symbol} */
export const Events = {
  SelectedNode: Symbol('SelectedNode'),
  DeselectedNode: Symbol('DeselectedNode'),
  OpenedNode: Symbol('OpenedNode'),
  SortingChanged: Symbol('SortingChanged'),
  PaddingChanged: Symbol('PaddingChanged'),
};

/** @enum {string} */
export const Order = {
  Ascending: 'sort-ascending',
  Descending: 'sort-descending'
};

/** @enum {string} */
export const Align = {
  Center: 'center',
  Right: 'right'
};

export const ColumnResizePadding = 24;
export const CenterResizerOverBorderAdjustment = 3;

/** @enum {string} */
export const ResizeMethod = {
  Nearest: 'nearest',
  First: 'first',
  Last: 'last'
};

/**
 * @unrestricted
 * @template NODE_TYPE
 */
export class DataGridNode extends Common.Object {
  /**
   * @param {?Object.<string, *>=} data
   * @param {boolean=} hasChildren
   */
  constructor(data, hasChildren) {
    super();
    /** @type {?Element} */
    this._element = null;
    /** @protected @type {boolean} @suppress {accessControls} */
    this._expanded = false;
    /** @type {boolean} */
    this._selected = false;
    /** @type {boolean} */
    this._dirty = false;
    /** @type {boolean} */
    this._inactive = false;
    /** @type {number|undefined} */
    this._depth;
    /** @type {boolean|undefined} */
    this._revealed;
    /** @type {boolean} */
    this._attached = false;
    /** @type {?{parent: !NODE_TYPE, index: number}} */
    this._savedPosition = null;
    /** @type {boolean} */
    this._shouldRefreshChildren = true;
    /** @type {!Object.<string, *>} */
    this._data = data || {};
    /** @type {boolean} */
    this._hasChildren = hasChildren || false;
    /** @type {!Array.<!NODE_TYPE>} */
    this.children = [];
    /** @type {?DataGrid.DataGrid} */
    this.dataGrid = null;
    /** @type {?NODE_TYPE} */
    this.parent = null;
    /** @type {?NODE_TYPE} */
    this.previousSibling = null;
    /** @type {?NODE_TYPE} */
    this.nextSibling = null;
    /** @type {number} */
    this.disclosureToggleWidth = 10;

    /** @type {boolean} */
    this.selectable = true;

    /** @type {boolean} */
    this._isRoot = false;
  }

  /**
   * @return {!Element}
   */
  element() {
    if (!this._element) {
      const element = this.createElement();
      this.createCells(element);
    }
    return /** @type {!Element} */ (this._element);
  }

  /**
   * @protected
   * @return {!Element}
   */
  createElement() {
    this._element = createElementWithClass('tr', 'data-grid-data-grid-node');
    this._element._dataGridNode = this;

    if (this._hasChildren) {
      this._element.classList.add('parent');
    }
    if (this.expanded) {
      this._element.classList.add('expanded');
    }
    if (this.selected) {
      this._element.classList.add('selected');
    }
    if (this.revealed) {
      this._element.classList.add('revealed');
    }
    if (this.dirty) {
      this._element.classList.add('dirty');
    }
    if (this.inactive) {
      this._element.classList.add('inactive');
    }
    return this._element;
  }

  /**
   * @return {?Element}
   */
  existingElement() {
    return this._element || null;
  }

  /**
   * @protected
   */
  resetElement() {
    this._element = null;
  }

  /**
   * @param {!Element} element
   * @protected
   */
  createCells(element) {
    element.removeChildren();
    const columnsArray = this.dataGrid._visibleColumnsArray;
    for (let i = 0; i < columnsArray.length; ++i) {
      element.appendChild(this.createCell(columnsArray[i].id));
    }
    element.appendChild(this._createTDWithClass('corner'));
  }

  /**
   * @return {!Object.<string, *>}
   */
  get data() {
    return this._data;
  }

  /**
   * @param {!Object.<string, *>} x
   */
  set data(x) {
    this._data = x || {};
    this.refresh();
  }

  /**
   * @return {boolean}
   */
  get revealed() {
    if (this._revealed !== undefined) {
      return this._revealed;
    }

    let currentAncestor = this.parent;
    while (currentAncestor && !currentAncestor._isRoot) {
      if (!currentAncestor.expanded) {
        this._revealed = false;
        return false;
      }

      currentAncestor = currentAncestor.parent;
    }

    this.revealed = true;
    return true;
  }

  /**
   * @param {boolean} x
   */
  set revealed(x) {
    if (this._revealed === x) {
      return;
    }

    this._revealed = x;

    if (this._element) {
      this._element.classList.toggle('revealed', this._revealed);
    }

    for (let i = 0; i < this.children.length; ++i) {
      this.children[i].revealed = x && this.expanded;
    }
  }

  /**
   * @return {boolean}
   */
  isDirty() {
    return this._dirty;
  }

  /**
   * @param {boolean} dirty
   */
  setDirty(dirty) {
    if (this._dirty === dirty) {
      return;
    }
    this._dirty = dirty;
    if (!this._element) {
      return;
    }
    if (dirty) {
      this._element.classList.add('dirty');
    } else {
      this._element.classList.remove('dirty');
    }
  }


  /**
   * @return {boolean}
   */
  isInactive() {
    return this._inactive;
  }

  /**
   * @param {boolean} inactive
   */
  setInactive(inactive) {
    if (this._inactive === inactive) {
      return;
    }
    this._inactive = inactive;
    if (!this._element) {
      return;
    }
    if (inactive) {
      this._element.classList.add('inactive');
    } else {
      this._element.classList.remove('inactive');
    }
  }

  /**
   * @return {boolean}
   */
  hasChildren() {
    return this._hasChildren;
  }

  /**
   * @param {boolean} x
   */
  setHasChildren(x) {
    if (this._hasChildren === x) {
      return;
    }

    this._hasChildren = x;

    if (!this._element) {
      return;
    }

    this._element.classList.toggle('parent', this._hasChildren);
    this._element.classList.toggle('expanded', this._hasChildren && this.expanded);
  }

  /**
   * @return {number}
   */
  get depth() {
    if (this._depth !== undefined) {
      return this._depth;
    }
    if (this.parent && !this.parent._isRoot) {
      this._depth = this.parent.depth + 1;
    } else {
      this._depth = 0;
    }
    return this._depth;
  }

  /**
   * @return {number}
   */
  get leftPadding() {
    return this.depth * this.dataGrid.indentWidth;
  }

  /**
   * @return {boolean}
   */
  get shouldRefreshChildren() {
    return this._shouldRefreshChildren;
  }

  /**
   * @param {boolean} x
   */
  set shouldRefreshChildren(x) {
    this._shouldRefreshChildren = x;
    if (x && this.expanded) {
      this.expand();
    }
  }

  /**
   * @return {boolean}
   */
  get selected() {
    return this._selected;
  }

  /**
   * @param {boolean} x
   */
  set selected(x) {
    if (x) {
      this.select();
    } else {
      this.deselect();
    }
  }

  /**
   * @return {boolean}
   */
  get expanded() {
    return this._expanded;
  }

  /**
   * @param {boolean} x
   */
  set expanded(x) {
    if (x) {
      this.expand();
    } else {
      this.collapse();
    }
  }

  refresh() {
    if (!this.dataGrid) {
      this._element = null;
    }
    if (!this._element) {
      return;
    }
    this.createCells(this._element);
  }

  /**
   * @param {string} className
   * @return {!Element}
   */
  _createTDWithClass(className) {
    const cell = createElementWithClass('td', className);
    const cellClass = this.dataGrid._cellClass;
    if (cellClass) {
      cell.classList.add(cellClass);
    }
    return cell;
  }

  /**
   * @param {string} columnId
   * @return {!Element}
   */
  createTD(columnId) {
    const cell = this._createTDWithClass(columnId + '-column');
    cell[DataGrid._columnIdSymbol] = columnId;

    const alignment = this.dataGrid._columns[columnId].align;
    if (alignment) {
      cell.classList.add(alignment);
    }

    if (columnId === this.dataGrid.disclosureColumnId) {
      cell.classList.add('disclosure');
      if (this.leftPadding) {
        cell.style.setProperty('padding-left', this.leftPadding + 'px');
      }
    }

    return cell;
  }

  /**
   * @param {string} columnId
   * @return {!Element}
   */
  createCell(columnId) {
    const cell = this.createTD(columnId);
    const data = this.data[columnId];
    if (data instanceof Node) {
      cell.appendChild(data);
    } else if (data !== null) {
      DataGrid.DataGrid.setElementText(cell, /** @type {string} */ (data), !!this.dataGrid._columns[columnId].longText);
    }

    return cell;
  }

  /**
   * @return {number}
   */
  nodeSelfHeight() {
    return 20;
  }

  /**
   * @param {!NODE_TYPE} child
   */
  appendChild(child) {
    this.insertChild(child, this.children.length);
  }

  /**
   * @param {boolean=} onlyCaches
   */
  resetNode(onlyCaches) {
    // @TODO(allada) This is a hack to make sure ViewportDataGrid can clean up these caches. Try Not To Use.
    delete this._depth;
    delete this._revealed;
    if (onlyCaches) {
      return;
    }
    if (this.previousSibling) {
      this.previousSibling.nextSibling = this.nextSibling;
    }
    if (this.nextSibling) {
      this.nextSibling.previousSibling = this.previousSibling;
    }
    this.dataGrid = null;
    this.parent = null;
    this.nextSibling = null;
    this.previousSibling = null;
    this._attached = false;
  }

  /**
   * @param {!NODE_TYPE} child
   * @param {number} index
   */
  insertChild(child, index) {
    if (!child) {
      throw 'insertChild: Node can\'t be undefined or null.';
    }
    if (child.parent === this) {
      const currentIndex = this.children.indexOf(child);
      if (currentIndex < 0) {
        console.assert(false, 'Inconsistent DataGrid state');
      }
      if (currentIndex === index) {
        return;
      }
      if (currentIndex < index) {
        --index;
      }
    }

    child.remove();

    this.children.splice(index, 0, child);
    this.setHasChildren(true);

    child.parent = this;
    child.dataGrid = this.dataGrid;
    child.recalculateSiblings(index);

    child._shouldRefreshChildren = true;

    let current = child.children[0];
    while (current) {
      current.resetNode(true);
      current.dataGrid = this.dataGrid;
      current._attached = false;
      current._shouldRefreshChildren = true;
      current = current.traverseNextNode(false, child, true);
    }

    if (this.expanded) {
      child._attach();
    }
    if (!this.revealed) {
      child.revealed = false;
    }
  }

  remove() {
    if (this.parent) {
      this.parent.removeChild(this);
    }
  }

  /**
   * @param {!NODE_TYPE} child
   */
  removeChild(child) {
    if (!child) {
      throw 'removeChild: Node can\'t be undefined or null.';
    }
    if (child.parent !== this) {
      throw 'removeChild: Node is not a child of this node.';
    }

    if (this.dataGrid) {
      this.dataGrid.updateSelectionBeforeRemoval(child, false);
    }

    child._detach();
    child.resetNode();
    this.children.remove(child, true);

    if (this.children.length <= 0) {
      this.setHasChildren(false);
    }
  }

  removeChildren() {
    if (this.dataGrid) {
      this.dataGrid.updateSelectionBeforeRemoval(this, true);
    }
    for (let i = 0; i < this.children.length; ++i) {
      const child = this.children[i];
      child._detach();
      child.resetNode();
    }

    this.children = [];
    this.setHasChildren(false);
  }

  /**
   * @param {number} myIndex
   */
  recalculateSiblings(myIndex) {
    if (!this.parent) {
      return;
    }

    const previousChild = this.parent.children[myIndex - 1] || null;
    if (previousChild) {
      previousChild.nextSibling = this;
    }
    this.previousSibling = previousChild;

    const nextChild = this.parent.children[myIndex + 1] || null;
    if (nextChild) {
      nextChild.previousSibling = this;
    }
    this.nextSibling = nextChild;
  }

  collapse() {
    if (this._isRoot) {
      return;
    }
    if (this._element) {
      this._element.classList.remove('expanded');
    }

    this._expanded = false;

    for (let i = 0; i < this.children.length; ++i) {
      this.children[i].revealed = false;
    }
  }

  collapseRecursively() {
    let item = this;
    while (item) {
      if (item.expanded) {
        item.collapse();
      }
      item = item.traverseNextNode(false, this, true);
    }
  }

  populate() {
  }

  expand() {
    if (!this._hasChildren || this.expanded) {
      return;
    }
    if (this._isRoot) {
      return;
    }

    if (this.revealed && !this._shouldRefreshChildren) {
      for (let i = 0; i < this.children.length; ++i) {
        this.children[i].revealed = true;
      }
    }

    if (this._shouldRefreshChildren) {
      for (let i = 0; i < this.children.length; ++i) {
        this.children[i]._detach();
      }

      this.populate();

      if (this._attached) {
        for (let i = 0; i < this.children.length; ++i) {
          const child = this.children[i];
          if (this.revealed) {
            child.revealed = true;
          }
          child._attach();
        }
      }

      this._shouldRefreshChildren = false;
    }

    if (this._element) {
      this._element.classList.add('expanded');
    }

    this._expanded = true;
  }

  expandRecursively() {
    let item = this;
    while (item) {
      item.expand();
      item = item.traverseNextNode(false, this);
    }
  }

  reveal() {
    if (this._isRoot) {
      return;
    }
    let currentAncestor = this.parent;
    while (currentAncestor && !currentAncestor._isRoot) {
      if (!currentAncestor.expanded) {
        currentAncestor.expand();
      }
      currentAncestor = currentAncestor.parent;
    }

    this.element().scrollIntoViewIfNeeded(false);
  }

  /**
   * @param {boolean=} supressSelectedEvent
   */
  select(supressSelectedEvent) {
    if (!this.dataGrid || !this.selectable || this.selected) {
      return;
    }

    if (this.dataGrid.selectedNode) {
      this.dataGrid.selectedNode.deselect();
    }

    this._selected = true;
    this.dataGrid.selectedNode = this;

    if (this._element) {
      this._element.classList.add('selected');
      this.dataGrid.setHasSelection(true);
    }

    if (!supressSelectedEvent) {
      this.dataGrid.dispatchEventToListeners(Events.SelectedNode, this);
    }
  }

  revealAndSelect() {
    if (this._isRoot) {
      return;
    }
    this.reveal();
    this.select();
  }

  /**
   * @param {boolean=} supressDeselectedEvent
   */
  deselect(supressDeselectedEvent) {
    if (!this.dataGrid || this.dataGrid.selectedNode !== this || !this.selected) {
      return;
    }

    this._selected = false;
    this.dataGrid.selectedNode = null;

    if (this._element) {
      this._element.classList.remove('selected');
      this.dataGrid.setHasSelection(false);
    }

    if (!supressDeselectedEvent) {
      this.dataGrid.dispatchEventToListeners(Events.DeselectedNode);
    }
  }

  /**
   * @param {boolean} skipHidden
   * @param {?NODE_TYPE=} stayWithin
   * @param {boolean=} dontPopulate
   * @param {!Object=} info
   * @return {?NODE_TYPE}
   */
  traverseNextNode(skipHidden, stayWithin, dontPopulate, info) {
    if (!dontPopulate && this._hasChildren) {
      this.populate();
    }

    if (info) {
      info.depthChange = 0;
    }

    let node = (!skipHidden || this.revealed) ? this.children[0] : null;
    if (node && (!skipHidden || this.expanded)) {
      if (info) {
        info.depthChange = 1;
      }
      return node;
    }

    if (this === stayWithin) {
      return null;
    }

    node = (!skipHidden || this.revealed) ? this.nextSibling : null;
    if (node) {
      return node;
    }

    node = this;
    while (node && !node._isRoot && !((!skipHidden || node.revealed) ? node.nextSibling : null) &&
           node.parent !== stayWithin) {
      if (info) {
        info.depthChange -= 1;
      }
      node = node.parent;
    }

    if (!node) {
      return null;
    }

    return (!skipHidden || node.revealed) ? node.nextSibling : null;
  }

  /**
   * @param {boolean} skipHidden
   * @param {boolean=} dontPopulate
   * @return {?NODE_TYPE}
   */
  traversePreviousNode(skipHidden, dontPopulate) {
    let node = (!skipHidden || this.revealed) ? this.previousSibling : null;
    if (!dontPopulate && node && node._hasChildren) {
      node.populate();
    }

    while (node &&
           ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null)) {
      if (!dontPopulate && node._hasChildren) {
        node.populate();
      }
      node = ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null);
    }

    if (node) {
      return node;
    }

    if (!this.parent || this.parent._isRoot) {
      return null;
    }

    return this.parent;
  }

  /**
   * @param {!Event} event
   * @return {boolean}
   */
  isEventWithinDisclosureTriangle(event) {
    if (!this._hasChildren) {
      return false;
    }
    const cell = event.target.enclosingNodeOrSelfWithNodeName('td');
    if (!cell || !cell.classList.contains('disclosure')) {
      return false;
    }

    const left = cell.totalOffsetLeft() + this.leftPadding;
    return event.pageX >= left && event.pageX <= left + this.disclosureToggleWidth;
  }

  _attach() {
    if (!this.dataGrid || this._attached) {
      return;
    }

    this._attached = true;

    const previousNode = this.traversePreviousNode(true, true);
    const previousElement = previousNode ? previousNode.element() : this.dataGrid._topFillerRow;
    this.dataGrid.dataTableBody.insertBefore(this.element(), previousElement.nextSibling);

    if (this.expanded) {
      for (let i = 0; i < this.children.length; ++i) {
        this.children[i]._attach();
      }
    }
  }

  _detach() {
    if (!this._attached) {
      return;
    }

    this._attached = false;

    if (this._element) {
      this._element.remove();
    }

    for (let i = 0; i < this.children.length; ++i) {
      this.children[i]._detach();
    }
  }

  savePosition() {
    if (this._savedPosition) {
      return;
    }

    if (!this.parent) {
      throw 'savePosition: Node must have a parent.';
    }
    this._savedPosition = {parent: this.parent, index: this.parent.children.indexOf(this)};
  }

  restorePosition() {
    if (!this._savedPosition) {
      return;
    }

    if (this.parent !== this._savedPosition.parent) {
      this._savedPosition.parent.insertChild(this, this._savedPosition.index);
    }

    this._savedPosition = null;
  }
}

/**
 * @unrestricted
 * @extends {DataGridNode<!NODE_TYPE>}
 * @template NODE_TYPE
 */
export class CreationDataGridNode extends DataGridNode {
  constructor(data, hasChildren) {
    super(data, hasChildren);
    /** @type {boolean} */
    this.isCreationNode = true;
  }

  makeNormal() {
    this.isCreationNode = false;
  }
}

/**
 * @unrestricted
 */
export class DataGridWidget extends UI.VBox {
  /**
   * @param {!DataGrid.DataGrid} dataGrid
   */
  constructor(dataGrid) {
    super();
    this._dataGrid = dataGrid;
    this.element.appendChild(dataGrid.element);
  }

  /**
   * @override
   */
  wasShown() {
    this._dataGrid.wasShown();
  }

  /**
   * @override
   */
  willHide() {
    this._dataGrid.willHide();
  }

  /**
   * @override
   */
  onResize() {
    this._dataGrid.onResize();
  }

  /**
   * @override
   * @return {!Array.<!Element>}
   */
  elementsToRestoreScrollPositionsFor() {
    return [this._dataGrid._scrollContainer];
  }

  /**
   * @override
   */
  detachChildWidgets() {
    super.detachChildWidgets();
    for (const dataGrid of this._dataGrids) {
      this.element.removeChild(dataGrid.element);
    }
    this._dataGrids = [];
  }
}

/* Legacy exported object */
self.DataGrid = self.DataGrid || {};

/* Legacy exported object */
DataGrid = DataGrid || {};

/**
 * @typedef {{
 *   id: string,
 *   title: (string|undefined),
 *   titleDOMFragment: (?DocumentFragment|undefined),
 *   sortable: boolean,
 *   sort: (?Order|undefined),
 *   align: (?Align|undefined),
 *   fixedWidth: (boolean|undefined),
 *   editable: (boolean|undefined),
 *   nonSelectable: (boolean|undefined),
 *   longText: (boolean|undefined),
 *   disclosure: (boolean|undefined),
 *   weight: (number|undefined),
 *   allowInSortByEvenWhenHidden: (boolean|undefined)
 * }}
 */
DataGrid.ColumnDescriptor;

DataGrid._preferredWidthSymbol = Symbol('preferredWidth');
DataGrid._columnIdSymbol = Symbol('columnId');
DataGrid._sortIconSymbol = Symbol('sortIcon');
DataGrid._longTextSymbol = Symbol('longText');

/**
 * @unrestricted
 * @constructor
 */
DataGrid.DataGrid = DataGridImpl;

/**
 * @unrestricted
 * @constructor
 */
DataGrid.CreationDataGridNode = CreationDataGridNode;

/**
 * @unrestricted
 * @constructor
 */
DataGrid.DataGridNode = DataGridNode;
DataGrid.DataGridWidget = DataGridWidget;

/** @enum {symbol} */
DataGrid.DataGrid.Events = Events;

/** @enum {string} */
DataGrid.DataGrid.Order = Order;

/** @enum {string} */
DataGrid.DataGrid.Align = Align;

/** @enum {string} */
DataGrid.DataGrid.ResizeMethod = ResizeMethod;

/**
 * @typedef {{
  *   id: string,
  *   title: (string|undefined),
  *   titleDOMFragment: (?DocumentFragment|undefined),
  *   sortable: boolean,
  *   sort: (?Order|undefined),
  *   align: (?Align|undefined),
  *   fixedWidth: (boolean|undefined),
  *   editable: (boolean|undefined),
  *   nonSelectable: (boolean|undefined),
  *   longText: (boolean|undefined),
  *   disclosure: (boolean|undefined),
  *   weight: (number|undefined),
  *   allowInSortByEvenWhenHidden: (boolean|undefined)
  * }}
  */
DataGrid.DataGrid.ColumnDescriptor = DataGrid.ColumnDescriptor;
