import Dropdown from "../Dropdown";
import { useCallback, useMemo, useRef, useState } from "react";
import { ArgsTable, Canvas, Meta, Story } from "@storybook/addon-docs";
import { createStoryMetaSettings, Link } from "../../../storybook";
import {
  COMBOBOX,
  MENU,
  SPLIT_BUTTON
} from "../../../storybook/components/related-components/component-description-map";
import { overviewPlaySuite } from "../__tests__/Dropdown.interactions";
import Label from "../../Label/Label";
import person1 from "./assets/person1.png";
import person3 from "./assets/person3.png";
import person2 from "./assets/person2.png";
import Avatar from "../../Avatar/Avatar";
import { OptionRenderer } from "./OptionRenderer.js";
import Flex from "../../Flex/Flex";
import { StoryDescription } from "../../../storybook/components/story-description/story-description";
import { Attach, Email } from "../../Icon/Icons";
import { DialogContentContainer } from "../../index";
import Dialog from "../../Dialog/Dialog";
import Button from "../../Button/Button";
import "./dropdown.stories.scss";

export const metaSettings = createStoryMetaSettings({
  component: Dropdown,
  enumPropNamesArray: ["size"],
  actionPropsArray: [
    "onMenuOpen",
    "onMenuClose",
    "onFocus",
    "onBlur",
    "onChange",
    "openMenuOnFocus",
    "onOptionRemove",
    "onOptionSelect",
    "onClear",
    "onInputChange"
  ]
});

<Meta
  title="Inputs/Dropdown"
  component={Dropdown}
  argTypes={metaSettings.argTypes}
  decorators={metaSettings.decorators}
/>

<!--- Component template -->

export const dropdownTemplate = props => {
  const options = useMemo(
    () => [
      { value: 1, label: "Option 1" },
      { value: 2, label: "Option 2" },
      { value: 3, label: "Option 3" }
    ],
    []
  );
  return (
    <div style={{ height: "150px" }}>
      <Dropdown options={options} {...props} />
    </div>
  );
};

<!--- Component documentation -->

# Dropdown

- [Overview](#overview)
- [Props](#props)
- [Usage](#usage)
- [Variants](#variants)
- [Do’s and don’ts](#dos-and-donts)
- [Use cases and examples](#use-cases-and-examples)
- [Related components](#related-components)
- [Feedback](#feedback)

## Overview

Dropdown present a list of options from which a user can select one or several.

<Canvas>
  <Story
    name="Overview"
    args={{ placeholder: "Placeholder text here", className: "dropdown-stories-styles_spacing" }}
    play={overviewPlaySuite}
  >
    {dropdownTemplate.bind({})}
  </Story>
</Canvas>

## Props

<ArgsTable of={Dropdown} />

## Usage

<UsageGuidelines
  guidelines={[
    "Dropdown menus are typically used when you have 5-8 items to choose from. They're used for navigation or command menus, where an action is initiated based on the selection.",
    "Use a consistent size of form components on the same page. For example, if you are using a medium size dropdown also use the same size text inputs, buttons, and so on.",
    "Avoid having multiple lines of text in a dropdown. If the text is too long for one line, add an ellipsis (…).",
    "When the menu is open, each option in the menu should be the same height as the field.",
    "When organizing dropdown menu items, sort the list in a logical order by putting the most selected option at the top."
  ]}
/>

## Variants

### Sizes

There are three sizes available: Small, Medium, and Large

<Canvas>
  <Story name="Sizes">
    <Dropdown placeholder="Small" size={Dropdown.size.SMALL} className="dropdown-stories-styles_spacing" />
    <Dropdown placeholder="Medium" size={Dropdown.size.MEDIUM} className="dropdown-stories-styles_spacing" />
    <Dropdown placeholder="Large" size={Dropdown.size.LARGE} className="dropdown-stories-styles_spacing" />
  </Story>
</Canvas>

### Kinds

There are three sizes available: primary, secondary,tertiary

<Canvas>
  <Story name="Kinds">
    <Dropdown
      kind={Dropdown.kind.PRIMARY}
      placeholder="PRIMARY"
      size={Dropdown.size.LARGE}
      className="dropdown-stories-styles_spacing"
    />
    <Dropdown
      kind={Dropdown.kind.SECONDARY}
      placeholder="SECONDARY"
      size={Dropdown.size.LARGE}
      className="dropdown-stories-styles_spacing"
    />
    <Dropdown
      kind={Dropdown.kind.TERTIARY}
      placeholder="TERTIARY"
      size={Dropdown.size.LARGE}
      className="dropdown-stories-styles_spacing"
    />
  </Story>
</Canvas>

### Disabled

<Canvas>
  <Story name="Disabled">
    {() => {
      const options = useMemo(
        () => [
          { value: "1", label: "Option 1" },
          { value: "2", label: "Option 2" },
          { value: "3", label: "Option 3" }
        ],
        []
      );
      return (
        <Flex direction={Flex.directions.ROW}>
          <Dropdown
            defaultValue={[options[0]]}
            options={options}
            disabled
            className="dropdown-stories-styles_spacing"
          />
          <Dropdown
            multi
            defaultValue={[options[0], options[1]]}
            options={options}
            disabled
            className="dropdown-stories-styles_spacing"
          />
        </Flex>
      );
    }}
  </Story>
</Canvas>

### RTL

<Canvas>
  <Story name="RTL">
    <Dropdown placeholder="Left to right (default)" className="dropdown-stories-styles_spacing" />
    <Dropdown placeholder="מימין לשמאל" className="dropdown-stories-styles_spacing" rtl />
  </Story>
</Canvas>

### Multi line states

The Dropdown component supports multiple options selection in two different state - single line and multiple lines.

<Canvas>
  <Story name="Multi-choice with different states">
    {() => {
      const options = useMemo(
        () => [
          {
            value: "Rotem",
            label: "Rotem Dekel"
          },
          {
            value: "Hadas",
            label: "Hadas Farhi"
          },
          {
            value: "Netta",
            label: "Netta Muller"
          },
          {
            value: "Dor",
            label: "Dor Yehuda"
          }
        ],
        []
      );
      return (
        <Flex wrap gap={Flex.gaps.MEDIUM}>
          <StoryDescription description="Single line" vertical>
            <div style={{ width: "400px" }}>
              <Dropdown
                placeholder="Single line multi state"
                defaultValue={[options[0]]}
                options={options}
                multi
                className="dropdown-stories-styles_with-tags"
              />
            </div>
          </StoryDescription>
          <StoryDescription description="Multiple lines" vertical>
            <div style={{ width: "400px" }}>
              <Dropdown
                placeholder="Multiple line multi state"
                defaultValue={[options[0]]}
                options={options}
                multi
                multiline
                className="dropdown-stories-styles_with-tags"
              />
            </div>
          </StoryDescription>
          <StoryDescription description="Mandatory default values" vertical>
            <div style={{ width: "400px" }}>
              <Dropdown
                defaultValue={[options[0]]}
                options={options}
                multi
                multiline
                className="dropdown-stories-styles_with-tags"
                withMandatoryDefaultOptions
              />
            </div>
          </StoryDescription>
        </Flex>
      );
    }}
  </Story>
</Canvas>

### Dropdown with avatar

<Canvas>
  <Story name="Dropdown with avatar">
    {() => {
      const optionsAvatar = useMemo(
        () => [
          {
            value: "Rotem",
            label: "Rotem Dekel",
            leftAvatar: person1
          },
          {
            value: "Hadas",
            label: "Hadas Farhi",
            leftAvatar: person2
          },
          {
            value: "Netta",
            label: "Netta Muller",
            leftAvatar: person3
          }
        ],
        []
      );
      return (
        <Flex gap={Flex.gaps.SMALL}>
          <StoryDescription vertical description="Single value">
            <div>
              <Dropdown
                defaultValue={[optionsAvatar[0]]}
                options={optionsAvatar}
                className="dropdown-stories-styles_with-tags"
              />
            </div>
          </StoryDescription>
          <StoryDescription vertical description="Multiple values">
            <div>
              <Dropdown
                defaultValue={[optionsAvatar[0]]}
                options={optionsAvatar}
                multi
                multiline
                className="dropdown-stories-styles_with-tags"
              />
            </div>
          </StoryDescription>
        </Flex>
      );
    }}
  </Story>
</Canvas>

### Dropdown with icon

<Canvas>
  <Story name="Dropdown with icon">
    {() => {
      const optionsIcons = useMemo(
        () => [
          {
            value: "email",
            label: "Email",
            leftIcon: Email
          },
          {
            value: "attach",
            label: "Attach",
            leftIcon: Attach
          }
        ],
        []
      );
      return (
        <Flex gap={Flex.gaps.SMALL}>
          <StoryDescription vertical description="Single value">
            <div>
              <Dropdown
                defaultValue={[optionsIcons[0]]}
                options={optionsIcons}
                className="dropdown-stories-styles_with-tags"
              />
            </div>
          </StoryDescription>
          <StoryDescription vertical description="Multiple values">
            <div>
              <Dropdown
                defaultValue={[optionsIcons[0]]}
                options={optionsIcons}
                multi
                multiline
                className="dropdown-stories-styles_with-tags"
              />
            </div>
          </StoryDescription>
        </Flex>
      );
    }}
  </Story>
</Canvas>

### Dropdown with tag colors

<Canvas>
  <Story name="Dropdown with tag colors">
    {() => {
      const optionsWithTagColors = useMemo(
        () => [
          {
            value: "Rotem",
            label: "Rotem Dekel",
            tagColor: "white",
            outlined: true
          },
          {
            value: "Hadas",
            label: "Hadas Farhi",
            tagColor: "gradient_red"
          },
          {
            value: "Netta",
            label: "Netta Muller",
            tagColor: "gradient_orange"
          }
        ],
        []
      );
      return (
        <StoryDescription vertical>
          <div>
            <Dropdown
              defaultValue={[optionsWithTagColors[0]]}
              options={optionsWithTagColors}
              multi
              multiline
              className="dropdown-stories-styles_with-tags"
            />
          </div>
        </StoryDescription>
      );
    }}
  </Story>
</Canvas>

### Dropdown with tooltips on items

<Canvas>
  <Story name="Dropdown with tooltips on items">
    {() => {
      const optionsWithTooltips = useMemo(
        () => [
          {
            value: "Option 1",
            label: "Option 1",
            tooltipProps: { content: "Description for option 1" }
          },
          {
            value: "Option 2",
            label: "Option 2",
            tooltipProps: { content: "Description for option 2" }
          }
        ],
        []
      );
      return (
        <StoryDescription vertical>
          <div>
            <Dropdown
              placeholder={"Placeholder text here"}
              options={optionsWithTooltips}
              className="dropdown-stories-styles_with-tags"
            />
          </div>
        </StoryDescription>
      );
    }}
  </Story>
</Canvas>

## Do’s and Don’ts

<ComponentRules
  rules={[
    {
      positive: {
        component: (
          <Dropdown
            placeholder="Placeholder text here"
            options={[
              { value: 1, label: "Option 1" },
              { value: 2, label: "Option 2" },
              { value: 3, label: "Option 3" }
            ]}
            className="dropdown-stories-styles_rules-spacing"
          />
        ),
        description:
          "Use the dropdown as a closed component. Users should normally be allowed only to click on the items; search is not recommended, though possible."
      },
      negative: {
        component: (
          <Dropdown
            menuIsOpen
            placeholder="Placeholder text here"
            options={[
              { value: 1, label: "Option 1" },
              { value: 2, label: "Option 2" },
              { value: 3, label: "Option 3" }
            ]}
            className="dropdown-stories-styles_rules-spacing"
          />
        ),
        description: (
          <>
            Don't keep the dropdown component in open mode as permanent state. If this is a design requirement consider
            use{" "}
            <Link href="/?path=/docs/inputs-combobox--overview" withoutSpacing>
              Combo box
            </Link>{" "}
            instead.
          </>
        )
      }
    }
  ]}
/>

## Use cases and examples

### multiple drop down with renderers as options

Inside the advanced filters, a user can select multiple people from the dropdown menu, and they will be shown as Tags.

<Canvas>
  <Story name="Dropdown with tags">
    {() => {
      const options = useMemo(
        () => [
          {
            value: "Dor Yehuda",
            label: "Hadas Farhi",
            src: person1,
            type: Avatar.types.IMG,
            size: Avatar.sizes.SMALL,
            name: "Dor Yehuda",
            position: "(Full Stack Developer)"
          },
          {
            value: "No",
            label: "Rotem Dekel",
            src: person3,
            type: Avatar.types.IMG,
            size: Avatar.sizes.SMALL,
            name: "Rotem Dekel",
            position: "(Product Designer)"
          },
          {
            value: "Yes",
            label: "Netta Muller",
            src: person2,
            type: Avatar.types.IMG,
            size: Avatar.sizes.SMALL,
            name: "Netta Muller",
            position: "(Brand Designer)"
          }
        ],
        []
      );
      return (
        <Dropdown
          defaultValue={[options[0]]}
          options={options}
          multi
          placeholder="Dropdown with tags"
          optionRenderer={OptionRenderer}
          className="dropdown-stories-styles_with-tags"
          searchIcon
        />
      );
    }}
  </Story>
</Canvas>

### Searchable Dropdown

In case of multiple options, you can use the `onInputChange` prop to allow filtering options.

<Canvas>
  <Story name="Searchable dropdown">
    {() => {
      const [searchValue, setSearchValue] = useState("");
      const allOptions = useMemo(
        () => [
          { value: "Red", label: "Red" },
          { value: "Orange", label: "Orange" },
          { value: "Yellow", label: "Yellow" },
          { value: "Green", label: "Green" },
          { value: "Blue", label: "Blue" },
          { value: "Indigo", label: "Indigo" },
          { value: "Violet", label: "Violet" }
        ],
        []
      );
      const options = useMemo(() => {
        if (!searchValue) return allOptions;
        return allOptions.filter(option => option.label.toLowerCase().includes(searchValue.toLowerCase()));
      }, [allOptions, searchValue]);
      const onInputChange = value => setSearchValue(value);
      return (
        <Dropdown
          options={options}
          multi
          placeholder="Select colors"
          className="dropdown-stories-styles_with-tags"
          onInputChange={onInputChange}
        />
      );
    }}
  </Story>
</Canvas>

### Dropdown with lables

A dropdown menu can include labels.

<Canvas>
  <Story name="Dropdown with lables">
    {() => {
      const labelRenderer = useCallback(({ label, color }) => {
        return <Label text={label} color={color} isAnimationDisabled />;
      });
      const options = useMemo(
        () => [
          { value: "success", label: "Success", color: Label.colors.POSITIVE },
          { value: "failed", label: "Failed", color: Label.colors.NEGATIVE },
          { value: "in progress", label: "In progress" }
        ],
        []
      );
      return (
        <Dropdown
          placeholder="Placeholder text here"
          options={options}
          defaultValue={[options[0]]}
          placeholder="Placeholder text here"
          className="dropdown-stories-styles_big-spacing"
          optionRenderer={labelRenderer}
          valueRenderer={labelRenderer}
        />
      );
    }}
  </Story>
</Canvas>

### Dropdown inside a form

A classic dropdown presents options a user needs to choose from.

<Canvas>
  <Story name="Dropdown inside a form">
    {() => {
      const options = useMemo(
        () => [
          { value: "Sometimes", label: "Sometimes" },
          { value: "No", label: "No" },
          { value: "Yes", label: "Yes" }
        ],
        []
      );
      return (
        <div>
          <h5 className="dropdown-stories-styles_title">Are you usually a Dark mode person?</h5>
          <Dropdown
            defaultValue={[options[0]]}
            placeholder="Placeholder text here"
            options={options}
            className="dropdown-stories-styles_big-spacing"
          />
        </div>
      );
    }}
  </Story>
</Canvas>

### Dropdown with groups

Dropdown with group.

<Canvas>
  <Story name="Dropdown with groups">
    {() => {
      const options = useMemo(
        () => [
          {
            label: "Group 1",
            options: [
              { value: "1", label: "Option 1" },
              { value: "2", label: "Option 2" }
            ]
          },
          {
            label: "Group 2",
            options: [
              { value: "3", label: "Option 3" },
              { value: "4", label: "Option 4" }
            ]
          }
        ],
        []
      );
      return (
        <Dropdown
          placeholder="Placeholder text here"
          options={options}
          className="dropdown-stories-styles_big-spacing"
        />
      );
    }}
  </Story>
</Canvas>

### Dropdown inside scrollable dialog

Use <b>insideOverflowContainer</b> prop attribute for displaying dropdown inside scrollable container (like our modal
component) or container with overflow hidden content.
Use <b>insideOverflowWithTransformContainer</b> prop attribute for displaying drop down inside scrollable container which use CSS transform function (like our dialog component) or container
with overflow hidden content which use CSS transform function.

<Canvas>
  <Story name="Dropdown inside scrollable dialog">
    {() => {
      const options = useMemo(
        () => [
          { value: "1", label: "Option 1" },
          { value: "2", label: "Option 2" },
          { value: "3", label: "Option 3" },
          { value: "4", label: "Option 4" },
          { value: "5", label: "Option 5" }
        ],
        []
      );
      const dialogRef = useRef();
      const dialogStyle = { width: "300px", height: "200px", overflow: "auto" };
      const secondDialogContent = (
        <DialogContentContainer style={dialogStyle} ref={dialogRef}>
          <Dropdown
            placeholder="Dropdown inside a scrollable dialog"
            options={options}
            insideOverflowWithTransformContainer
          />
        </DialogContentContainer>
      );
      return (
        <Flex gap={Flex.gaps.LARGE}>
          <DialogContentContainer style={dialogStyle}>
            <Dropdown placeholder="Dropdown inside a scrollable dialog" options={options} insideOverflowContainer />
          </DialogContentContainer>
          <Dialog
            ref={dialogRef}
            content={secondDialogContent}
            hideTrigger={Dialog.hideShowTriggers.CLICK_OUTSIDE}
            showTrigger={Dialog.hideShowTriggers.CLICK}
          >
            <Button>Press me for dropdown inside dialog!</Button>
          </Dialog>
        </Flex>
      );
    }}
  </Story>
</Canvas>

## Related components

<RelatedComponents componentsNames={[COMBOBOX, SPLIT_BUTTON, MENU]} />
