interface SelectionStateHolder<T> {
  lists: T[]
  selectedItems: number[]
}

type GetItemIdFn<T> = (item: T) => number

/**
 * Returns true when every item currently in `lists` is present in
 * `selectedItems`. Used by the "select-all" checkbox indicator.
 *
 * @since 1.0.4
 */
export function isAllSelected<T>(component: SelectionStateHolder<T>, getItemId: GetItemIdFn<T>): boolean {
  return component.lists.length > 0 && component.lists.every((item) => component.selectedItems.includes(getItemId(item)))
}

/**
 * Toggle the "select all" checkbox: clears the selection if everything is
 * currently selected, otherwise selects every item in the current list view.
 *
 * @since 1.0.4
 */
export function toggleAllSelection<T>(component: SelectionStateHolder<T>, getItemId: GetItemIdFn<T>): void {
  if (isAllSelected(component, getItemId)) {
    component.selectedItems = []
  } else {
    component.selectedItems = component.lists.map((item) => getItemId(item))
  }
}

/**
 * Toggle a single item's selection state by its id.
 *
 * @since 1.0.4
 */
export function toggleItemSelection(component: { selectedItems: number[] }, itemId: number): void {
  const index = component.selectedItems.indexOf(itemId)
  if (index === -1) {
    component.selectedItems = [...component.selectedItems, itemId]
  } else {
    component.selectedItems = component.selectedItems.filter((id) => id !== itemId)
  }
}
