// 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 './multiselect.scss';
import m from 'mithril';
import {Icons} from '../base/semantic_icons';
import {Button, type ButtonVariant} from './button';
import {Checkbox} from './checkbox';
import {EmptyState} from './empty_state';
import {Popup, PopupPosition} from './popup';
import {TextInput} from './text_input';
import type {Intent} from './common';

export interface MultiSelectOption {
  // The ID is used to indentify this option, and is used in callbacks.
  id: string;
  // This is the name used for searching, and displayed if `label` is not
  // provided.
  name: string;
  // Whether the option is selected or not.
  checked: boolean;
  // If provided, this is used as checkbox the label.
  label?: m.Children;
  // Optional details that are shown on hover.
  details?: string;
}

export interface MultiSelectDiff {
  id: string;
  checked: boolean;
}

export interface MultiSelectAttrs {
  options: MultiSelectOption[];
  onChange?: (diffs: MultiSelectDiff[]) => void;
  repeatCheckedItemsAtTop?: boolean;
  showNumSelected?: boolean;
  fixedSize?: boolean;
  readonly showSelectAllButton?: boolean;
}

export type PopupMultiSelectAttrs = MultiSelectAttrs & {
  readonly intent?: Intent;
  readonly compact?: boolean;
  readonly icon?: string;
  readonly label: string;
  readonly variant?: ButtonVariant;
  readonly position?: PopupPosition;
};

// A component which shows a list of items with checkboxes, allowing the user to
// select from the list which ones they want to be selected.
// Also provides search functionality.
// This component is entirely controlled and callbacks must be supplied for when
// the selected items list changes, and when the search term changes.
// There is an optional boolean flag to enable repeating the selected items at
// the top of the list for easy access - defaults to false.
export class MultiSelect implements m.ClassComponent<MultiSelectAttrs> {
  private searchText: string = '';

  view({attrs}: m.CVnode<MultiSelectAttrs>) {
    const {options, fixedSize = true} = attrs;
    this.validateOptions(options);

    const filteredItems = options.filter(({name}) => {
      return name.toLowerCase().includes(this.searchText.toLowerCase());
    });

    return m(
      fixedSize
        ? '.pf-multiselect-panel.pf-multi-select-fixed-size'
        : '.pf-multiselect-panel',
      this.renderSearchBox(),
      this.renderListOfItems(attrs, filteredItems),
    );
  }

  private validateOptions(options: MultiSelectOption[]) {
    const ids = new Set<string>();
    for (const option of options) {
      if (ids.has(option.id)) {
        throw new Error(`Duplicate option ID: ${option.id}`);
      }
      ids.add(option.id);
    }
  }

  private renderListOfItems(
    attrs: MultiSelectAttrs,
    options: MultiSelectOption[],
  ) {
    const {
      repeatCheckedItemsAtTop,
      onChange = () => {},
      showSelectAllButton = true,
    } = attrs;
    const allChecked = options.every(({checked}) => checked);
    const anyChecked = options.some(({checked}) => checked);

    if (options.length === 0) {
      return m(EmptyState, {
        title: `No results for '${this.searchText}'`,
      });
    } else {
      return [
        m(
          '.pf-list',
          repeatCheckedItemsAtTop &&
            anyChecked &&
            m(
              '.pf-multiselect-container',
              m(
                '.pf-multiselect-header',
                m(
                  'span',
                  this.searchText === '' ? 'Selected' : `Selected (Filtered)`,
                ),
                m(Button, {
                  label:
                    this.searchText === '' ? 'Clear All' : 'Clear Filtered',
                  icon: Icons.Deselect,
                  onclick: () => {
                    const diffs = options
                      .filter(({checked}) => checked)
                      .map(({id}) => ({id, checked: false}));
                    onChange(diffs);
                  },
                  disabled: !anyChecked,
                }),
              ),
              this.renderOptions(
                attrs,
                options.filter(({checked}) => checked),
              ),
            ),
          m(
            '.pf-multiselect-container',
            m(
              '.pf-multiselect-header',
              m(
                'span',
                this.searchText === '' ? 'Options' : `Options (Filtered)`,
              ),
              showSelectAllButton &&
                m(Button, {
                  label:
                    this.searchText === '' ? 'Select All' : 'Select Filtered',
                  icon: Icons.SelectAll,
                  compact: true,
                  onclick: () => {
                    const diffs = options
                      .filter(({checked}) => !checked)
                      .map(({id}) => ({id, checked: true}));
                    onChange(diffs);
                  },
                  disabled: allChecked,
                }),
              m(Button, {
                label: this.searchText === '' ? 'Clear All' : 'Clear Filtered',
                icon: Icons.Deselect,
                compact: true,
                onclick: () => {
                  const diffs = options
                    .filter(({checked}) => checked)
                    .map(({id}) => ({id, checked: false}));
                  onChange(diffs);
                },
                disabled: !anyChecked,
              }),
            ),
            this.renderOptions(attrs, options),
          ),
        ),
      ];
    }
  }

  private renderSearchBox() {
    return m(
      '.pf-search-bar',
      m(TextInput, {
        oninput: (event: Event) => {
          const eventTarget = event.target as HTMLTextAreaElement;
          this.searchText = eventTarget.value;
        },
        leftIcon: Icons.Search,
        value: this.searchText,
        placeholder: 'Filter options...',
        className: 'pf-search-box',
      }),
      this.renderClearButton(),
    );
  }

  private renderClearButton() {
    if (this.searchText != '') {
      return m(Button, {
        onclick: () => {
          this.searchText = '';
        },
        label: '',
        icon: 'close',
      });
    } else {
      return null;
    }
  }

  private renderOptions(attrs: MultiSelectAttrs, options: MultiSelectOption[]) {
    const {onChange = () => {}} = attrs;

    return options.map((item) => {
      const {checked, name, label, details, id} = item;
      return m(Checkbox, {
        label: label != undefined ? label : name,
        key: id, // Prevents transitions jumping between items when searching
        checked,
        className: 'pf-multiselect-item',
        onchange: () => {
          onChange([{id, checked: !checked}]);
        },
        title: details,
      });
    });
  }
}

// The same multi-select component that functions as a drop-down instead of
// a list.
export class PopupMultiSelect
  implements m.ClassComponent<PopupMultiSelectAttrs>
{
  view({attrs}: m.CVnode<PopupMultiSelectAttrs>) {
    const {
      icon,
      position = PopupPosition.Auto,
      intent,
      compact,
      variant,
    } = attrs;

    return m(
      Popup,
      {
        trigger: m(Button, {
          label: this.labelText(attrs),
          icon,
          intent,
          compact,
          variant,
        }),
        position,
      },
      m(MultiSelect, attrs as MultiSelectAttrs),
    );
  }

  private labelText(attrs: PopupMultiSelectAttrs): string {
    const {options, showNumSelected, label} = attrs;

    if (showNumSelected) {
      const numSelected = options.filter(({checked}) => checked).length;
      return `${label} (${numSelected} selected)`;
    } else {
      return label;
    }
  }
}
