// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import * as React from 'react';
import { mergeClasses } from "@coreai-ds/react-components";
import { Overflow } from "@coreai-ds/react-components";
import { TabList } from "@coreai-ds/react-components";
import { bundleIcon } from "@fluentui/react-icons";
import { CalendarTodayFilled } from "@fluentui/react-icons";
import { CalendarTodayRegular } from "@fluentui/react-icons";
import { CalendarAgendaFilled } from "@fluentui/react-icons";
import { CalendarAgendaRegular } from "@fluentui/react-icons";
import { CalendarDayFilled } from "@fluentui/react-icons";
import { CalendarDayRegular } from "@fluentui/react-icons";
import { Calendar3DayFilled } from "@fluentui/react-icons";
import { Calendar3DayRegular } from "@fluentui/react-icons";
import { CalendarWorkWeekFilled } from "@fluentui/react-icons";
import { CalendarWorkWeekRegular } from "@fluentui/react-icons";
import { CalendarWeekStartFilled } from "@fluentui/react-icons";
import { CalendarWeekStartRegular } from "@fluentui/react-icons";
import { CalendarMonthFilled } from "@fluentui/react-icons";
import { CalendarMonthRegular } from "@fluentui/react-icons";
import { CalendarSearchFilled } from "@fluentui/react-icons";
import { CalendarSearchRegular } from "@fluentui/react-icons";
import { CalendarChatFilled } from "@fluentui/react-icons";
import { CalendarChatRegular } from "@fluentui/react-icons";
import { OverflowItem } from "@coreai-ds/react-components";
import { Tab } from "@coreai-ds/react-components";
import { useOverflowMenu } from "@coreai-ds/react-components";
import { Menu } from "@coreai-ds/react-components";
import { MenuTrigger } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { MoreHorizontalFilled } from "@fluentui/react-icons";
import { MoreHorizontalRegular } from "@fluentui/react-icons";
import { MenuPopover } from "@coreai-ds/react-components";
import { MenuList } from "@coreai-ds/react-components";
import type { MenuItemProps } from "@coreai-ds/react-components";
import { useIsOverflowItemVisible } from "@coreai-ds/react-components";
import { MenuItem } from "@coreai-ds/react-components";

const useStyles = makeStyles({
    root: {
        alignItems: 'flex-start',
        display: 'flex',
        flexDirection: 'column',
        justifyContent: 'flex-start',
        overflow: 'auto',
        padding: '50px 20px',
        rowGap: '20px',
        minHeight: '600px', //lets the page remain at a minimum height when vertical tabs are resized
    },
});

//----- Stories -----//
const useExampleStyles = makeStyles({
    example: {
        backgroundColor: tokens.colorNeutralBackground2,
        overflow: 'hidden',
        padding: '5px',
        zIndex: 0, //stop the browser resize handle from piercing the overflow menu
    },
    horizontal: {
        height: 'fit-content',
        minWidth: '150px',
        resize: 'horizontal',
        width: '600px',
    },
    vertical: {
        height: '250px',
        minHeight: '100px',
        resize: 'vertical',
        width: 'fit-content',
        display: 'flex',
        alignContent: 'stretch',
        alignItems: 'stretch',
        justifyContent: 'stretch',
        justifyItems: 'stretch',
    },
});

//----- Example Tab Data -----//
type ExampleTab = {
    id: string;
    name: string;
    icon: React.ReactElement;
};

const CalendarToday = bundleIcon(CalendarTodayFilled, CalendarTodayRegular);

const CalendarAgenda = bundleIcon(CalendarAgendaFilled, CalendarAgendaRegular);

const CalendarDay = bundleIcon(CalendarDayFilled, CalendarDayRegular);

const Calendar3Day = bundleIcon(Calendar3DayFilled, Calendar3DayRegular);

const CalendarWorkWeek = bundleIcon(CalendarWorkWeekFilled, CalendarWorkWeekRegular);

const CalendarWeekStart = bundleIcon(CalendarWeekStartFilled, CalendarWeekStartRegular);

const CalendarMonth = bundleIcon(CalendarMonthFilled, CalendarMonthRegular);

const CalendarSearch = bundleIcon(CalendarSearchFilled, CalendarSearchRegular);

const CalendarChat = bundleIcon(CalendarChatFilled, CalendarChatRegular);

const tabs: ExampleTab[] = [
    {
        id: 'today',
        name: 'Today',
        icon: <CalendarToday />,
    },
    {
        id: 'agenda',
        name: 'Agenda',
        icon: <CalendarAgenda />,
    },
    {
        id: 'day',
        name: 'Day',
        icon: <CalendarDay />,
    },
    {
        id: 'threeDay',
        name: 'Three Day',
        icon: <Calendar3Day />,
    },
    {
        id: 'workWeek',
        name: 'Work Week',
        icon: <CalendarWorkWeek />,
    },
    {
        id: 'week',
        name: 'Week',
        icon: <CalendarWeekStart />,
    },
    {
        id: 'month',
        name: 'Month',
        icon: <CalendarMonth />,
    },
    {
        id: 'search',
        name: 'Search',
        icon: <CalendarSearch />,
    },
    {
        id: 'chat',
        name: 'Conversations',
        icon: <CalendarChat />,
    },
];

type OverflowMenuProps = {
    onTabSelect?: (tabId: string) => void;
};

//----- OverflowMenu -----//
const useOverflowMenuStyles = makeStyles({
    menu: {
        backgroundColor: tokens.colorNeutralBackground1,
    },
    menuButton: {
        alignSelf: 'center',
    },
});

const MoreHorizontal = bundleIcon(MoreHorizontalFilled, MoreHorizontalRegular);

//----- OverflowMenuItem -----//
type OverflowMenuItemProps = {
    tab: ExampleTab;
    onClick: MenuItemProps['onClick'];
};

/**
 * A menu item for an overflow menu that only displays when the tab is not visible
 */
const OverflowMenuItem = (props: OverflowMenuItemProps) => {
    const { tab, onClick } = props;
    const isVisible = useIsOverflowItemVisible(tab.id);
    if (isVisible) {
        return null;
    }
    return (<MenuItem key={tab.id} icon={tab.icon} onClick={onClick}>
      <div>{tab.name}</div>
    </MenuItem>);
};

/**
 * A menu for selecting tabs that have overflowed and are not visible.
 */
const OverflowMenu = (props: OverflowMenuProps) => {
    const { onTabSelect } = props;
    const { ref, isOverflowing, overflowCount } = useOverflowMenu<HTMLButtonElement>();
    const styles = useOverflowMenuStyles();
    const onItemClick = (tabId: string) => {
        onTabSelect?.(tabId);
    };
    if (!isOverflowing) {
        return null;
    }
    return (<Menu hasIcons>
      <MenuTrigger disableButtonEnhancement>
        <Button appearance="transparent" className={styles.menuButton} ref={ref} icon={<MoreHorizontal />} aria-label={`${overflowCount} more tabs`} role="tab"/>
      </MenuTrigger>
      <MenuPopover>
        <MenuList className={styles.menu}>
          {tabs.map(tab => (<OverflowMenuItem key={tab.id} tab={tab} onClick={() => onItemClick(tab.id)}/>))}
        </MenuList>
      </MenuPopover>
    </Menu>);
};

const HorizontalExample = () => {
    const styles = useExampleStyles();
    const [selectedTabId, setSelectedTabId] = React.useState<string>('today');
    const onTabSelect = (tabId: string) => {
        setSelectedTabId(tabId);
    };
    return (<div className={mergeClasses(styles.example, styles.horizontal)}>
      <Overflow minimumVisible={2}>
        <TabList selectedValue={selectedTabId} onTabSelect={(_, d) => onTabSelect(d.value as string)}>
          {tabs.map(tab => {
            return (<OverflowItem key={tab.id} id={tab.id} priority={tab.id === selectedTabId ? 2 : 1}>
                <Tab value={tab.id} icon={<span>{tab.icon}</span>}>
                  {tab.name}
                </Tab>
              </OverflowItem>);
        })}
          <OverflowMenu onTabSelect={onTabSelect}/>
        </TabList>
      </Overflow>
    </div>);
};

const VerticalExample = () => {
    const styles = useExampleStyles();
    const [selectedTabId, setSelectedTabId] = React.useState<string>('today');
    const onTabSelect = (tabId: string) => {
        setSelectedTabId(tabId);
    };
    return (<div className={mergeClasses(styles.example, styles.vertical)}>
      <Overflow minimumVisible={2} overflowAxis="vertical">
        <TabList vertical selectedValue={selectedTabId} onTabSelect={(_, d) => onTabSelect(d.value as string)}>
          {tabs.map(tab => {
            return (<OverflowItem key={tab.id} id={tab.id} priority={tab.id === selectedTabId ? 2 : 1}>
                <Tab value={tab.id} icon={<span>{tab.icon}</span>}>
                  {tab.name}
                </Tab>
              </OverflowItem>);
        })}
          <OverflowMenu onTabSelect={onTabSelect}/>
        </TabList>
      </Overflow>
    </div>);
};

export const WithOverflow = (): JSXElement => {
    const styles = useStyles();
    return (<div className={styles.root}>
      <HorizontalExample />
      <VerticalExample />
    </div>);
};

export default WithOverflow;
