// Copyright (C) 2023 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 {isString} from '../../base/object_utils';
import {Icons} from '../../base/semantic_icons';
import {EngineProxy} from '../../trace_processor/engine';
import {Row} from '../../trace_processor/query_result';
import {Anchor} from '../../widgets/anchor';
import {BasicTable} from '../../widgets/basic_table';
import {Button} from '../../widgets/button';
import {MenuDivider, MenuItem, PopupMenu2} from '../../widgets/menu';
import {Spinner} from '../../widgets/spinner';

import {ArgumentSelector} from './argument_selector';
import {argColumn, Column, columnFromSqlTableColumn} from './column';
import {renderCell} from './render_cell';
import {SqlTableState} from './state';
import {isArgSetIdColumn, SqlTableDescription} from './table_description';

export interface SqlTableConfig {
  readonly state: SqlTableState;
}

export class SqlTable implements m.ClassComponent<SqlTableConfig> {
  private readonly table: SqlTableDescription;
  private readonly engine: EngineProxy;

  private state: SqlTableState;

  constructor(vnode: m.Vnode<SqlTableConfig>) {
    this.state = vnode.attrs.state;
    this.table = this.state.table;
    this.engine = this.state.engine;
  }

  renderFilters(): m.Children {
    const filters: m.Child[] = [];
    for (const filter of this.state.getFilters()) {
      const label = isString(filter)
        ? filter
        : `Arg(${filter.argName}) ${filter.op}`;
      filters.push(
        m(Button, {
          label,
          icon: 'close',
          onclick: () => {
            this.state.removeFilter(filter);
          },
        }),
      );
    }
    return filters;
  }

  renderAddColumnOptions(addColumn: (column: Column) => void): m.Children {
    // We do not want to add columns which already exist, so we track the
    // columns which we are already showing here.
    // TODO(altimin): Theoretically a single table can have two different
    // arg_set_ids, so we should track (arg_set_id_column, arg_name) pairs here.
    const existingColumns = new Set<string>();

    for (const column of this.state.getSelectedColumns()) {
      existingColumns.add(column.alias);
    }

    const result = [];
    for (const column of this.table.columns) {
      if (existingColumns.has(column.name)) continue;
      if (isArgSetIdColumn(column)) {
        result.push(
          m(
            MenuItem,
            {
              label: column.name,
            },
            m(ArgumentSelector, {
              engine: this.engine,
              argSetId: column,
              tableName: this.table.name,
              constraints: this.state.getQueryConstraints(),
              alreadySelectedColumns: existingColumns,
              onArgumentSelected: (argument: string) => {
                addColumn(argColumn(this.table.name, column, argument));
              },
            }),
          ),
        );
        continue;
      }
      result.push(
        m(MenuItem, {
          label: column.name,
          onclick: () => addColumn(columnFromSqlTableColumn(column)),
        }),
      );
    }
    return result;
  }

  renderColumnHeader(column: Column, index: number) {
    const sorted = this.state.isSortedBy(column);
    const icon =
      sorted === 'ASC'
        ? Icons.SortedAsc
        : sorted === 'DESC'
        ? Icons.SortedDesc
        : Icons.ContextMenu;
    return m(
      PopupMenu2,
      {
        trigger: m(Anchor, {icon}, column.title),
      },
      sorted !== 'DESC' &&
        m(MenuItem, {
          label: 'Sort: highest first',
          icon: Icons.SortedDesc,
          onclick: () => {
            this.state.sortBy({column, direction: 'DESC'});
          },
        }),
      sorted !== 'ASC' &&
        m(MenuItem, {
          label: 'Sort: lowest first',
          icon: Icons.SortedAsc,
          onclick: () => {
            this.state.sortBy({column, direction: 'ASC'});
          },
        }),
      sorted !== undefined &&
        m(MenuItem, {
          label: 'Unsort',
          icon: Icons.Close,
          onclick: () => this.state.unsort(),
        }),
      this.state.getSelectedColumns().length > 1 &&
        m(MenuItem, {
          label: 'Hide',
          icon: Icons.Hide,
          onclick: () => this.state.hideColumnAtIndex(index),
        }),
      m(MenuDivider),
      m(
        MenuItem,
        {label: 'Add column', icon: Icons.AddColumn},
        this.renderAddColumnOptions((column) => {
          this.state.addColumn(column, index);
        }),
      ),
    );
  }

  view() {
    const rows = this.state.getDisplayedRows();

    return [
      m('div', this.renderFilters()),
      m(BasicTable, {
        data: rows,
        columns: this.state.getSelectedColumns().map((column, i) => ({
          title: this.renderColumnHeader(column, i),
          render: (row: Row) => renderCell(column, row, this.state),
        })),
      }),
      this.state.isLoading() && m(Spinner),
      this.state.getQueryError() !== undefined &&
        m('.query-error', this.state.getQueryError()),
    ];
  }
}

export {SqlTableDescription};
