"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.createPortalRendererComponent = createPortalRendererComponent;
exports.getPortalProviderAPI = void 0;
exports.usePortalProvider = usePortalProvider;
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
var _react = _interopRequireWildcard(require("react"));
var _reactDom = require("react-dom");
var _PortalBucket = require("./PortalBucket");
var _PortalManager = require("./PortalManager");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != _typeof(e) && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function createPortalRendererComponent(portalManager) {
  return function PortalRenderer() {
    var _useState = (0, _react.useState)(portalManager.getBuckets()),
      _useState2 = (0, _slicedToArray2.default)(_useState, 2),
      buckets = _useState2[0],
      setBuckets = _useState2[1];
    (0, _react.useLayoutEffect)(function () {
      portalManager.registerPortalRenderer(setBuckets);
      return function () {
        portalManager.unregisterPortalRenderer();
      };
    }, []);
    var portalsElements = (0, _react.useMemo)(function () {
      return buckets.map(function (_, i) {
        return /*#__PURE__*/_react.default.createElement(_PortalBucket.PortalBucket, {
          key: i,
          id: i,
          portalManager: portalManager
        });
      });
    }, [buckets]);
    return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, portalsElements);
  };
}

/**
 * Creates a portal provider for managing multiple React portals. The provider
 * facilitates rendering, removing, and destroying portals managed by a given
 * PortalManager.
 *
 * @param {PortalManager} portalManager - An instance of a PortalManager which
 * is responsible for registering, managing, and destroying portals.
 * @returns {PortalProviderAPI} An object containing methods to render, remove, and destroy
 * portals.
 *  - `render(children, container, key)` Renders a new React portal with the given
 *    children, mounts it into the specified DOM container, and registers it
 *    with the PortalManager using a unique key.
 *  - `remove(key)` Removes a previously rendered portal identified by its key
 *    and deregisters it from the PortalManager.
 *  - `destroy()` Clears all portals managed by this provider and invokes the
 *    destroy method on the PortalManager to clean up any resources.
 *
 */
var getPortalProviderAPI = exports.getPortalProviderAPI = function getPortalProviderAPI(portalManager) {
  var portalsMap = new Map();
  return {
    render: function render(children, container, key) {
      var portal = /*#__PURE__*/(0, _reactDom.createPortal)(children(), container, key);
      portalsMap.set(key, portalManager.registerPortal(key, portal));
    },
    remove: function remove(key) {
      var _portalsMap$get;
      (_portalsMap$get = portalsMap.get(key)) === null || _portalsMap$get === void 0 || _portalsMap$get();
      portalsMap.delete(key);
    },
    destroy: function destroy() {
      portalsMap.clear();
      portalManager.destroy();
    }
  };
};

/**
 * Initializes PortalManager and creates PortalRendererComponent. Offers an API (portalProviderAPI) for managing portals.
 * @returns {[PortalProviderAPI, PortalRendererComponent]} An array containing two elements:
 *         1. portalProviderAPI: An object providing an API for rendering and removing portals.
 *         2. PortalRenderer: A React component responsible for rendering the portal content.
 */
function usePortalProvider() {
  var portalManager = (0, _react.useMemo)(function () {
    return new _PortalManager.PortalManager();
  }, []);
  var PortalRenderer = (0, _react.useMemo)(function () {
    return createPortalRendererComponent(portalManager);
  }, [portalManager]);
  var portalProviderAPI = (0, _react.useMemo)(function () {
    return getPortalProviderAPI(portalManager);
  }, [portalManager]);

  // Cleanup on unmount
  (0, _react.useEffect)(function () {
    return function () {
      portalProviderAPI.destroy();
    };
  }, [portalManager, portalProviderAPI]);
  return [portalProviderAPI, PortalRenderer];
}