import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
import _extends from '@babel/runtime/helpers/extends';
import _objectWithoutProperties from '@babel/runtime/helpers/objectWithoutProperties';
import _defineProperty from '@babel/runtime/helpers/defineProperty';
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
import _partition from '../../node_modules/lodash-es/partition.js';
import 'core-js/modules/es.symbol.js';
import 'core-js/modules/es.array.concat.js';
import 'core-js/modules/es.array.filter.js';
import 'core-js/modules/es.array.includes.js';
import 'core-js/modules/es.array.map.js';
import 'core-js/modules/es.array.slice.js';
import 'core-js/modules/es.object.get-own-property-descriptor.js';
import 'core-js/modules/es.object.get-own-property-descriptors.js';
import 'core-js/modules/es.object.keys.js';
import 'core-js/modules/es.object.to-string.js';
import 'core-js/modules/es.regexp.constructor.js';
import 'core-js/modules/es.regexp.exec.js';
import 'core-js/modules/es.regexp.to-string.js';
import 'core-js/modules/es.string.includes.js';
import 'core-js/modules/es.string.replace.js';
import 'core-js/modules/web.dom-collections.for-each.js';
import { Search, SideNavItems, SideNav as SideNav$2, SideNavLink, SideNavMenu, SideNavMenuItem } from '@carbon/react';
import PropTypes from 'prop-types';
import React__default, { useState, useEffect } from 'react';
import classnames from 'classnames';
import { settings } from '../../constants/Settings.js';
import { CarbonIconPropType } from '../../constants/SharedPropTypes.js';
import { handleSpecificKeyDown } from '../../utils/componentUtilityFunctions.js';
import { SideNavMetaDataPropType } from './sideNavPropTypes.js';
import FilterableSideNavMenu from './FilterableSideNavMenu.js';

var _excluded = ["links", "defaultExpanded", "hasSearch", "isSideNavExpanded", "i18n", "testId", "recentLinks", "onFilterItems"];
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
var iotPrefix = settings.iotPrefix,
  prefix = settings.prefix;
var markText = function markText(allText, substringToMark) {
  var regex = new RegExp("(.*)(".concat(substringToMark, ")(.*)"), 'i');
  var regexResult = regex.exec(allText);
  if (regexResult !== null) {
    var _regexResult$slice = regexResult.slice(1, 4),
      _regexResult$slice2 = _slicedToArray(_regexResult$slice, 3),
      textInFront = _regexResult$slice2[0],
      markedText = _regexResult$slice2[1],
      textBehind = _regexResult$slice2[2];
    return /*#__PURE__*/React__default.createElement(React__default.Fragment, null, /*#__PURE__*/React__default.createElement("span", null, textInFront), /*#__PURE__*/React__default.createElement("mark", null, markedText), /*#__PURE__*/React__default.createElement("span", null, textBehind));
  }
  return allText;
};
var filterLinks = function filterLinks(items, searchValue) {
  var filteredItems = [];
  items.forEach(function (link) {
    var isLeaf = !link.childContent;
    var content = link.linkContent || link.content;
    if (isLeaf && content.toLowerCase().includes(searchValue)) {
      filteredItems.push(link);
    } else if (!isLeaf) {
      var matchingChildren = filterLinks(link.childContent, searchValue);
      if (matchingChildren.length) {
        filteredItems.push(_objectSpread(_objectSpread({}, link), {}, {
          childContent: matchingChildren
        }));
      }
    }
  });
  return filteredItems;
};
var SideNavPropTypes = {
  /** Specify whether the side navigation is expanded or collapsed */
  defaultExpanded: PropTypes.bool,
  /** Enables search functionality for the links */
  hasSearch: PropTypes.bool,
  /** array of link item objects */
  links: PropTypes.arrayOf(PropTypes.shape({
    /** is current link active */
    isActive: PropTypes.bool,
    /** bot show/hide link */
    isEnabled: PropTypes.bool,
    /** pins the link to the top if hasSearch is true */
    isPinned: PropTypes.bool,
    /** extra props to pass to link component */
    /** Example:
        // What to render for link
        element: PropTypes.any,
        // trigger something instead of follow link
        onClick: PropTypes.func,
        // url to link to
        href: PropTypes.string,
    */
    metaData: SideNavMetaDataPropType,
    /** the icon component to render */
    icon: CarbonIconPropType.isRequired,
    /** string for the title of overall submenu */
    linkContent: PropTypes.string,
    /** array of child links to render in a subnav */
    childContent: PropTypes.arrayOf(PropTypes.shape({
      /** props to pass to link component */
      /** Example:
        // What to render for link
        element: PropTypes.any,
        // trigger something instead of follow link
        onClick: PropTypes.func,
        // url to link to
        href: PropTypes.string,
      */
      metaData: SideNavMetaDataPropType,
      /** content to render inside sub menu link */
      content: PropTypes.oneOfType([PropTypes.string, PropTypes.node, PropTypes.bool, PropTypes.func]).isRequired,
      /** is current link active */
      isActive: PropTypes.bool
    }))
  })).isRequired,
  recentLinks: PropTypes.arrayOf(PropTypes.shape({
    /** is current link active */
    isActive: PropTypes.bool,
    /** bot show/hide link */
    isEnabled: PropTypes.bool,
    /** pins the link to the top if hasSearch is true */
    isPinned: PropTypes.bool,
    /** extra props to pass to link component */
    /** Example:
        // What to render for link
        element: PropTypes.any,
        // trigger something instead of follow link
        onClick: PropTypes.func,
        // url to link to
        href: PropTypes.string,
    */
    metaData: SideNavMetaDataPropType,
    /** the icon component to render */
    icon: CarbonIconPropType.isRequired,
    /** string for the title of overall submenu */
    linkContent: PropTypes.string,
    /** array of child links to render in a subnav */
    childContent: PropTypes.arrayOf(PropTypes.shape({
      /** props to pass to link component */
      /** Example:
        // What to render for link
        element: PropTypes.any,
        // trigger something instead of follow link
        onClick: PropTypes.func,
        // url to link to
        href: PropTypes.string,
      */
      metaData: SideNavMetaDataPropType,
      /** content to render inside sub menu link */
      content: PropTypes.oneOfType([PropTypes.string, PropTypes.node, PropTypes.bool, PropTypes.func]).isRequired,
      /** is current link active */
      isActive: PropTypes.bool
    }))
  })),
  isSideNavExpanded: PropTypes.bool,
  i18n: PropTypes.shape({
    closeText: PropTypes.string,
    openText: PropTypes.string,
    sideNavLabelText: PropTypes.string,
    submenuLabel: PropTypes.string,
    emptySearchText: PropTypes.string,
    searchCloseButtonLabelText: PropTypes.string,
    searchPlaceholder: PropTypes.string,
    searchLabelText: PropTypes.string
  }),
  testId: PropTypes.string,
  onFilterItems: PropTypes.func
};
var defaultProps = {
  defaultExpanded: false,
  hasSearch: false,
  isSideNavExpanded: false,
  i18n: {
    closeText: 'Close',
    openText: 'Open',
    sideNavLabelText: 'Side navigation',
    submenuLabel: 'dropdown',
    emptySearchText: 'No matches found',
    searchCloseButtonLabelText: 'Clear search input',
    searchPlaceholder: 'Find navigation item...',
    searchLabelText: 'Find navigation item'
  },
  testId: 'side-nav',
  recentLinks: [],
  onFilterItems: function onFilterItems() {}
};

/**
 * Simply recursive check for active children, so that a grandparent
 * can also be marked as active when necessary.
 *
 * @param {Object} link
 * @returns boolean
 */
var isAnyChildActive = function isAnyChildActive(link) {
  if (link.isActive) {
    return true;
  }
  if (link.hasOwnProperty('childContent')) {
    return link.childContent.some(function (childLink) {
      return isAnyChildActive(childLink);
    });
  }
  return false;
};
/**
 * Side Navigation. part of UI shell
 */
var SideNav = function SideNav(_ref) {
  var links = _ref.links,
    defaultExpanded = _ref.defaultExpanded,
    hasSearch = _ref.hasSearch,
    isSideNavExpanded = _ref.isSideNavExpanded,
    i18n = _ref.i18n,
    testId = _ref.testId,
    recentLinks = _ref.recentLinks,
    onFilterItems = _ref.onFilterItems,
    props = _objectWithoutProperties(_ref, _excluded);
  /**
   * Recursive function for rendering all the nested children nav items
   *
   * @param {Object} link a single link object
   * @param {Number} index The index of the item in the array
   * @param {Number} level The number of levels deep this link is
   * @returns ReactElement
   */
  var renderLinkMenu = function renderLinkMenu(link, index) {
    var _link$metaData, _link$metaData2;
    var level = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
    var searchValue = arguments.length > 3 ? arguments[3] : undefined;
    var isFiltering = searchValue !== undefined;
    var parentActive = false;
    var tabIndex = searchValue && (_link$metaData = link.metaData) !== null && _link$metaData !== void 0 && _link$metaData.getTabIndexBasedOnSearch ? link.metaData.getTabIndexBasedOnSearch(link, index) : (_link$metaData2 = link.metaData) === null || _link$metaData2 === void 0 ? void 0 : _link$metaData2.tabIndex;
    var children = link.childContent.map(function (childLink, childIndex) {
      if (isAnyChildActive(childLink)) {
        parentActive = true;
      }
      if (childLink.hasOwnProperty('childContent')) {
        return renderLinkMenu(childLink, childIndex, level + 1, searchValue);
      }
      var preventSideNavMenuFromClosingOnBublingEsc = isFiltering;
      var onKeyDown = preventSideNavMenuFromClosingOnBublingEsc ? handleSpecificKeyDown(['Escape'], function (evt) {
        return evt.stopPropagation();
      }) : undefined;
      var content = searchValue ? markText(childLink.content, searchValue) : childLink.content;
      return /*#__PURE__*/React__default.createElement(SideNavMenuItem, _extends({
        onKeyDown: onKeyDown,
        key: "menu-link-".concat(link.childContent.indexOf(childLink), "-child"),
        isActive: childLink.isActive,
        "data-testid": "".concat(testId, "-menu-item-").concat(index)
      }, childLink.metaData), content);
    });
    return /*#__PURE__*/React__default.createElement(FilterableSideNavMenu, _extends({
      isFiltering: isFiltering,
      isActive: parentActive,
      renderIcon: link.icon,
      "aria-label": i18n.submenuLabel,
      key: "menu-link-".concat(link.linkContent.replace(/\s/g, ''), "-dropdown"),
      title: link.linkContent,
      testId: "".concat(testId, "-menu-").concat(index),
      className: "".concat(iotPrefix, "--side-nav__item--depth-").concat(level)
    }, link.metaData ? _objectSpread(_objectSpread({}, link.metaData), {}, {
      tabIndex: tabIndex
    }) : {}), children);
  };
  var renderLinks = function renderLinks(linkConfigurations, searchValue) {
    return linkConfigurations.map(function (link, index) {
      var _link$metaData3, _link$metaData4;
      if (!link.isEnabled) {
        return null;
      }
      if (link.hasOwnProperty('childContent')) {
        return renderLinkMenu(link, index, 0, searchValue);
      }
      var isFiltering = searchValue !== undefined;
      var content = searchValue ? markText(link.linkContent, searchValue) : link.linkContent;
      var tabIndex = searchValue && (_link$metaData3 = link.metaData) !== null && _link$metaData3 !== void 0 && _link$metaData3.getTabIndexBasedOnSearch ? link.metaData.getTabIndexBasedOnSearch(link, index) : (_link$metaData4 = link.metaData) === null || _link$metaData4 === void 0 ? void 0 : _link$metaData4.tabIndex;
      return /*#__PURE__*/React__default.createElement(SideNavLink, _extends({
        key: "menu-link-".concat(link.metaData.label.replace(/\s/g, ''), "-global"),
        "aria-label": link.metaData.label,
        onClick: link.metaData.onClick,
        href: link.metaData.href,
        renderIcon: link.icon,
        isActive: link.isActive,
        "data-testid": "".concat(testId, "-link-").concat(index),
        className: classnames(link.metaData.className, _defineProperty({}, "".concat(iotPrefix, "--side-nav__item--is-filtering"), isFiltering))
      }, link.metaData ? _objectSpread(_objectSpread({}, link.metaData), {}, {
        tabIndex: tabIndex
      }) : {}), content);
    }).filter(function (i) {
      return i;
    });
  };
  var _ref2 = hasSearch ? _partition([].concat(_toConsumableArray(recentLinks), _toConsumableArray(links)), function (link) {
      return link.isPinned;
    }) : [[], [].concat(_toConsumableArray(recentLinks), _toConsumableArray(links))],
    _ref3 = _slicedToArray(_ref2, 2),
    pinnedLinks = _ref3[0],
    filterableLinks = _ref3[1];
  var renderedPinnedLinks = renderLinks(pinnedLinks);
  var _useState = useState(renderLinks(filterableLinks)),
    _useState2 = _slicedToArray(_useState, 2),
    renderedFilterableLinks = _useState2[0],
    setRenderedFilterableLinks = _useState2[1];
  var _useState3 = useState(false),
    _useState4 = _slicedToArray(_useState3, 2),
    isFiltering = _useState4[0],
    setIsFiltering = _useState4[1];
  var handleSearchChange = function handleSearchChange(event) {
    var _event$target;
    var isSearching = 'value' in event.target && ((_event$target = event.target) === null || _event$target === void 0 ? void 0 : _event$target.value) !== '';
    var newSearchValue = isSearching ? event.target.value.toLowerCase() : undefined;
    setIsFiltering(isSearching);
    var linksToRender = isSearching ? filterLinks(filterableLinks, newSearchValue) : filterableLinks;
    setRenderedFilterableLinks(renderLinks(linksToRender, newSearchValue));
  };
  useEffect(function () {
    onFilterItems(renderedFilterableLinks);
  }, [onFilterItems, renderedFilterableLinks]);
  var search = hasSearch ? [/*#__PURE__*/React__default.createElement(Search, {
    key: "sidenav-search",
    id: "sidenav-search",
    "data-testid": "".concat(testId, "-search"),
    closeButtonLabelText: i18n.searchCloseButtonLabelText,
    placeholder: i18n.searchPlaceholder,
    labelText: i18n.searchLabelText,
    onChange: handleSearchChange,
    size: "md"
  })] : [];
  var staticSideNavContent = hasSearch && pinnedLinks.length ? [/*#__PURE__*/React__default.createElement(SideNavItems, {
    className: "".concat(iotPrefix, "--side-nav__pinned-items"),
    key: "pinned-side-nav-content"
  }, renderedPinnedLinks)] : [];
  var dynamicSideNavContent = isFiltering && renderedFilterableLinks.length === 0 ? /*#__PURE__*/React__default.createElement("div", {
    key: "empty-search",
    className: "".concat(iotPrefix, "--side-nav__empty-search-msg")
  }, i18n.emptySearchText) :
  /*#__PURE__*/
  // The key needed to pick up the change of `defaultExpanded` in the SideNavMenuItems
  React__default.createElement(SideNavItems, {
    key: "dynamic-side-nav-content-".concat(isFiltering)
  }, renderedFilterableLinks);

  // TODO: Will be added back in when footer is added for rails.
  // see: https://github.com/carbon-design-system/carbon/blob/main/packages/react/src/components/UIShell/SideNav.js#L143
  // const translateById = (id) =>
  //   id !== 'carbon.sidenav.state.closed' ? i18n.closeText : i18n.openText;

  return /*#__PURE__*/React__default.createElement(SideNav$2, _extends({
    "data-testid": testId,
    className: classnames("".concat(iotPrefix, "--side-nav"), _defineProperty(_defineProperty({}, "".concat(iotPrefix, "--side-nav--expanded"), isSideNavExpanded), "".concat(prefix, "--side-nav--expanded"), isSideNavExpanded)),
    expanded: isSideNavExpanded
    // TODO: Will be added back in when footer is added for rails.
    // see: https://github.com/carbon-design-system/carbon/blob/main/packages/react/src/components/UIShell/SideNav.js#L143
    // translateById={translateById}
    ,
    "aria-label": i18n.sideNavLabelText,
    defaultExpanded: defaultExpanded,
    isRail: true
  }, props), // We use an array for the children since CarbonSideNav can't handle null or
  // undefined being passed as a child so if hasSearch is false we don't pass anything.
  [].concat(search, staticSideNavContent, [dynamicSideNavContent]));
};
SideNav.propTypes = SideNavPropTypes;
SideNav.defaultProps = defaultProps;
SideNav$2.displayName = 'SideNav';
SideNavItems.displayName = 'SideNavItems';
SideNavLink.displayName = 'SideNavLink';
SideNavMenu.displayName = 'SideNavMenu';
SideNavMenuItem.displayName = 'SideNavMenuItem';
FilterableSideNavMenu.displayName = 'SideNavMenu';
SideNav.__docgenInfo = {
  "description": "Side Navigation. part of UI shell",
  "methods": [],
  "displayName": "SideNav",
  "props": {
    "defaultExpanded": {
      "defaultValue": {
        "value": "false",
        "computed": false
      },
      "description": "Specify whether the side navigation is expanded or collapsed",
      "type": {
        "name": "bool"
      },
      "required": false
    },
    "hasSearch": {
      "defaultValue": {
        "value": "false",
        "computed": false
      },
      "description": "Enables search functionality for the links",
      "type": {
        "name": "bool"
      },
      "required": false
    },
    "isSideNavExpanded": {
      "defaultValue": {
        "value": "false",
        "computed": false
      },
      "description": "",
      "type": {
        "name": "bool"
      },
      "required": false
    },
    "i18n": {
      "defaultValue": {
        "value": "{\n  closeText: 'Close',\n  openText: 'Open',\n  sideNavLabelText: 'Side navigation',\n  submenuLabel: 'dropdown',\n  emptySearchText: 'No matches found',\n  searchCloseButtonLabelText: 'Clear search input',\n  searchPlaceholder: 'Find navigation item...',\n  searchLabelText: 'Find navigation item',\n}",
        "computed": false
      },
      "description": "",
      "type": {
        "name": "shape",
        "value": {
          "closeText": {
            "name": "string",
            "required": false
          },
          "openText": {
            "name": "string",
            "required": false
          },
          "sideNavLabelText": {
            "name": "string",
            "required": false
          },
          "submenuLabel": {
            "name": "string",
            "required": false
          },
          "emptySearchText": {
            "name": "string",
            "required": false
          },
          "searchCloseButtonLabelText": {
            "name": "string",
            "required": false
          },
          "searchPlaceholder": {
            "name": "string",
            "required": false
          },
          "searchLabelText": {
            "name": "string",
            "required": false
          }
        }
      },
      "required": false
    },
    "testId": {
      "defaultValue": {
        "value": "'side-nav'",
        "computed": false
      },
      "description": "",
      "type": {
        "name": "string"
      },
      "required": false
    },
    "recentLinks": {
      "defaultValue": {
        "value": "[]",
        "computed": false
      },
      "description": "",
      "type": {
        "name": "arrayOf",
        "value": {
          "name": "shape",
          "value": {
            "isActive": {
              "name": "bool",
              "description": "is current link active",
              "required": false
            },
            "isEnabled": {
              "name": "bool",
              "description": "bot show/hide link",
              "required": false
            },
            "isPinned": {
              "name": "bool",
              "description": "pins the link to the top if hasSearch is true",
              "required": false
            },
            "metaData": {
              "name": "custom",
              "raw": "SideNavMetaDataPropType",
              "description": "Example:\n          // What to render for link\n          element: PropTypes.any,\n          // trigger something instead of follow link\n          onClick: PropTypes.func,\n          // url to link to\n          href: PropTypes.string,",
              "required": false
            },
            "icon": {
              "name": "custom",
              "raw": "CarbonIconPropType.isRequired",
              "description": "the icon component to render",
              "required": true
            },
            "linkContent": {
              "name": "string",
              "description": "string for the title of overall submenu",
              "required": false
            },
            "childContent": {
              "name": "arrayOf",
              "value": {
                "name": "shape",
                "value": {
                  "metaData": {
                    "name": "custom",
                    "raw": "SideNavMetaDataPropType",
                    "description": "Example:\n            // What to render for link\n            element: PropTypes.any,\n            // trigger something instead of follow link\n            onClick: PropTypes.func,\n            // url to link to\n            href: PropTypes.string,",
                    "required": false
                  },
                  "content": {
                    "name": "union",
                    "value": [{
                      "name": "string"
                    }, {
                      "name": "node"
                    }, {
                      "name": "bool"
                    }, {
                      "name": "func"
                    }],
                    "description": "content to render inside sub menu link",
                    "required": true
                  },
                  "isActive": {
                    "name": "bool",
                    "description": "is current link active",
                    "required": false
                  }
                }
              },
              "description": "array of child links to render in a subnav",
              "required": false
            }
          }
        }
      },
      "required": false
    },
    "onFilterItems": {
      "defaultValue": {
        "value": "() => {}",
        "computed": false
      },
      "description": "",
      "type": {
        "name": "func"
      },
      "required": false
    },
    "links": {
      "description": "array of link item objects",
      "type": {
        "name": "arrayOf",
        "value": {
          "name": "shape",
          "value": {
            "isActive": {
              "name": "bool",
              "description": "is current link active",
              "required": false
            },
            "isEnabled": {
              "name": "bool",
              "description": "bot show/hide link",
              "required": false
            },
            "isPinned": {
              "name": "bool",
              "description": "pins the link to the top if hasSearch is true",
              "required": false
            },
            "metaData": {
              "name": "custom",
              "raw": "SideNavMetaDataPropType",
              "description": "Example:\n          // What to render for link\n          element: PropTypes.any,\n          // trigger something instead of follow link\n          onClick: PropTypes.func,\n          // url to link to\n          href: PropTypes.string,",
              "required": false
            },
            "icon": {
              "name": "custom",
              "raw": "CarbonIconPropType.isRequired",
              "description": "the icon component to render",
              "required": true
            },
            "linkContent": {
              "name": "string",
              "description": "string for the title of overall submenu",
              "required": false
            },
            "childContent": {
              "name": "arrayOf",
              "value": {
                "name": "shape",
                "value": {
                  "metaData": {
                    "name": "custom",
                    "raw": "SideNavMetaDataPropType",
                    "description": "Example:\n            // What to render for link\n            element: PropTypes.any,\n            // trigger something instead of follow link\n            onClick: PropTypes.func,\n            // url to link to\n            href: PropTypes.string,",
                    "required": false
                  },
                  "content": {
                    "name": "union",
                    "value": [{
                      "name": "string"
                    }, {
                      "name": "node"
                    }, {
                      "name": "bool"
                    }, {
                      "name": "func"
                    }],
                    "description": "content to render inside sub menu link",
                    "required": true
                  },
                  "isActive": {
                    "name": "bool",
                    "description": "is current link active",
                    "required": false
                  }
                }
              },
              "description": "array of child links to render in a subnav",
              "required": false
            }
          }
        }
      },
      "required": true
    }
  }
};
var SideNav$1 = SideNav;

export { SideNavPropTypes, SideNav$1 as default };
