// Copyright (C) 2023 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use size 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 {allUnique, range} from '../../base/array_utils';
import {
  compareUniversal,
  comparingBy,
  ComparisonFn,
  SortableValue,
  SortDirection,
  withDirection,
} from '../../base/comparison_utils';
import {raf} from '../../core/raf_scheduler';
import {
  menuItem,
  PopupMenuButton,
  popupMenuIcon,
  PopupMenuItem,
} from '../popup_menu';

export interface ColumnDescriptorAttrs<T> {
  // Context menu items displayed on the column header.
  contextMenu?: PopupMenuItem[];

  // Unique column ID, used to identify which column is currently sorted.
  columnId?: string;

  // Sorting predicate: if provided, column would be sortable.
  ordering?: ComparisonFn<T>;

  // Simpler way to provide a sorting: instead of full predicate, the function
  // can map the row for "sorting key" associated with the column.
  sortKey?: (value: T) => SortableValue;
}

export class ColumnDescriptor<T> {
  name: string;
  render: (row: T) => m.Child;
  id: string;
  contextMenu?: PopupMenuItem[];
  ordering?: ComparisonFn<T>;

  constructor(
    name: string, render: (row: T) => m.Child,
    attrs?: ColumnDescriptorAttrs<T>) {
    this.name = name;
    this.render = render;
    this.id = attrs?.columnId === undefined ? name : attrs.columnId;

    if (attrs === undefined) {
      return;
    }

    if (attrs.sortKey !== undefined && attrs.ordering !== undefined) {
      throw new Error('only one way to order a column should be specified');
    }

    if (attrs.sortKey !== undefined) {
      this.ordering = comparingBy(attrs.sortKey, compareUniversal);
    }
    if (attrs.ordering !== undefined) {
      this.ordering = attrs.ordering;
    }
  }
}

export function numberColumn<T>(
  name: string, getter: (t: T) => number, contextMenu?: PopupMenuItem[]):
    ColumnDescriptor<T> {
  return new ColumnDescriptor<T>(name, getter, {contextMenu, sortKey: getter});
}

export function stringColumn<T>(
  name: string, getter: (t: T) => string, contextMenu?: PopupMenuItem[]):
    ColumnDescriptor<T> {
  return new ColumnDescriptor<T>(name, getter, {contextMenu, sortKey: getter});
}

export function widgetColumn<T>(
  name: string, getter: (t: T) => m.Child): ColumnDescriptor<T> {
  return new ColumnDescriptor<T>(name, getter);
}

interface SortingInfo<T> {
  columnId: string;
  direction: SortDirection;
  // TODO(ddrone): figure out if storing this can be avoided.
  ordering: ComparisonFn<T>;
}

// Encapsulated table data, that contains the input to be displayed, as well as
// some helper information to allow sorting.
export class TableData<T> {
  data: T[];
  private _sortingInfo?: SortingInfo<T>;
  private permutation: number[];

  constructor(data: T[]) {
    this.data = data;
    this.permutation = range(data.length);
  }

  * iterateItems(): Generator<T> {
    for (const index of this.permutation) {
      yield this.data[index];
    }
  }

  items(): T[] {
    return Array.from(this.iterateItems());
  }

  setItems(newItems: T[]) {
    this.data = newItems;
    this.permutation = range(newItems.length);
    if (this._sortingInfo !== undefined) {
      this.reorder(this._sortingInfo);
    }
    raf.scheduleFullRedraw();
  }

  resetOrder() {
    this.permutation = range(this.data.length);
    this._sortingInfo = undefined;
    raf.scheduleFullRedraw();
  }

  get sortingInfo(): SortingInfo<T>|undefined {
    return this._sortingInfo;
  }

  reorder(info: SortingInfo<T>) {
    this._sortingInfo = info;
    this.permutation.sort(withDirection(
      comparingBy((index: number) => this.data[index], info.ordering),
      info.direction));
    raf.scheduleFullRedraw();
  }
}

export interface TableAttrs<T> {
  data: TableData<T>;
  columns: ColumnDescriptor<T>[];
}

function directionOnIndex(
  columnId: string,
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  info?: SortingInfo<any>): SortDirection|undefined {
  if (info === undefined) {
    return undefined;
  }
  return info.columnId === columnId ? info.direction : undefined;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export class Table implements m.ClassComponent<TableAttrs<any>> {
  renderColumnHeader(
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    vnode: m.Vnode<TableAttrs<any>>, column: ColumnDescriptor<any>): m.Child {
    let currDirection: SortDirection|undefined = undefined;

    let items = column.contextMenu;
    if (column.ordering !== undefined) {
      const ordering = column.ordering;
      currDirection = directionOnIndex(column.id, vnode.attrs.data.sortingInfo);
      const newItems: PopupMenuItem[] = [];
      if (currDirection !== 'ASC') {
        newItems.push(menuItem('Sort ascending', () => {
          vnode.attrs.data.reorder(
            {columnId: column.id, direction: 'ASC', ordering});
        }));
      }
      if (currDirection !== 'DESC') {
        newItems.push(menuItem('Sort descending', () => {
          vnode.attrs.data.reorder({
            columnId: column.id,
            direction: 'DESC',
            ordering,
          });
        }));
      }
      if (currDirection !== undefined) {
        newItems.push(menuItem('Restore original order', () => {
          vnode.attrs.data.resetOrder();
        }));
      }
      items = [
        ...newItems,
        ...(items ?? []),
      ];
    }

    return m(
      'td', column.name, items === undefined ? null : m(PopupMenuButton, {
        icon: popupMenuIcon(currDirection),
        items,
      }));
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  checkValid(attrs: TableAttrs<any>) {
    if (!allUnique(attrs.columns.map((c) => c.id))) {
      throw new Error('column IDs should be unique');
    }
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  oncreate(vnode: m.VnodeDOM<TableAttrs<any>, this>) {
    this.checkValid(vnode.attrs);
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  onupdate(vnode: m.VnodeDOM<TableAttrs<any>, this>) {
    this.checkValid(vnode.attrs);
  }

  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  view(vnode: m.Vnode<TableAttrs<any>>): m.Child {
    const attrs = vnode.attrs;

    return m(
      'table.generic-table',
      m('thead',
        m('tr.header',
          attrs.columns.map(
            (column) => this.renderColumnHeader(vnode, column)))),
      attrs.data.items().map(
        (row) =>
          m('tr',
            attrs.columns.map((column) => m('td', column.render(row))))));
  }
}
