import React, { useContext, useMemo } from 'react';
import { elementType, func, number, node, bool } from 'prop-types';
import { createNamedContext } from '../../utils';
import useControlProp from '../../hooks/useControlProp';
import useId from '../../hooks/useId';

const TabsContext = createNamedContext('Tabs', {});

function useTabsContext() {
  return useContext(TabsContext);
}

const Tabs = ({
  children,
  index: indexProp,
  onChange: onChangeProp,
  defaultIndex = 0,
  as: Comp = 'div',
  paths,
  ...rest
}) => {
  const [index, onChange] = useControlProp(indexProp, onChangeProp, defaultIndex);
  const id = useId();

  const ctx = useMemo(
    () => ({
      index,
      onChange,
      id,
      paths,
    }),
    [index, onChange, id, paths],
  );

  return (
    <TabsContext.Provider value={ctx}>
      <Comp {...rest}>{children}</Comp>
    </TabsContext.Provider>
  );
};

Tabs.propTypes = {
  as: elementType,
  children: node.isRequired,
  defaultIndex: number,
  index: number,
  onChange: func,
};

const TabPanels = ({ children }) => {
  const ctx = useTabsContext();
  return (
    <React.Fragment>
      {React.Children.map(children, (child, index) => {
        return React.cloneElement(child, {
          index,
          id: `panel-${ctx.id}-${index}`,
          role: 'tabpanel',
          'aria-labelledby': `tab-${ctx.id}-${index}`,
          'aria-hidden': ctx.index !== index,
          hidden: ctx.index !== index,
        });
      })}
    </React.Fragment>
  );
};

const TabPanel = ({ children, hidden, renderWhenHidden, index, ...rest }) => {
  return hidden && !renderWhenHidden ? null : (
    <div {...rest} hidden={hidden} style={{ display: hidden ? 'none' : 'block' }}>
      {children}
    </div>
  );
};

TabPanel.propTypes = {
  renderWhenHidden: bool,
};

export { Tabs, useTabsContext, TabPanels, TabPanel };
