// @flow
import React, { useState, useCallback, type Node } from 'react';
import styled from 'styled-components';
import { groupBy } from 'lodash';
import { action } from '@storybook/addon-actions';
import { SearchInput } from './search-input.component';
import { Box } from '../../../primitives';
import { Text } from '../../typography';
import { getPaletteColor } from '../../../mixins/branding';
import { MarginChecker } from '../../../mixins/spacing/story-support/margin-checker';
import { StackeeChecker } from '../../../mixins/stackee/story-support/stackee-checker';
import docs from './search-input.mdx';
import { Link } from '../../typography/link';

export default {
  component: SearchInput,
  title: 'Forms/SearchInput',
  parameters: {
    docs: {
      page: docs,
    },
  },
};

type SearchInputDemoProps = {|
  large?: boolean,
  bold?: boolean,
  hideLabel?: boolean,
  allowNotFound?: boolean,
  showNotFoundOnlyOnNoResults?: boolean,
  iconPosition?: string,
  notFoundText?: string,
  value?: string,
  initialValue?: string,
  focusOnMount?: boolean,
  renderItem?: ({
    id: string,
    text: string,
    isSeparator?: boolean,
    selected?: boolean,
  }) => Node,
  renderNotFoundItem?: () => Node,
  showSeparators?: boolean,
  clearSearchOnClick?: boolean,
|};
const SearchInputDemo = ({
  large = true,
  bold,
  hideLabel,
  allowNotFound = false,
  showNotFoundOnlyOnNoResults = false,
  iconPosition,
  notFoundText = '',
  value,
  initialValue,
  renderItem,
  renderNotFoundItem,
  focusOnMount = false,
  showSeparators = false,
  clearSearchOnClick = false,
}: SearchInputDemoProps) => {
  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 (
    <SearchInput
      value={value}
      initialValue={initialValue}
      iconPosition={iconPosition}
      placeholder="Placeholder"
      onChange={onDemoSearchInputChange}
      onSearchResultClicked={onDemoSearchResultClick}
      searchResults={search(demoSearchInput)}
      searchInput={demoSearchInput}
      large={large}
      bold={bold}
      allowNotFound={allowNotFound}
      showNotFoundOnlyOnNoResults={showNotFoundOnlyOnNoResults}
      hideLabel={hideLabel}
      notFoundText={notFoundText}
      label="Country search"
      renderItem={renderItem}
      renderNotFoundItem={renderNotFoundItem}
      focusOnMount={focusOnMount}
      clearSearchOnClick={clearSearchOnClick}
    />
  );
};

export const Default = () => <SearchInputDemo />;
export const InitialValue = () => <SearchInputDemo initialValue="Canada" />;

export const NotFoundButtonLarge = () => (
  <SearchInputDemo allowNotFound notFoundText="Can't find it?" />
);

export const NotFoundButtonSmall = () => (
  <SearchInputDemo
    allowNotFound
    large={false}
    bold
    notFoundText="Can't find it?"
  />
);

export const Small = () => <SearchInputDemo large={false} />;
export const SmallBold = () => <SearchInputDemo large={false} bold />;
export const NoLabel = () => <SearchInputDemo large={false} bold hideLabel />;

const HoverBox = styled(Box)`
  background: ${({ selected, theme }) =>
    selected
      ? getPaletteColor('brand-secondary-bg')({ theme })
      : getPaletteColor('white')({ theme })};

  &:hover,
  &:focus,
  &:active {
    background: ${getPaletteColor('brand-secondary-bg')};
    color: ${getPaletteColor('brand-secondary-bg')};
  }
`;

export const CustomItemRendererAndSeparators = () => (
  <SearchInputDemo
    showSeparators
    renderItem={({ id, text, selected }) => (
      <HoverBox selected={selected} spacing={['ph2', 'p1']}>
        <Text spacing="m0">ID: {id}</Text>
        <Text bold spacing="m0" fontSize="f4">
          {text}
        </Text>
      </HoverBox>
    )}
  />
);
export const CustomItemRendererAndSeparatorsSmall = () => (
  <SearchInputDemo
    large={false}
    showSeparators
    renderItem={({ id, text, selected }) => (
      <HoverBox
        selected={selected}
        spacing={['ph2', 'p1']}
        stacked="row"
        justify="space-between"
      >
        <Text spacing="m0">ID: {id}</Text>
        <Text bold spacing="m0" fontSize="f1">
          {text}
        </Text>
      </HoverBox>
    )}
  />
);

export const CustomNotFoundOnNoResults = () => {
  const NotFoundItem = (
    <Box stacked="column" spacing={['ph2', 'pv4']}>
      <Text spacing="m0" align="center">
        Can&apos;t find what you&apos;re looking for?
      </Text>
      <Text align="center">
        <Link
          colorName="brand-secondary-fg"
          onClick={action('findOutWhyClicked')}
        >
          Find out why
        </Link>
      </Text>
    </Box>
  );

  return (
    <SearchInputDemo
      allowNotFound
      large={false}
      bold
      showNotFoundOnlyOnNoResults
      renderNotFoundItem={() => NotFoundItem}
    />
  );
};

export const FocusOnMount = () => <SearchInputDemo focusOnMount large />;
export const ClearOnResultClick = () => <SearchInputDemo clearSearchOnClick />;

export const MixinsMarginOnlySpacing = () => (
  <MarginChecker
    Component={SearchInput}
    label="Find stuff"
    searchResults={[
      { id: 'country-can', text: 'Canada' },
      { id: 'country-usa', text: 'United States' },
    ]}
  />
);

export const MixinsStackee = () => (
  <StackeeChecker
    Component={SearchInput}
    label="Find stuff"
    searchResults={[
      { id: 'country-can', text: 'Canada' },
      { id: 'country-usa', text: 'United States' },
    ]}
  />
);
