import { LocationDescriptor } from 'history';
import React, { ForwardedRef } from 'react';
import { noop } from '../../../helpers/utils';
import { Data } from '../../../types/data';
import { ActionData } from '../../Actions/Actions.models';
import { IconName } from '../../Icons';
import { ListSelectMode } from '../../List';
import { Explorer, ExplorerProps } from '../Explorer';
import {
  ExplorerBulkAction,
  ExplorerDataProviderConnection,
  ItemSelection,
} from '../Explorer.model';

export interface SelectionExplorerProps<T extends Data>
  extends Omit<
    ExplorerProps<T>,
    | 'selectionMode'
    | 'onItemClicked'
    | 'onBulkActionsToggled'
    | 'bulkActions'
    | 'setTabTitle'
  > {
  /** Whether or not the selection of multiple items is allowed (default: false) */
  allowBulkSelect?: boolean;

  /**
   * Callback called when the user finished the selection.
   * The selected item (or items) will be passed as argument to the callback.
   */
  onSelection?: (selection: ItemSelection<T>) => void;

  /** When set, this function is used to generate inline menu link that navigates user to details page for each item. */
  generateItemLink?: (data: T) => LocationDescriptor<unknown>;
}

/**
 * Selection Explorer
 * @example
 * <SelectionExplorer<DataInterface>
 *  title="Title"
 *  columns={[{propertyName: 'id', size: '1fr', label: 'Id'}]}
 *  stationKey="station-key"
 *  dataProvider={dataProvider}
 * />
 */
export const SelectionExplorer = React.forwardRef(function SelectionExplorer<
  T extends Data,
>(
  { generateItemLink, inlineMenuActions, ...rest }: SelectionExplorerProps<T>,
  ref: ForwardedRef<ExplorerDataProviderConnection<T>>,
): JSX.Element {
  const {
    allowBulkSelect = false,
    onSelection = noop,
    modalMode = true,
  } = rest;

  const onItemClickedHandler = (item: T, mode?: ListSelectMode): void => {
    // only if the list is not in Multi mode is this executed
    if (mode !== ListSelectMode.Multi) {
      onSelection({ mode: 'SINGLE_ITEMS', items: [item] });
    }
  };

  let selectionExplorerActions = inlineMenuActions;

  if (generateItemLink) {
    selectionExplorerActions = (data: T): ActionData[] => {
      return [
        ...(inlineMenuActions?.(data) ?? []),
        {
          label: 'Open Details',
          path: generateItemLink(data),
          openInNewTab: true,
        },
      ];
    };
  }

  return (
    <Explorer<T>
      {...rest}
      ref={ref}
      modalMode={modalMode}
      setTabTitle={false}
      bulkActions={[
        ...(allowBulkSelect
          ? [
              {
                label: 'Apply Selection',
                icon: IconName.Checkmark,
                onClick: ((arg: ItemSelection<T>) => {
                  onSelection(arg);
                }) as ExplorerBulkAction<T>['onClick'],
                showStartedNotification: false,
              },
            ]
          : []),
      ]}
      selectionMode={ListSelectMode.Single}
      onItemClicked={onItemClickedHandler}
      inlineMenuActions={selectionExplorerActions}
    />
  );
});
