import { jsx, jsxs } from "react/jsx-runtime";
import { createContext, useReducer, useContext, useRef, useEffect, cloneElement } from "react";
import assert from "assert";
import { Box } from "../Box/Box.mjs";
import { getNextIndex, useResponsiveValue, smoothScroll, smoothScrollIntoView, normalizeKey } from "../Autosuggest/Autosuggest.mjs";
import { Text, Overlay } from "../Accordion/AccordionItem.mjs";
import { buildDataAttributes } from "../Accordion/Accordion.mjs";
import { useBraidTheme } from "../../../../side-effects/lib/components/BraidProvider/BraidProvider.mjs";
import { tab, cropToIconX, hoveredTab, tabFocusRing } from "./Tabs.css.mjs";
const useSpace = () => useBraidTheme().space;
const TAB_BUTTON_RIGHT = 0;
const TAB_BUTTON_LEFT = 1;
const TAB_BUTTON_HOME = 2;
const TAB_BUTTON_END = 3;
const TAB_BUTTON_TAB = 4;
const TAB_BUTTON_ENTER = 5;
const TAB_BUTTON_SPACE = 6;
const TAB_BUTTON_CLICK = 7;
const TAB_LIST_UPDATED = 8;
const TAB_LIST_FOCUSED = 9;
const TAB_PANELS_UPDATED = 10;
const TAB_BUTTON_REGISTER = 11;
const getTabLabelId = (uniqueId, index) => `${uniqueId}_${index + 1}_label`;
const getPanelId = (uniqueId, index) => `${uniqueId}_${index + 1}_panel`;
const tabA11y = ({ uniqueId }) => ({
  tabListProps: ({ label }) => ({
    role: "tablist",
    "aria-orientation": "horizontal",
    "aria-label": label
  }),
  tabProps: ({ tabIndex, isSelected }) => ({
    role: "tab",
    tabIndex: isSelected ? void 0 : -1,
    "aria-selected": isSelected,
    "aria-controls": getPanelId(uniqueId, tabIndex),
    id: `${uniqueId}_${tabIndex + 1}`
  }),
  tabLabelProps: ({ tabIndex }) => ({
    id: getTabLabelId(uniqueId, tabIndex)
  }),
  tabPanelProps: ({ panelIndex, isSelected }) => ({
    role: "tabpanel",
    "aria-labelledby": getTabLabelId(uniqueId, panelIndex),
    "aria-hidden": isSelected ? void 0 : true,
    id: getPanelId(uniqueId, panelIndex),
    tabIndex: isSelected ? 0 : void 0
  })
});
const TabsContext = createContext(null);
const TabsProvider = ({
  children,
  onChange,
  id,
  selectedItem
}) => {
  const [tabsState, dispatch] = useReducer(
    (state, action) => {
      switch (action.type) {
        case TAB_BUTTON_LEFT: {
          return {
            ...state,
            focusedTabIndex: getNextIndex(
              -1,
              state.focusedTabIndex,
              state.tabItems.length
            )
          };
        }
        case TAB_BUTTON_RIGHT: {
          return {
            ...state,
            focusedTabIndex: getNextIndex(
              1,
              state.focusedTabIndex,
              state.tabItems.length
            )
          };
        }
        case TAB_BUTTON_HOME: {
          return {
            ...state,
            focusedTabIndex: 0
          };
        }
        case TAB_BUTTON_END: {
          return {
            ...state,
            focusedTabIndex: state.tabItems.length - 1
          };
        }
        case TAB_BUTTON_TAB: {
          return {
            ...state,
            focusedTabIndex: null
          };
        }
        case TAB_BUTTON_ENTER:
        case TAB_BUTTON_SPACE:
        case TAB_BUTTON_CLICK: {
          return {
            ...state,
            focusedTabIndex: action.value,
            selectedIndex: action.value
          };
        }
        case TAB_BUTTON_REGISTER: {
          return {
            ...state,
            tabButtonElements: {
              ...state.tabButtonElements,
              [action.tabListItemIndex.toString()]: action.tabEl
            }
          };
        }
        case TAB_LIST_FOCUSED: {
          return {
            ...state,
            focusedTabIndex: action.value || 0
          };
        }
        case TAB_LIST_UPDATED: {
          return {
            ...state,
            tabItems: action.tabItems,
            selectedIndex: 0
          };
        }
        case TAB_PANELS_UPDATED: {
          return {
            ...state,
            panels: action.panels
          };
        }
        default:
          return state;
      }
    },
    {
      selectedIndex: 0,
      focusedTabIndex: null,
      tabItems: [],
      panels: [],
      tabButtonElements: {}
    }
  );
  return /* @__PURE__ */ jsx(
    TabsContext.Provider,
    {
      value: {
        ...tabsState,
        selectedIndex: typeof selectedItem !== "undefined" ? tabsState.tabItems.indexOf(selectedItem) : tabsState.selectedIndex,
        selectedItem,
        dispatch,
        a11y: tabA11y({ uniqueId: id }),
        onChange
      },
      children
    }
  );
};
const TabListContext = createContext(null);
const paddingX = "small";
const Tab = ({
  children,
  data,
  badge,
  icon,
  item,
  ...restProps
}) => {
  const tabsContext = useContext(TabsContext);
  const tabListContext = useContext(TabListContext);
  const tabRef = useRef(null);
  assert(
    tabListContext !== null,
    "A Tab must be rendered as a child of Tabs. See the documentation for correct usage: https://seek-oss.github.io/braid-design-system/components/Tab"
  );
  assert(
    // @ts-expect-error
    !badge || badge.type.__isBadge__,
    `Tab badge prop can only be an instance of Badge. e.g. <Tab badge={<Badge>New</Badge>}>`
  );
  assert(
    !badge || badge.props.bleedY === void 0,
    "Badge elements cannot set the 'bleedY' prop when passed to a Tab component"
  );
  assert(
    !icon || icon.props.size === void 0 && icon.props.tone === void 0,
    "Icons cannot set the 'size' or 'tone' prop when passed to a Tab component"
  );
  if (!tabListContext) {
    throw new Error("Tab rendered outside Tabs context");
  }
  if (!tabsContext) {
    throw new Error("Tab rendered outside TabsProvider");
  }
  const {
    focusedTabIndex,
    selectedIndex,
    selectedItem,
    dispatch,
    a11y,
    onChange
  } = tabsContext;
  const { tabListItemIndex, scrollContainer, isLast } = tabListContext;
  const isSelected = selectedIndex > -1 ? selectedIndex === tabListItemIndex : selectedItem === item;
  const isFocused = focusedTabIndex === tabListItemIndex;
  const { grid, space } = useSpace();
  useEffect(() => {
    if (tabRef.current && isFocused) {
      tabRef.current.focus();
    }
  }, [isFocused]);
  const firstRenderRef = useRef(true);
  const isMobile = useResponsiveValue()({
    mobile: true,
    tablet: false
  });
  useEffect(() => {
    if (!tabRef.current || !scrollContainer) {
      return;
    }
    if (isSelected || isFocused) {
      if (isMobile) {
        smoothScroll(tabRef.current, {
          scrollContainer,
          direction: "horizontal",
          offset: space[paddingX] * grid * 3,
          ...firstRenderRef.current ? { duration: 0 } : { speed: 0.7 }
        });
      } else {
        smoothScrollIntoView(tabRef.current, {
          scrollContainer,
          direction: "horizontal",
          offset: space[paddingX] * grid * 6,
          ...firstRenderRef.current ? { duration: 0 } : { speed: 0.7 }
        });
      }
    }
    firstRenderRef.current = false;
  }, [isSelected, isFocused, scrollContainer, space, grid, isMobile]);
  useEffect(() => {
    if (tabRef.current) {
      dispatch({
        type: TAB_BUTTON_REGISTER,
        tabEl: tabRef.current,
        tabListItemIndex
      });
    }
  }, [dispatch, tabListItemIndex]);
  const onKeyUp = (event) => {
    const targetKey = normalizeKey(event);
    if (targetKey === "Tab") {
      return;
    }
    if (onChange && (targetKey === "Enter" || targetKey === " ")) {
      onChange(tabListItemIndex, item);
    }
    const action = {
      ArrowRight: { type: TAB_BUTTON_RIGHT },
      ArrowLeft: { type: TAB_BUTTON_LEFT },
      Home: { type: TAB_BUTTON_HOME },
      End: { type: TAB_BUTTON_END },
      Enter: { type: TAB_BUTTON_ENTER, value: tabListItemIndex },
      " ": { type: TAB_BUTTON_SPACE, value: tabListItemIndex }
    };
    if (action[targetKey]) {
      dispatch(action[targetKey]);
    }
  };
  const onKeyDown = (event) => {
    const targetKey = normalizeKey(event);
    if (targetKey === "Tab" && focusedTabIndex !== null) {
      dispatch({ type: TAB_BUTTON_TAB });
      return;
    }
    const isArrowPress = targetKey.indexOf("Arrow") === 0;
    const isActionKeyPress = targetKey === "Enter" || targetKey === " ";
    if (isArrowPress || isActionKeyPress) {
      event.preventDefault();
    }
  };
  return /* @__PURE__ */ jsxs(
    Box,
    {
      component: "button",
      type: "button",
      ...a11y.tabProps({ tabIndex: tabListItemIndex, isSelected }),
      ref: tabRef,
      onKeyUp,
      onKeyDown,
      onClick: (event) => {
        event.stopPropagation();
        event.preventDefault();
        if (onChange) {
          onChange(tabListItemIndex, item);
        }
        dispatch({ type: TAB_BUTTON_CLICK, value: tabListItemIndex });
      },
      onFocus: isSelected ? () => dispatch({
        type: TAB_LIST_FOCUSED,
        value: tabListItemIndex
      }) : void 0,
      display: "flex",
      alignItems: "center",
      textAlign: "left",
      borderRadius: "standard",
      cursor: "pointer",
      outline: "none",
      position: "relative",
      zIndex: 1,
      paddingLeft: tabListItemIndex > 0 ? paddingX : void 0,
      paddingRight: !isLast ? paddingX : void 0,
      paddingY: "medium",
      className: tab,
      ...buildDataAttributes({ data, validateRestProps: restProps }),
      children: [
        /* @__PURE__ */ jsx(
          Box,
          {
            component: "span",
            display: "block",
            position: "absolute",
            "aria-hidden": true,
            transition: "fast",
            opacity: isSelected ? 0 : void 0,
            className: icon ? cropToIconX : void 0,
            children: /* @__PURE__ */ jsx(Text, { tone: "secondary", icon, children })
          }
        ),
        /* @__PURE__ */ jsx(
          Box,
          {
            component: "span",
            display: "block",
            position: "absolute",
            "aria-hidden": true,
            transition: "fast",
            opacity: 0,
            className: [
              !isSelected ? hoveredTab : void 0,
              icon ? cropToIconX : void 0
            ],
            children: /* @__PURE__ */ jsx(Text, { icon, children })
          }
        ),
        /* @__PURE__ */ jsx(
          Box,
          {
            component: "span",
            display: "block",
            transition: "fast",
            opacity: !isSelected ? 0 : void 0,
            className: icon ? cropToIconX : void 0,
            children: /* @__PURE__ */ jsx(
              Text,
              {
                ...a11y.tabLabelProps({ tabIndex: tabListItemIndex }),
                tone: "formAccent",
                icon,
                children
              }
            )
          }
        ),
        badge ? /* @__PURE__ */ jsx(Box, { component: "span", paddingLeft: "xsmall", children: cloneElement(badge, { bleedY: true }) }) : null,
        /* @__PURE__ */ jsx(
          Overlay,
          {
            component: "span",
            zIndex: 1,
            boxShadow: "outlineFocus",
            borderRadius: "standard",
            className: tabFocusRing,
            visible: false,
            transition: "fast",
            onlyVisibleForKeyboardNavigation: true
          }
        )
      ]
    }
  );
};
Tab.__isTab__ = true;
export {
  TAB_LIST_UPDATED,
  TAB_PANELS_UPDATED,
  Tab,
  TabListContext,
  TabsContext,
  TabsProvider,
  useSpace
};
