function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }

function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }

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

import PropTypes from "prop-types";

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) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_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; }

/*
 * SPDX-License-Identifier: Apache-2.0
 *
 * The OpenSearch Contributors require contributions made to
 * this file be licensed under the Apache-2.0 license or a
 * compatible open source license.
 *
 * Modifications Copyright OpenSearch Contributors. See
 * GitHub history for details.
 */

/*
 * Licensed to Elasticsearch B.V. under one or more contributor
 * license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright
 * ownership. Elasticsearch B.V. licenses this file to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
import React, { Fragment, useEffect, useState } from 'react';
import classNames from 'classnames';
import { OuiI18n } from '../../i18n';
import { OuiInnerText } from '../../inner_text';
import { OuiLink } from '../../link';
import { OuiPopover } from '../../popover';
import { OuiIcon } from '../../icon';
import { throttle } from '../../../services';
import { getBreakpoint } from '../../../services/breakpoint';

/* Try to fit breadcrumbs with at least 135px into the width of each of the BREAKPOINTS
 *    1. put aside 250px for the last breadcrumb and possible loss due to layout
 *    2. provide at least 135px for each remaining breadcrumb
 *
 *     * OuiBreadcrumbs has 48px padding on the side with a max-width of 160px
 *     * OuiSimplifiedBreadcrumbs has 24px for gap and separator
 *     * To be uniform
 *           160px - 48px + 24px ≈ 135px for each simplified breadcrumb
 *           275px - 48px + 24px ≈ 250px for last simplified breadcrumb and external spacing
 *
 *    numberOfBreadcrumbs = (breakpointWidth - 251) / 136 + 1
 */
var responsiveDefault = {
  xs: 1,
  // Show only one
  s: 3,
  //  (575 - 250) / 135 + 1 = 3.40
  m: 4,
  //  (768 - 250) / 135 + 1 = 4.83
  l: 6,
  //  (992 - 250) / 135 + 1 = 6.49
  xl: 8,
  // (1200 - 250) / 135 + 1 = 8.04
  xxl: 11,
  // (1680 - 250) / 135 + 1 = 11.59
  xxxl: 13 // (1920 - 250) / 135 + 1 = 13.37

};
/*
  xxxl: 1920,
  xxl: 1680,
  xl: 1200,
  l: 992,
  m: 768,
  s: 575,
 */

var limitBreadcrumbs = function limitBreadcrumbs(breadcrumbs, max, allBreadcrumbs) {
  var breadcrumbsAtStart = [];
  var breadcrumbsAtEnd = [];
  var limit = Math.min(max, breadcrumbs.length);
  var start = Math.floor(limit / 2);
  var overflowBreadcrumbs = allBreadcrumbs.slice(start, start + breadcrumbs.length - limit);

  for (var i = 0; i < limit; i++) {
    // We'll alternate with displaying breadcrumbs at the end and at the start, but be biased
    // towards breadcrumbs the end so that if max is an odd number, we'll have one more
    // breadcrumb visible at the end than at the beginning.
    var isEven = i % 2 === 0; // We're picking breadcrumbs from the front AND the back, so we treat each iteration as a
    // half-iteration.

    var normalizedIndex = Math.floor(i * 0.5);
    var indexOfBreadcrumb = isEven ? breadcrumbs.length - 1 - normalizedIndex : normalizedIndex;
    var breadcrumb = breadcrumbs[indexOfBreadcrumb];

    if (isEven) {
      breadcrumbsAtEnd.unshift(breadcrumb);
    } else {
      breadcrumbsAtStart.push(breadcrumb);
    }
  }

  var OuiBreadcrumbCollapsed = function OuiBreadcrumbCollapsed() {
    var _useState = useState(false),
        _useState2 = _slicedToArray(_useState, 2),
        isPopoverOpen = _useState2[0],
        setIsPopoverOpen = _useState2[1];

    var ellipsisButton = /*#__PURE__*/React.createElement(OuiI18n, {
      token: "ouiSimplifiedBreadcrumbs.collapsedBadge.ariaLabel",
      default: "Show collapsed breadcrumbs"
    }, function (ariaLabel) {
      return /*#__PURE__*/React.createElement(OuiLink, {
        className: "ouiSimplifiedBreadcrumb ouiSimplifiedBreadcrumb__collapsedLink",
        "aria-label": ariaLabel,
        title: ariaLabel,
        onClick: function onClick() {
          return setIsPopoverOpen(!isPopoverOpen);
        }
      }, "\u2026 ", /*#__PURE__*/React.createElement(OuiIcon, {
        type: "arrowDown",
        size: "s"
      }));
    });
    return /*#__PURE__*/React.createElement(Fragment, null, /*#__PURE__*/React.createElement(OuiPopover, {
      className: "ouiSimplifiedBreadcrumb ouiSimplifiedBreadcrumb--collapsed",
      button: ellipsisButton,
      isOpen: isPopoverOpen,
      closePopover: function closePopover() {
        return setIsPopoverOpen(false);
      }
    }, /*#__PURE__*/React.createElement(OuiSimplifiedBreadcrumbs, {
      className: "ouiSimplifiedBreadcrumbs__inPopover",
      breadcrumbs: overflowBreadcrumbs,
      responsive: false,
      truncate: false,
      hideLastBreadCrumb: false,
      hideTrailingSeparator: true,
      disableTrailingLink: false,
      max: 0
    })), /*#__PURE__*/React.createElement(OuiBreadcrumbSeparator, null));
  };

  if (max < breadcrumbs.length) {
    breadcrumbsAtStart.push( /*#__PURE__*/React.createElement(OuiBreadcrumbCollapsed, {
      key: "collapsed"
    }));
  }

  return [].concat(breadcrumbsAtStart, breadcrumbsAtEnd);
};

var OuiBreadcrumbSeparator = function OuiBreadcrumbSeparator() {
  return (
    /*#__PURE__*/
    // preserveAspectRatio is none so we can stretch it vertically and keep the width fixed
    React.createElement("svg", {
      xmlns: "http://www.w3.org/2000/svg",
      viewBox: "0 0 8 12",
      preserveAspectRatio: "none",
      className: "ouiBreadcrumbSeparator"
    }, /*#__PURE__*/React.createElement("path", {
      fill: "currentColor",
      d: "M2 12H0L6 0h2z"
    }))
  );
};

export var OuiSimplifiedBreadcrumbs = function OuiSimplifiedBreadcrumbs(_ref) {
  var breadcrumbs = _ref.breadcrumbs,
      className = _ref.className,
      _ref$responsive = _ref.responsive,
      responsive = _ref$responsive === void 0 ? responsiveDefault : _ref$responsive,
      _ref$truncate = _ref.truncate,
      truncate = _ref$truncate === void 0 ? true : _ref$truncate,
      _ref$max = _ref.max,
      max = _ref$max === void 0 ? 5 : _ref$max,
      hideTrailingSeparator = _ref.hideTrailingSeparator,
      disableTrailingLink = _ref.disableTrailingLink,
      hideLastBreadCrumb = _ref.hideLastBreadCrumb,
      rest = _objectWithoutProperties(_ref, ["breadcrumbs", "className", "responsive", "truncate", "max", "hideTrailingSeparator", "disableTrailingLink", "hideLastBreadCrumb"]);

  // Use the default object if they simply passed `true` for responsive
  var responsiveObject = _typeof(responsive) === 'object' ? responsive : responsiveDefault;
  var allowedBreakpoints = responsive ? Object.keys(responsiveObject) : undefined;

  var _useState3 = useState(getBreakpoint(typeof window === 'undefined' ? -Infinity : window.innerWidth, undefined, allowedBreakpoints)),
      _useState4 = _slicedToArray(_useState3, 2),
      currentBreakpoint = _useState4[0],
      setCurrentBreakpoint = _useState4[1];

  var functionToCallOnWindowResize = throttle(function () {
    var newBreakpoint = getBreakpoint(window.innerWidth, undefined, allowedBreakpoints);

    if (newBreakpoint !== currentBreakpoint) {
      setCurrentBreakpoint(newBreakpoint);
    } // reacts every 50ms to resize changes and always gets the final update

  }, 50); // Add window resize handlers

  useEffect(function () {
    window.addEventListener('resize', functionToCallOnWindowResize);
    return function () {
      window.removeEventListener('resize', functionToCallOnWindowResize);
    };
  }, [responsive, responsiveObject, functionToCallOnWindowResize]);
  var isInPopover = className === 'ouiSimplifiedBreadcrumbs__inPopover';
  var breadcrumbElements = breadcrumbs.map(function (breadcrumb, index) {
    var text = breadcrumb.text,
        href = breadcrumb.href,
        onClick = breadcrumb.onClick,
        truncate = breadcrumb.truncate,
        breadcrumbClassName = breadcrumb.className,
        breadcrumbRest = _objectWithoutProperties(breadcrumb, ["text", "href", "onClick", "truncate", "className"]);

    var breadcrumbsLength = breadcrumbs.length;
    var isLastBreadcrumb = index === breadcrumbsLength - 1;
    if (isLastBreadcrumb && hideLastBreadCrumb) return null;
    var isFirstBreadcrumb = index === 0; // If hideLastBreadCrumb, the trailing breadcrumb would be the one before the last

    var isTrailingBreadcrumb = index >= breadcrumbsLength - (hideLastBreadCrumb ? 2 : 1);
    var breadcrumbClasses = classNames('ouiSimplifiedBreadcrumb', breadcrumbClassName, {
      'ouiSimplifiedBreadcrumb--last': isLastBreadcrumb,
      'ouiSimplifiedBreadcrumb--truncate': truncate
    });
    var link = !(href || onClick) || isTrailingBreadcrumb && disableTrailingLink ? /*#__PURE__*/React.createElement(OuiInnerText, null, function (ref, innerText) {
      return /*#__PURE__*/React.createElement("span", _extends({
        ref: ref,
        className: breadcrumbClasses,
        title: innerText,
        "aria-current": isLastBreadcrumb && !isInPopover ? 'page' : 'false'
      }, breadcrumbRest), text);
    }) : /*#__PURE__*/React.createElement(OuiInnerText, null, function (ref, innerText) {
      return /*#__PURE__*/React.createElement(OuiLink, _extends({
        ref: ref,
        onClick: onClick,
        href: href,
        className: breadcrumbClasses,
        title: innerText
      }, breadcrumbRest), text);
    });
    var wall = isFirstBreadcrumb ? /*#__PURE__*/React.createElement("div", {
      className: classNames('ouiSimplifiedBreadcrumbWall', {
        'ouiSimplifiedBreadcrumbWall--single': isFirstBreadcrumb && isLastBreadcrumb
      })
    }, link) : link;
    var separator = hideTrailingSeparator && isTrailingBreadcrumb ? null : /*#__PURE__*/React.createElement(OuiBreadcrumbSeparator, null);
    return /*#__PURE__*/React.createElement(Fragment, {
      key: index
    }, wall, separator);
  }); // The max property collapses any breadcrumbs past the max quantity.
  // This is the same behavior we want for responsiveness.
  // So calculate the max value based on the combination of `max` and `responsive`
  // First, calculate the responsive max value

  var responsiveMax = responsive && responsiveObject[currentBreakpoint] || null; // Second, if both max and responsiveMax are set, use the smaller of the two. Otherwise, use the one that is set.

  var calculatedMax = max && responsiveMax ? Math.min(max, responsiveMax) : max || responsiveMax;
  var limitedBreadcrumbs = calculatedMax ? limitBreadcrumbs(breadcrumbElements, calculatedMax, breadcrumbs) : breadcrumbElements;
  var classes = classNames('ouiSimplifiedBreadcrumbs', className, {
    'ouiSimplifiedBreadcrumbs--truncate': truncate
  });
  return /*#__PURE__*/React.createElement("nav", _extends({
    "aria-label": "breadcrumb",
    className: classes
  }, rest), limitedBreadcrumbs);
};
/* OUI -> EUI Aliases: Build-Time */

OuiSimplifiedBreadcrumbs.propTypes = {
  className: PropTypes.string,
  "aria-label": PropTypes.string,
  "data-test-subj": PropTypes.string,

  /**
     * Hides extra (above the max) breadcrumbs under a collapsed item as the window gets smaller.
     * Pass a custom #OuiBreadcrumbResponsiveMaxCount object to change the number of breadcrumbs to show at the particular breakpoints.
     * Omitting or passing a `0` value will show all breadcrumbs.
     *
     * Pass `false` to turn this behavior off.
     *
     * Default: `{ xs: 1, s: 2, m: 4 }`
     */
  responsive: PropTypes.oneOfType([PropTypes.bool.isRequired, PropTypes.any.isRequired]),

  /**
     * Forces all breadcrumbs to single line and
     * truncates each breadcrumb to a particular width,
     * except for the last item
     */
  truncate: PropTypes.bool,

  /**
     * Collapses the inner items past the maximum set here
     * into a single ellipses item
     */
  max: PropTypes.oneOfType([PropTypes.number.isRequired, PropTypes.oneOf([null])]),

  /**
     * The array of individual #OuiBreadcrumb items
     */
  breadcrumbs: PropTypes.arrayOf(PropTypes.shape({
    className: PropTypes.string,
    "aria-label": PropTypes.string,
    "data-test-subj": PropTypes.string,

    /**
       * Visible label of the breadcrumb
       */
    text: PropTypes.node.isRequired,
    href: PropTypes.string,
    onClick: PropTypes.func,

    /**
       * Force a max-width on the breadcrumb text
       */
    truncate: PropTypes.bool
  }).isRequired).isRequired,
  hideTrailingSeparator: PropTypes.bool,
  disableTrailingLink: PropTypes.bool,
  hideLastBreadCrumb: PropTypes.bool
};

/* OUI -> EUI Aliases: Build-Time */
export { EuiSimplifiedBreadcrumbs } from '../../../eui_components/breadcrumbs/simplified_breadcrumbs/simplified_breadcrumbs';