import React, { forwardRef } from 'react';
import PropTypes from 'prop-types';
import { useTabContext } from './TabsProvider';

const propTypes = {
  /**
   * Children to set inside the TabPanel.
   */
  children: PropTypes.node,
  /**
   * The name of the panel. It should match the tab name to show itself when
   * the matching tab is selected.
   */
  name: PropTypes.string.isRequired,
  /**
   * A ref that will contains the current visible panel ref.
   */
  selectedPanelRef: PropTypes.any,
  /**
   * The custom tag for the root of the Tab
   */
  tag: PropTypes.oneOfType([PropTypes.func, PropTypes.string]),
};

const defaultProps = {
  children: '',
  selectedPanelRef: null,
  tag: 'div',
};

const assignRef = (ref, value) => {
  if (ref == null) return;
  if (typeof ref === 'function') {
    ref(value);
  } else {
    try {
      // eslint-disable-next-line no-param-reassign
      ref.current = value;
    } catch (error) {
      throw new Error(`Cannot assign value "${value}" to ref "${ref}"`);
    }
  }
};

export const TabPanel = forwardRef(({
  children, selectedPanelRef, name, tag: Tag, ...attributes
}, ref) => {
  const { id, selectedName } = useTabContext();

  const isSelected = name === selectedName;

  if (!isSelected) {
    return '';
  }

  return (
    <Tag
      ref={(node) => {
        if (isSelected) {
          assignRef(selectedPanelRef, node);
        }
        assignRef(ref, node);
      }}
      role="tabpanel"
      aria-labelledby={`tab:${id}:${name}`}
      id={`panel:${id}:${name}`}
      {...attributes}
    >
      {children}
    </Tag>
  );
});

TabPanel.propTypes = propTypes;
TabPanel.defaultProps = defaultProps;
