import _pt from "prop-types";

function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }

import React, { useState, useRef } from 'react';
import Tab from './Tab';
import TabPanel from './TabPanel';
import classnames from 'classnames';
import get from 'lodash/get';

/** CONSTANTS
 * Adding in the constant values for keycodes
 * to handle onKeyDown events
 */
var LEFT_ARROW = 'ArrowLeft';
var RIGHT_ARROW = 'ArrowRight';
/**
 * Determine if a React component is a TabPanel
 * @param {React.Node} child - a React component
 * @return {Boolean} Is this a TabPanel component?
 */

var isTabPanel = function isTabPanel(child) {
  var componentName = get(child, 'type.displayName') || get(child, 'type.name'); // Check child.type first and as a fallback, check child.type.displayName follow by child.type.name

  return child && (child.type === TabPanel || componentName === 'TabPanel');
};
/**
 * Get the id of the first TabPanel child
 * @param {Object} props
 * @return {String} The id
 */


var getDefaultSelectedId = function getDefaultSelectedId(props) {
  var selectedId; // TODO: Use the panelChildren method to pass in an array
  // of panels, instead of doing it here...

  React.Children.forEach(props.children, function (child) {
    if (isTabPanel(child) && !selectedId) {
      selectedId = child.props.id;
    }
  });
  return selectedId;
};
/**
 * Generate an id for a panel's associated tab if one doesn't yet exist
 * @param {Object} TabPanel component
 * @return {String} Tab ID
 */


var panelTabId = function panelTabId(panel) {
  return panel.props.tabId || "ds-c-tabs__item--".concat(panel.props.id);
};

export var Tabs = function Tabs(props) {
  var initialSelectedId = props.defaultSelectedId || getDefaultSelectedId(props);

  var _useState = useState(initialSelectedId),
      _useState2 = _slicedToArray(_useState, 2),
      selectedId = _useState2[0],
      setSelectedId = _useState2[1];

  var listClasses = classnames('ds-c-tabs', props.tablistClassName); // using useRef hook to keep track of elements to focus

  var tabsRef = useRef({});
  /**
   * Update the URL in the browser without adding a new entry to the history.
   * @param {String} url - Absolute or relative URL
   */

  var replaceState = function replaceState(url) {
    if (window.history) {
      window.history.replaceState({}, document.title, url);
    }
  };

  var panelChildren = function panelChildren() {
    return React.Children.toArray(props.children).filter(isTabPanel);
  };

  var handleSelectedTabChange = function handleSelectedTabChange(newSelectedId) {
    var onChange = props.onChange;

    if (onChange) {
      onChange(newSelectedId, selectedId);
    }

    tabsRef.current[newSelectedId].focus();
    replaceState(tabsRef.current[newSelectedId].href);
    setSelectedId(newSelectedId);
  };

  var handleTabClick = function handleTabClick(evt, panelId) {
    evt.preventDefault();
    handleSelectedTabChange(panelId);
  };

  var handleTabKeyDown = function handleTabKeyDown(evt, panelId) {
    var tabs = panelChildren();
    var tabIndex = tabs.findIndex(function (elem) {
      return elem.props.id === panelId;
    });
    var target;

    switch (evt.key) {
      case LEFT_ARROW:
        evt.preventDefault();

        if (tabIndex === 0) {
          var prevTab = tabs[tabs.length - 1];
          target = prevTab.props.id;
        } else {
          var _prevTab = tabs[tabIndex - 1];
          target = _prevTab.props.id;
        }

        handleSelectedTabChange(target);
        break;

      case RIGHT_ARROW:
        evt.preventDefault();

        if (tabIndex === tabs.length - 1) {
          var currentTab = tabs[0];
          target = currentTab.props.id;
        } else {
          var nextTab = tabs[tabIndex + 1];
          target = nextTab.props.id;
        }

        handleSelectedTabChange(target);
        break;

      default:
        break;
    }
  };

  var renderChildren = function renderChildren() {
    return React.Children.map(props.children, function (child) {
      if (isTabPanel(child) && /*#__PURE__*/React.isValidElement(child)) {
        // Extend props on panels before rendering. Also removes any props
        // that don't need passed into TabPanel but are used to generate
        // the Tab components
        return /*#__PURE__*/React.cloneElement(child, {
          selected: selectedId === child.props.id,
          tab: undefined,
          tabHref: undefined,
          tabId: panelTabId(child)
        });
      }

      return child;
    });
  };

  var renderTabs = function renderTabs() {
    var panels = panelChildren();
    var tabs = panels.map(function (panel) {
      return /*#__PURE__*/React.createElement(Tab, {
        className: panel.props.tabClassName,
        href: panel.props.tabHref,
        disabled: panel.props.disabled,
        id: panelTabId(panel),
        key: panel.key,
        onClick: handleTabClick,
        onKeyDown: handleTabKeyDown,
        panelId: panel.props.id,
        ref: function ref(tab) {
          tabsRef.current[panel.props.id] = tab;
        },
        selected: selectedId === panel.props.id
      }, panel.props.tab);
    });
    return tabs;
  };

  return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
    className: listClasses,
    role: "tablist"
  }, renderTabs()), renderChildren());
};
Tabs.propTypes = {
  /**
     * Must only contain `TabPanel` components
     */
  children: _pt.node.isRequired,

  /**
     * Sets the initial selected `TabPanel` state. If this isn't set, the first
     * `TabPanel` will be selected.
     */
  defaultSelectedId: _pt.string,

  /**
     * A callback function that's invoked when the selected tab is changed.
     * `(selectedId, prevSelectedId) => void`
     */
  onChange: _pt.func,

  /**
     * Additional classes to be added to the component wrapping the tabs
     */
  tablistClassName: _pt.string
};
export default Tabs;