import * as React from 'react';

export type ModalSelectorLayoutSingleProps = {
  /** OK button callback, called with the currently selected item  */
  onOk?: (selectedItem: ModalSelectorLayoutItem) => void;
  /** display checkbox and allow multi selection */
  multiple?: false;
};

export type ModalSelectorLayoutMultipleProps = {
  /** OK button callback, called with the currently selected item  */
  onOk?: (selectedItems: ModalSelectorLayoutItem[]) => void;
  /** display checkbox and allow multi selection */
  multiple: true;
};

export type ModalSelectorLayoutProps = ModalSelectorLayoutCommonProps &
  (ModalSelectorLayoutSingleProps | ModalSelectorLayoutMultipleProps);

export type ModalSelectorLayoutCommonProps = {
  /** applied as data-hook HTML attribute that can be used to create driver in testing */
  dataHook?: string;
  /** Title of the modal
   * @default 'Choose Your Items'
   */
  title?: React.ReactNode;
  /** Fixed text displayed above the list */
  subtitle?: React.ReactNode;
  /** X button callback */
  onClose?: React.MouseEventHandler<HTMLButtonElement>;
  /** Cancel button callback */
  onCancel?: React.MouseEventHandler<HTMLButtonElement>;
  /**
   * paging function that should have a signature of
   * ```typescript
   * (searchQuery: string, offset: number, limit: number) =>
   * Promise<{
   *  items: Array<{
   *    id: number | string,
   *    title: node,
   *    subtitle?: string,
   *    extraText?: string,
   *    extraNode?: node,
   *    disabled?: boolean // show item as disabled, dont count it in "select all", exclude from `onOk`
   *    selected?: boolean // force item as selected
   *    image?: node
   *    subtitleNode?: node,
   *    belowNode?: node,
   *    showBelowNodeOnSelect?: boolean,
   *  }>,
   *  totalCount: number
   * }>
   * ```
   * `offset` - next requested item's index<br>
   * `limit` - number of items requested<br>
   * `totalCount` - total number of items that suffice the current search query
   * */
  dataSource: ModalSelectorLayoutDatasourceFn;
  /** Cancel button's text
   * @default 'Cancel'
   */
  cancelButtonText?: string;
  /** OK button's text
   * @default 'Select'
   */
  okButtonText?: string;
  /** Image icon size
   * @default 'large'
   */
  imageSize?: ModalSelectorLayoutImageSize;
  /**
   * Image icon shape, `rectangular` or `circle`.<br>
   * NOTE: `circle` is not compatible with `imageSize` of `portrait` or `cinema`
   *
   * @default 'rectangular'
   */
  imageShape?: ModalSelectorLayoutImageShape;
  /** Placeholder text of the search input
   * @default 'Search...'
   */
  searchPlaceholder?: string;
  /**
   * Component/element that will be rendered when there is nothing to display,
   * i.e. empty `{items:[], totalCount: 0}` was returned on the first call to `dataSource`
   * */
  emptyState?: React.ReactNode;
  /**
   * Function that will get the current `searchQuery` and should return the component/element
   * that will be rendered when there are no items that suffice the entered search query
   *  */
  noResultsFoundStateFactory?: (searchValue: string) => React.ReactNode;
  /** Number of items loaded each time the user scrolls down
   * @default 50
   */
  itemsPerPage?: number;
  /** Whether to display the search input or not
   * @default true
   */
  withSearch?: boolean;
  /** Search debounce in milliseconds */
  searchDebounceMs?: number;
  /** Height CSS property, sets the height of the modal
   * @default '100%'
   */
  height?: string;
  /** Max-height CSS property, sets the maximum height of the modal.
   * @default '100%'
   */
  maxHeight?: string;
  /** string to be displayed in footer when `multiple` prop is used and no items are selected
   * @default 'Select All'
   */
  selectAllText?: string;
  /** string to be displayed in footer when `multiple` prop is used and some or all items ar selected
   * @default 'Deselect All'
   */
  deselectAllText?: string;
  /** to disable confirm button
   * @default false
   */
  disableConfirmation?: boolean;
  /** callback that triggers on select and return selected item object*/
  onSelect?: (item: ModalSelectorLayoutItem) => void;
  /** Used to display some side component in the footer.
   * Will override element select all in the footer when multiple=true */
  sideActions?: React.ReactNode;
};

export default class ModalSelectorLayout extends React.PureComponent<ModalSelectorLayoutProps> {}

export type ModalSelectorLayoutDatasourceFn = (
  searchQuery: string,
  offset: number,
  limit: number,
) => Promise<{ items: ModalSelectorLayoutItem[]; totalCount: number }>;

export interface ModalSelectorLayoutItem {
  id: number | string;
  /** Title of the modal
   * @default 'Choose Your Items'
   */
  title: React.ReactNode;
  /** Fixed text displayed above the list */
  subtitle?: string;
  extraText?: string;
  extraNode?: React.ReactNode;
  disabled?: boolean;
  selected?: boolean;
  image?: React.ReactNode;
  subtitleNode?: React.ReactNode;
  belowNode?: React.ReactNode;
  showBelowNodeOnSelect?: boolean;
}

export type ModalSelectorLayoutImageSize =
  | 'tiny'
  | 'small'
  | 'portrait'
  | 'large'
  | 'cinema';

export type ModalSelectorLayoutImageShape = 'rectangular' | 'circle';
