// Copyright (C) 2024 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import m from 'mithril';
import {Trash} from '../base/disposable';
import {findRef, toHTMLElement} from '../base/dom_utils';
import {Rect} from '../base/geom';
import {assertExists} from '../base/logging';
import {Style} from './common';
import {scheduleFullRedraw} from './raf';
import {VirtualScrollHelper} from './virtual_scroll_helper';

/**
 * The |VirtualTable| widget can be useful when attempting to render a large
 * amount of tabular data - i.e. dumping the entire contents of a database
 * table.
 *
 * A naive approach would be to load the entire dataset from the table and
 * render it into the DOM. However, this has a number of disadvantages:
 * - The query could potentially be very slow on large enough datasets.
 * - The amount of data pulled could be larger than the available memory.
 * - Rendering thousands of DOM elements using Mithril can get be slow.
 * - Asking the browser to create and update thousands of elements on the DOM
 *   can also be slow.
 *
 * This implementation takes advantage of the fact that computer monitors are
 * only so tall, so most will only be able to display a small subset of rows at
 * a given time, and the user will have to scroll to reveal more data.
 *
 * Thus, this widgets operates in such a way as to only render the DOM elements
 * that are visible within the given scrolling container's viewport. To avoid
 * spamming render updates, we render a few more rows above and below the
 * current viewport, and only trigger an update once the user scrolls too close
 * to the edge of the rendered data. These margins and tolerances are
 * configurable with the |renderOverdrawPx| and |renderTolerancePx| attributes.
 *
 * When it comes to loading data, it's often more performant to run fewer large
 * queries compared to more frequent smaller queries. Running a new query every
 * time we want to update the DOM is usually too frequent, and results in
 * flickering as the data is usually not loaded at the time the relevant row
 * scrolls into view.
 *
 * Thus, this implementation employs two sets of limits, one to refresh the DOM
 * and one larger one to re-query the data. The latter may be configured using
 * the |queryOverdrawPx| and |queryTolerancePx| attributes.
 *
 * The smaller DOM refreshes and handled internally, but the user must be called
 * to invoke a new query update. When new data is required, the |onReload|
 * callback is called with the row offset and count.
 *
 * The data must be passed in the |data| attribute which contains the offset of
 * the currently loaded data and a number of rows.
 *
 * Row and column content is flexible as m.Children are accepted and passed
 * straight to mithril.
 *
 * The widget is quite opinionated in terms of its styling, but the entire
 * widget and each row may be tweaked using |className| and |style| attributes
 * which behave in the same way as they do on other Mithril components.
 */

export interface VirtualTableAttrs {
  // A list of columns containing the header row content and column widths
  columns: VirtualTableColumn[];

  // Row height in px (each row must have the same height)
  rowHeight: number;

  // Offset of the first row
  firstRowOffset: number;

  // Total number of rows
  numRows: number;

  // The row data to render
  rows: VirtualTableRow[];

  // Optional: Called when we need to reload data
  onReload?: (rowOffset: number, rowCount: number) => void;

  // Additional class name applied to the table container element
  className?: string;

  // Additional styles applied to the table container element
  style?: Style;

  // Optional: Called when a row is hovered, passing the hovered row's id
  onRowHover?: (id: number) => void;

  // Optional: Called when a row is un-hovered, passing the un-hovered row's id
  onRowOut?: (id: number) => void;

  // Optional: Number of pixels equivalent of rows to overdraw above and below
  // the viewport
  // Defaults to a sensible value
  renderOverdrawPx?: number;

  // Optional: How close we can get to the edge before triggering a DOM redraw
  // Defaults to a sensible value
  renderTolerancePx?: number;

  // Optional: Number of pixels equivalent of rows to query above and below the
  // viewport
  // Defaults to a sensible value
  queryOverdrawPx?: number;

  // Optional: How close we can get to the edge if the loaded data before we
  // trigger another query
  // Defaults to a sensible value
  queryTolerancePx?: number;
}

export interface VirtualTableColumn {
  // Content to render in the header row
  header: m.Children;

  // CSS width e.g. 12px, 4em, etc...
  width: string;
}

export interface VirtualTableRow {
  // Id for this row (must be unique within this dataset)
  // Used for callbacks and as a Mithril key.
  id: number;

  // Data for each column in this row - must match number of elements in columns
  cells: m.Children[];

  // Optional: Additional class name applied to the row element
  className?: string;
}

export class VirtualTable implements m.ClassComponent<VirtualTableAttrs> {
  private readonly CONTAINER_REF = 'CONTAINER';
  private readonly SLIDER_REF = 'SLIDER';
  private readonly trash = new Trash();
  private renderBounds = {rowStart: 0, rowEnd: 0};

  view({attrs}: m.Vnode<VirtualTableAttrs>): m.Children {
    const {columns, className, numRows, rowHeight, style} = attrs;
    return m(
      '.pf-vtable',
      {className, style, ref: this.CONTAINER_REF},
      m(
        '.pf-vtable-content',
        m(
          '.pf-vtable-header',
          columns.map((col) =>
            m('.pf-vtable-data', {style: {width: col.width}}, col.header),
          ),
        ),
        m(
          '.pf-vtable-slider',
          {ref: this.SLIDER_REF, style: {height: `${rowHeight * numRows}px`}},
          m(
            '.pf-vtable-puck',
            {
              style: {
                transform: `translateY(${
                  this.renderBounds.rowStart * rowHeight
                }px)`,
              },
            },
            this.renderContent(attrs),
          ),
        ),
      ),
    );
  }

  private renderContent(attrs: VirtualTableAttrs): m.Children {
    const rows: m.ChildArray = [];
    for (
      let i = this.renderBounds.rowStart;
      i < this.renderBounds.rowEnd;
      ++i
    ) {
      rows.push(this.renderRow(attrs, i));
    }
    return rows;
  }

  private renderRow(attrs: VirtualTableAttrs, i: number): m.Children {
    const {rows, firstRowOffset, rowHeight, columns, onRowHover, onRowOut} =
      attrs;
    if (i >= firstRowOffset && i < firstRowOffset + rows.length) {
      // Render the row...
      const index = i - firstRowOffset;
      const rowData = rows[index];
      return m(
        '.pf-vtable-row',
        {
          className: rowData.className,
          style: {height: `${rowHeight}px`},
          onmouseover: () => {
            onRowHover?.(rowData.id);
          },
          onmouseout: () => {
            onRowOut?.(rowData.id);
          },
        },
        rowData.cells.map((data, colIndex) =>
          m('.pf-vtable-data', {style: {width: columns[colIndex].width}}, data),
        ),
      );
    } else {
      // Render a placeholder div with the same height as a row but a
      // transparent background
      return m('', {style: {height: `${rowHeight}px`}});
    }
  }

  oncreate({dom, attrs}: m.VnodeDOM<VirtualTableAttrs>) {
    const {
      renderOverdrawPx = 200,
      renderTolerancePx = 100,
      queryOverdrawPx = 10_000,
      queryTolerancePx = 5_000,
    } = attrs;

    const sliderEl = toHTMLElement(assertExists(findRef(dom, this.SLIDER_REF)));
    const containerEl = assertExists(findRef(dom, this.CONTAINER_REF));
    const virtualScrollHelper = new VirtualScrollHelper(sliderEl, containerEl, [
      {
        overdrawPx: renderOverdrawPx,
        tolerancePx: renderTolerancePx,
        callback: ({top, bottom}: Rect) => {
          const height = bottom - top;
          const rowStart = Math.floor(top / attrs.rowHeight / 2) * 2;
          const rowCount = Math.ceil(height / attrs.rowHeight / 2) * 2;
          this.renderBounds = {rowStart, rowEnd: rowStart + rowCount};
          scheduleFullRedraw();
        },
      },
      {
        overdrawPx: queryOverdrawPx,
        tolerancePx: queryTolerancePx,
        callback: ({top, bottom}: Rect) => {
          const rowStart = Math.floor(top / attrs.rowHeight / 2) * 2;
          const rowEnd = Math.ceil(bottom / attrs.rowHeight);
          attrs.onReload?.(rowStart, rowEnd - rowStart);
        },
      },
    ]);
    this.trash.add(virtualScrollHelper);
  }

  onremove(_: m.VnodeDOM<VirtualTableAttrs>) {
    this.trash.dispose();
  }
}
