// @flow
import React, { useState, useCallback, type Node } from 'react';
import { groupBy } from 'lodash';
import { storiesOf } from '@storybook/react';
import { action } from '@storybook/addon-actions';
import { withInfo } from '@storybook/addon-info';
import { SearchInput } from './index';
import { configDocs } from '../../../../.storybook/config-docs';
import docs from './SEARCH_INPUT.mkd';
import { Grid, GridItem } from '../..';
import { Text } from '../../typography';
import { Box } from '../../../primitives';

type SearchInputProps = {|
  large?: boolean,
  bold?: boolean,
  hideLabel?: boolean,
  allowNotFound?: boolean,
  iconPosition?: string,
  notFoundText?: string,
  value?: string,
  focusOnMount?: boolean,
  renderItem?: ({ id: string, text: string, isSeparator?: boolean }) => Node,
  showSeparators?: boolean,
  clearSearchOnClick?: boolean,
|};
const SearchInputDemo = ({
  large = true,
  bold,
  hideLabel,
  allowNotFound = false,
  iconPosition,
  notFoundText = '',
  value,
  renderItem,
  focusOnMount = false,
  showSeparators = false,
  clearSearchOnClick = false,
}: SearchInputProps) => {
  const [demoSearchInput, setDemoSearchInput] = useState();

  const onDemoSearchInputChange = useCallback((newSearchInput) => {
    action('Setting search term')(newSearchInput);
    setDemoSearchInput(newSearchInput);
  }, []);

  const onDemoSearchResultClick = useCallback((id, v) => {
    action('Clicked ID')(id);
    action('Setting value')(v);
  }, []);

  const countries = [
    { id: 'country-can', text: 'Canada', region: 'North America' },
    { id: 'country-usa', text: 'United States', region: 'North America' },
    { id: 'country-uae', text: 'United Arab Emirates', region: 'Middle East' },
    { id: 'country-fr', text: 'France', region: 'Europe' },
    { id: 'country-es', text: 'Spain', region: 'Europe' },
  ];

  const search = (searchTerm) => {
    if (searchTerm == null) {
      return [];
    }

    const regexp = new RegExp(searchTerm, 'gi');
    let results = countries.filter((country) => country.text.match(regexp));
    if (showSeparators) {
      const resultsByRegion = groupBy(results, 'region');
      results = [];
      Object.keys(resultsByRegion).forEach((key) => {
        const resultsForRegion = resultsByRegion[key] ?? [];
        if (resultsForRegion.length > 0) {
          results.push({ id: 'key', text: key, isSeparator: true });
          results.push(...resultsForRegion);
        }
      });
    }
    return results.map(({ id, text }) => ({ id, text }));
  };

  return (
    <Box spacing="pv5" colorName="background">
      <Grid>
        <GridItem sm={12} md={6} lg={4}>
          <SearchInput
            value={value}
            iconPosition={iconPosition}
            placeholder="Placeholder"
            onChange={onDemoSearchInputChange}
            onSearchResultClicked={onDemoSearchResultClick}
            searchResults={search(demoSearchInput)}
            searchInput={demoSearchInput}
            large={large}
            bold={bold}
            allowNotFound={allowNotFound}
            hideLabel={hideLabel}
            notFoundText={notFoundText}
            label="Country search"
            renderItem={renderItem}
            focusOnMount={focusOnMount}
            clearSearchOnClick={clearSearchOnClick}
          />
        </GridItem>
      </Grid>
    </Box>
  );
};

storiesOf('Core/Forms/SearchInput', module)
  .addDecorator(withInfo(configDocs(docs, SearchInput)))
  .add('normal', () => <SearchInputDemo />)
  .add('default value', () => <SearchInputDemo value="Canada" />)
  .add('with "Not Found" button (large)', () => (
    <SearchInputDemo allowNotFound notFoundText="Can't find it?" />
  ))
  .add('with "Not Found" button (small)', () => (
    <SearchInputDemo
      allowNotFound
      large={false}
      bold
      notFoundText="Can't find it?"
    />
  ))
  .add('small', () => <SearchInputDemo large={false} />)
  .add('small, bold', () => <SearchInputDemo large={false} bold />)
  .add('no label', () => <SearchInputDemo large={false} bold hideLabel />)
  .add('custom item renderer with separators', () => (
    <SearchInputDemo
      showSeparators
      renderItem={({ id, text }) => (
        <Box>
          <Text spacing="m0">ID: {id}</Text>
          <Text bold spacing="m0" fontSize="f4">
            {text}
          </Text>
        </Box>
      )}
    />
  ))
  .add('custom item renderer with separators (small)', () => (
    <SearchInputDemo
      large={false}
      showSeparators
      renderItem={({ id, text }) => (
        <Box>
          <Text spacing="m0">ID: {id}</Text>
          <Text bold spacing="m0" fontSize="f4">
            {text}
          </Text>
        </Box>
      )}
    />
  ))
  .add('focused on mount', () => <SearchInputDemo focusOnMount large />)
  .add('clear input on result click', () => (
    <SearchInputDemo clearSearchOnClick />
  ));
