import React from 'react';
import { element, arrayOf, oneOf, node, oneOfType, string, number } from 'prop-types';
import styled from '@emotion/styled';
import css from '@styled-system/css';
import { useTabsContext } from './Tabs';
import { Shelf, Stack } from '../Layout';
import Divider from '../Divider';
import { focusVisibleRing } from '../../utils/styled';
import Text from '../Text/Text';

const TabList = ({
  appearance = 'primary',
  size = 'large',
  orientation = 'horizontal',
  accentColor,
  spacing = 'left',
  children,
  gap = orientation === 'vertical' ? 'xsmall' : appearance === 'primary' ? 0 : 'large',
  ...rest
}) => {
  const ctx = useTabsContext();

  const childs = React.Children.map(children, (child, index) => {
    return React.cloneElement(child, {
      isSelected: index === ctx.index,
      onSelect: () => ctx.onChange(index),
      id: `tab-${ctx.id}-${index}`,
      'aria-controls': `panel-${ctx.id}-${index}`,
      as: ctx.paths ? 'a' : child.as,
      href: ctx.paths ? ctx.paths[index] : child.href,
      appearance,
      size,
      orientation,
      accentColor,
      spacing,
    });
  });

  if (orientation === 'horizontal') {
    return (
      <div>
        <Shelf as="nav" gap={gap} role="tablist" flexWrap="nowrap" {...rest}>
          {childs}
        </Shelf>
        {appearance === 'primary' && <Divider mt="-1px" />}
      </div>
    );
  }

  return <Stack gap={gap}>{childs}</Stack>;
};

TabList.propTypes = {
  children: arrayOf(element).isRequired,
  gap: oneOfType([string, number]),
  orientation: oneOf(['horizontal', 'vertical']),
  appearance: oneOf(['primary', 'secondary']),
  size: oneOf(['large', 'small']),
  spacing: oneOf(['left', 'centered']),
};

const StyledPrimaryTab = styled('button')(
  {
    backgroundColor: 'transparent',
    cursor: 'pointer',
    appearance: 'none',
    textDecoration: 'none',
  },
  ({ isSelected, size, theme, spacing, accentColor = 'brand' }) =>
    css({
      color: isSelected ? 'foreground' : 'foregroundAccent',
      borderBottom: '3px solid',
      borderBottomColor: isSelected ? accentColor : 'transparent',
      paddingLeft: 'gutter',
      paddingRight: 'gutter',
      paddingTop: 10,
      paddingBottom: size === 'large' ? 'gutter' : 10,
      flexGrow: spacing === 'centered' ? 1 : 0,
      '& > *': {
        display: 'flex',
        justifyContent: spacing === 'centered' ? 'center' : 'flex-start',
      },
      '&:hover': {
        color: 'foreground',
      },
    })(theme),
  focusVisibleRing(3),
);

const StyledSecondaryTab = styled('button')(
  {
    backgroundColor: 'transparent',
    cursor: 'pointer',
    appearance: 'none',
    textDecoration: 'none',
  },
  ({ isSelected, theme }) =>
    css({
      color: isSelected ? 'foreground' : 'foregroundAccent',

      '&:hover': {
        color: 'foreground',
      },
    })(theme),
  focusVisibleRing(3),
);

const Tab = ({
  children,
  isSelected,
  onSelect,
  as,
  appearance,
  orientation,
  size,
  label,
  accentColor,
  spacing,
  ...rest
}) => {
  const props = {};
  if (as === 'a') {
    if (isSelected) {
      props['aria-current'] = 'page';
    }
  } else {
    props['aria-selected'] = isSelected;
    props.role = 'tab';
  }

  function handleClick(e) {
    e.preventDefault();
    onSelect();
  }

  let Comp;
  if (appearance === 'primary' && orientation === 'horizontal') {
    Comp = StyledPrimaryTab;
  } else {
    Comp = StyledSecondaryTab;
  }

  return (
    <Comp
      onClick={handleClick}
      accentColor={accentColor}
      spacing={spacing}
      as={as}
      isSelected={isSelected}
      size={size}
      {...props}
      {...rest}
    >
      <Shelf gap="xsmall" flexWrap="nowrap">
        <Text
          color="inherit"
          trim={false}
          fontSize={size === 'large' ? 18 : 16}
          fontWeight={isSelected ? 'bold' : 'standard'}
        >
          {children}
        </Text>
        {label}
      </Shelf>
    </Comp>
  );
};

Tab.propTypes = {
  children: node.isRequired,
  label: node,
};

export { TabList, Tab };
