// 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 {Icons} from '../base/semantic_icons';

import {Button} from './button';
import {Checkbox} from './checkbox';
import {EmptyState} from './empty_state';
import {Popup, PopupPosition} from './popup';
import {scheduleFullRedraw} from './raf';
import {TextInput} from './text_input';

export interface Option {
  // The ID is used to indentify this option, and is used in callbacks.
  id: string;
  // This is the name displayed and used for searching.
  name: string;
  // Whether the option is selected or not.
  checked: boolean;
}

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

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

export type PopupMultiSelectAttrs = MultiSelectAttrs & {
  minimal?: boolean;
  compact?: boolean;
  icon?: string;
  label: string;
  popupPosition?: 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;

    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 renderListOfItems(attrs: MultiSelectAttrs, options: Option[]) {
    const {repeatCheckedItemsAtTop, onChange = () => {}} = 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,
                  minimal: true,
                  onclick: () => {
                    const diffs = options
                      .filter(({checked}) => checked)
                      .map(({id}) => ({id, checked: false}));
                    onChange(diffs);
                    scheduleFullRedraw();
                  },
                  disabled: !anyChecked,
                }),
              ),
              this.renderOptions(
                attrs,
                options.filter(({checked}) => checked),
              ),
            ),
          m(
            '.pf-multiselect-container',
            m(
              '.pf-multiselect-header',
              m(
                'span',
                this.searchText === '' ? 'Options' : `Options (Filtered)`,
              ),
              m(Button, {
                label:
                  this.searchText === '' ? 'Select All' : 'Select Filtered',
                icon: Icons.SelectAll,
                minimal: true,
                compact: true,
                onclick: () => {
                  const diffs = options
                    .filter(({checked}) => !checked)
                    .map(({id}) => ({id, checked: true}));
                  onChange(diffs);
                  scheduleFullRedraw();
                },
                disabled: allChecked,
              }),
              m(Button, {
                label: this.searchText === '' ? 'Clear All' : 'Clear Filtered',
                icon: Icons.Deselect,
                minimal: true,
                compact: true,
                onclick: () => {
                  const diffs = options
                    .filter(({checked}) => checked)
                    .map(({id}) => ({id, checked: false}));
                  onChange(diffs);
                  scheduleFullRedraw();
                },
                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;
          scheduleFullRedraw();
        },
        value: this.searchText,
        placeholder: 'Filter options...',
        className: 'pf-search-box',
      }),
      this.renderClearButton(),
    );
  }

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

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

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

// 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, popupPosition = PopupPosition.Auto, minimal, compact} = attrs;

    return m(
      Popup,
      {
        trigger: m(Button, {
          label: this.labelText(attrs),
          icon,
          minimal,
          compact,
        }),
        position: popupPosition,
      },
      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;
    }
  }
}
