import {Fragment, useState} from 'react';
import range from 'lodash/range';

import JSXNode from 'sentry/components/stories/jsxNode';
import Matrix from 'sentry/components/stories/matrix';
import SideBySide from 'sentry/components/stories/sideBySide';
import SizingWindow from 'sentry/components/stories/sizingWindow';
import type {TabListProps, TabsProps} from 'sentry/components/tabs';
import {TabList, TabPanels, Tabs} from 'sentry/components/tabs';
import storyBook from 'sentry/stories/storyBook';

export default storyBook(Tabs, story => {
  const TABS = [
    {key: 'one', label: 'One', content: 'This is the first Panel.'},
    {key: 'two', label: 'Two', content: 'This is the second panel'},
    {key: 'three', label: 'Three', content: 'This is the third panel'},
  ];

  story('Default', () => (
    <Fragment>
      <p>
        You should be using all of <JSXNode name="Tabs" />, <JSXNode name="TabList" />,{' '}
        <JSXNode name="TabList.Item" />, <JSXNode name="TabPanels" /> and
        <JSXNode name="TabPanels.Item" /> components.
      </p>
      <p>
        This will give you all kinds of accessibility and state tracking out of the box.
        But you will have to render all tab content, including hooks, upfront.
      </p>
      <SizingWindow>
        <Tabs>
          <TabList>
            {TABS.map(tab => (
              <TabList.Item key={tab.key}>{tab.label}</TabList.Item>
            ))}
          </TabList>
          <TabPanels>
            {TABS.map(tab => (
              <TabPanels.Item key={tab.key}>{tab.content}</TabPanels.Item>
            ))}
          </TabPanels>
        </Tabs>
      </SizingWindow>
    </Fragment>
  ));

  story('Items Overflow', () => {
    const tabs = range(65, 75).map(i => ({
      key: 'i' + i,
      label: String.fromCharCode(i, i, i, i),
      content: String.fromCharCode(i, i, i, i),
    }));
    return (
      <Fragment>
        <p>When there are many items, they will overflow into a dropdown menu.</p>
        <SizingWindow display="block" style={{height: '210px', width: '400px'}}>
          <Tabs defaultValue="two">
            <TabList>
              {tabs.map(tab => (
                <TabList.Item key={tab.key}>{tab.label}</TabList.Item>
              ))}
            </TabList>
          </Tabs>
        </SizingWindow>
      </Fragment>
    );
  });

  story('Default Value', () => (
    <Fragment>
      <p>
        Set <JSXNode name="Tabs" props={{defaultValue: String}} />
      </p>
      <SizingWindow>
        <Tabs defaultValue="two">
          <TabList>
            {TABS.map(tab => (
              <TabList.Item key={tab.key}>{tab.label}</TabList.Item>
            ))}
          </TabList>
          <TabPanels>
            {TABS.map(tab => (
              <TabPanels.Item key={tab.key}>{tab.content}</TabPanels.Item>
            ))}
          </TabPanels>
        </Tabs>
      </SizingWindow>
    </Fragment>
  ));

  story('Controlled Value', () => {
    const [selected, setSelected] = useState('two');
    return (
      <Fragment>
        <p>
          If you want to control the state of the tabs from outside, you can call{' '}
          <var>{'useState()'}</var> and set{' '}
          <JSXNode name="Tabs" props={{value: String, onChange: Function}} /> manually.
        </p>
        <p>
          This is useful if you want to detect button clicks and do something different.{' '}
          The <JSXNode name="Tabs" /> context wrapper is not required in this case.
        </p>
        <p>selected={selected}</p>
        <SizingWindow>
          <Tabs value={selected} onChange={setSelected}>
            <TabList>
              {TABS.map(tab => (
                <TabList.Item key={tab.key}>{tab.label}</TabList.Item>
              ))}
            </TabList>
            <TabPanels>
              {TABS.map(tab => (
                <TabPanels.Item key={tab.key}>{tab.content}</TabPanels.Item>
              ))}
            </TabPanels>
          </Tabs>
        </SizingWindow>
      </Fragment>
    );
  });

  story('Rendering', () => (
    <Matrix<TabsProps<string> & TabListProps>
      render={props => (
        <Tabs orientation={props.orientation}>
          <TabList hideBorder={props.hideBorder}>
            {TABS.map(tab => (
              <TabList.Item key={tab.key}>{tab.label}</TabList.Item>
            ))}
          </TabList>
          <TabPanels>
            {TABS.map(tab => (
              <TabPanels.Item key={tab.key}>{tab.content}</TabPanels.Item>
            ))}
          </TabPanels>
        </Tabs>
      )}
      propMatrix={{
        orientation: ['horizontal', 'vertical'],
        hideBorder: [false, true],
      }}
      selectedProps={['orientation', 'hideBorder']}
    />
  ));

  story('Disabled', () => (
    <SideBySide>
      <div>
        <p>
          Use <JSXNode name="Tabs" props={{disabled: true}} /> to disable everything.
        </p>
        <SizingWindow>
          <Tabs disabled>
            <TabList>
              {TABS.map(tab => (
                <TabList.Item key={tab.key}>{tab.label}</TabList.Item>
              ))}
            </TabList>
            <TabPanels>
              {TABS.map(tab => (
                <TabPanels.Item key={tab.key}>{tab.content}</TabPanels.Item>
              ))}
            </TabPanels>
          </Tabs>
        </SizingWindow>
      </div>
      <div>
        <p>
          Use <JSXNode name="TabList" props={{disabledKeys: Array}} /> to disable
          individual <JSXNode name="TabList.Item" /> children.
        </p>
        <SizingWindow>
          <Tabs>
            <TabList disabledKeys={['two']}>
              {TABS.map(tab => (
                <TabList.Item key={tab.key}>{tab.label}</TabList.Item>
              ))}
            </TabList>
            <TabPanels>
              {TABS.map(tab => (
                <TabPanels.Item key={tab.key}>{tab.content}</TabPanels.Item>
              ))}
            </TabPanels>
          </Tabs>
        </SizingWindow>
      </div>
    </SideBySide>
  ));
});