"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
var _typeof = require("@babel/runtime/helpers/typeof");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.ExtensionComponent = void 0;
var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
var _assertThisInitialized2 = _interopRequireDefault(require("@babel/runtime/helpers/assertThisInitialized"));
var _inherits2 = _interopRequireDefault(require("@babel/runtime/helpers/inherits"));
var _possibleConstructorReturn2 = _interopRequireDefault(require("@babel/runtime/helpers/possibleConstructorReturn"));
var _getPrototypeOf2 = _interopRequireDefault(require("@babel/runtime/helpers/getPrototypeOf"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = _interopRequireWildcard(require("react"));
var _memoizeOne = _interopRequireDefault(require("memoize-one"));
var _state = require("@atlaskit/editor-prosemirror/state");
var _extensions = require("../extensions");
var _utils = require("../utils");
var _Extension = _interopRequireDefault(require("./Extension/Extension"));
var _InlineExtension = _interopRequireDefault(require("./Extension/InlineExtension"));
var _MultiBodiedExtension = _interopRequireDefault(require("./MultiBodiedExtension"));
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 _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = (0, _getPrototypeOf2.default)(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = (0, _getPrototypeOf2.default)(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return (0, _possibleConstructorReturn2.default)(this, result); }; }
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
var ExtensionComponent = exports.ExtensionComponent = /*#__PURE__*/function (_Component) {
  (0, _inherits2.default)(ExtensionComponent, _Component);
  var _super = _createSuper(ExtensionComponent);
  function ExtensionComponent() {
    var _this;
    (0, _classCallCheck2.default)(this, ExtensionComponent);
    for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
      args[_key] = arguments[_key];
    }
    _this = _super.call.apply(_super, [this].concat(args));
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "privatePropsParsed", false);
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "state", {});
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "mounted", false);
    // memoized to avoid rerender on extension state changes
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "getNodeRenderer", (0, _memoizeOne.default)(_extensions.getNodeRenderer));
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "getExtensionModuleNodePrivateProps", (0, _memoizeOne.default)(_extensions.getExtensionModuleNodePrivateProps));
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "setIsNodeHovered", function (isHovered) {
      _this.setState({
        isNodeHovered: isHovered
      });
    });
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "setStateFromPromise", function (stateKey, promise) {
      promise && promise.then(function (p) {
        if (!_this.mounted) {
          return;
        }
        _this.setState((0, _defineProperty2.default)({}, stateKey, p));
      });
    });
    /**
     * Parses any private nodes once an extension provider is available.
     *
     * We do this separately from resolving a node renderer component since the
     * private props come from extension provider, rather than an extension
     * handler which only handles `render`/component concerns.
     */
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "parsePrivateNodePropsIfNeeded", /*#__PURE__*/(0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee() {
      var _this$props$node$attr, extensionType, extensionKey, privateProps;
      return _regenerator.default.wrap(function _callee$(_context) {
        while (1) switch (_context.prev = _context.next) {
          case 0:
            if (!(_this.privatePropsParsed || !_this.state.extensionProvider)) {
              _context.next = 2;
              break;
            }
            return _context.abrupt("return");
          case 2:
            _this.privatePropsParsed = true;
            _this$props$node$attr = _this.props.node.attrs, extensionType = _this$props$node$attr.extensionType, extensionKey = _this$props$node$attr.extensionKey;
            /**
             * getExtensionModuleNodePrivateProps can throw if there are issues in the
             * manifest
             */
            _context.prev = 4;
            _context.next = 7;
            return _this.getExtensionModuleNodePrivateProps(_this.state.extensionProvider, extensionType, extensionKey);
          case 7:
            privateProps = _context.sent;
            _this.setState({
              _privateProps: privateProps
            });
            _context.next = 14;
            break;
          case 11:
            _context.prev = 11;
            _context.t0 = _context["catch"](4);
            // eslint-disable-next-line no-console
            console.error('Provided extension handler has thrown an error\n', _context.t0);
            /** We don't want this error to block renderer */
            /** We keep rendering the default content */
          case 14:
          case "end":
            return _context.stop();
        }
      }, _callee, null, [[4, 11]]);
    })));
    (0, _defineProperty2.default)((0, _assertThisInitialized2.default)(_this), "handleExtension", function (pmNode, actions) {
      var _pmNode$marks;
      var _this$props = _this.props,
        extensionHandlers = _this$props.extensionHandlers,
        editorView = _this$props.editorView;
      var _pmNode$attrs = pmNode.attrs,
        extensionType = _pmNode$attrs.extensionType,
        extensionKey = _pmNode$attrs.extensionKey,
        parameters = _pmNode$attrs.parameters,
        text = _pmNode$attrs.text;
      var isBodiedExtension = pmNode.type.name === 'bodiedExtension';
      if (isBodiedExtension) {
        return;
      }
      var fragmentLocalId = pmNode === null || pmNode === void 0 || (_pmNode$marks = pmNode.marks) === null || _pmNode$marks === void 0 || (_pmNode$marks = _pmNode$marks.find(function (m) {
        return m.type.name === 'fragment';
      })) === null || _pmNode$marks === void 0 || (_pmNode$marks = _pmNode$marks.attrs) === null || _pmNode$marks === void 0 ? void 0 : _pmNode$marks.localId;
      var node = {
        type: pmNode.type.name,
        extensionType: extensionType,
        extensionKey: extensionKey,
        parameters: parameters,
        content: text,
        localId: pmNode.attrs.localId,
        fragmentLocalId: fragmentLocalId
      };
      var result;
      if (extensionHandlers && extensionHandlers[extensionType]) {
        var render = (0, _utils.getExtensionRenderer)(extensionHandlers[extensionType]);
        result = render(node, editorView.state.doc, actions);
      }
      if (!result) {
        var extensionHandlerFromProvider = _this.state.extensionProvider && _this.getNodeRenderer(_this.state.extensionProvider, extensionType, extensionKey);
        if (extensionHandlerFromProvider) {
          var NodeRenderer = extensionHandlerFromProvider;
          if (node.type === 'multiBodiedExtension') {
            return /*#__PURE__*/_react.default.createElement(NodeRenderer, {
              node: node,
              references: _this.props.references,
              actions: actions
            });
          } else {
            return /*#__PURE__*/_react.default.createElement(NodeRenderer, {
              node: node,
              references: _this.props.references
            });
          }
        }
      }
      return result;
    });
    return _this;
  }
  (0, _createClass2.default)(ExtensionComponent, [{
    key: "UNSAFE_componentWillMount",
    value: function UNSAFE_componentWillMount() {
      this.mounted = true;
    }
  }, {
    key: "componentDidMount",
    value: function componentDidMount() {
      var extensionProvider = this.props.extensionProvider;
      if (extensionProvider) {
        this.setStateFromPromise('extensionProvider', extensionProvider);
      }
    }
  }, {
    key: "componentDidUpdate",
    value: function componentDidUpdate() {
      this.parsePrivateNodePropsIfNeeded();
    }
  }, {
    key: "componentWillUnmount",
    value: function componentWillUnmount() {
      this.mounted = false;
    }
  }, {
    key: "UNSAFE_componentWillReceiveProps",
    value: function UNSAFE_componentWillReceiveProps(nextProps) {
      var extensionProvider = nextProps.extensionProvider;
      if (extensionProvider && this.props.extensionProvider !== extensionProvider) {
        this.setStateFromPromise('extensionProvider', extensionProvider);
      }
    }
  }, {
    key: "render",
    value: function render() {
      var _this$state$_privateP;
      var _this$props2 = this.props,
        node = _this$props2.node,
        handleContentDOMRef = _this$props2.handleContentDOMRef,
        editorView = _this$props2.editorView,
        references = _this$props2.references,
        editorAppearance = _this$props2.editorAppearance,
        pluginInjectionApi = _this$props2.pluginInjectionApi,
        getPos = _this$props2.getPos,
        eventDispatcher = _this$props2.eventDispatcher,
        showMacroInteractionDesignUpdates = _this$props2.showMacroInteractionDesignUpdates;
      var selection = editorView.state.selection;
      var selectedNode = selection instanceof _state.NodeSelection && selection.node;
      var position = typeof getPos === 'function' && getPos();
      var resolvedPosition = position && editorView.state.doc.resolve(position);
      var isNodeNested = !!(resolvedPosition && resolvedPosition.depth > 0);
      if (node.type.name === 'multiBodiedExtension') {
        return /*#__PURE__*/_react.default.createElement(_MultiBodiedExtension.default, {
          node: node,
          editorView: editorView,
          getPos: getPos,
          handleContentDOMRef: handleContentDOMRef,
          tryExtensionHandler: this.tryExtensionHandler.bind(this),
          eventDispatcher: eventDispatcher,
          pluginInjectionApi: pluginInjectionApi,
          editorAppearance: editorAppearance,
          showMacroInteractionDesignUpdates: showMacroInteractionDesignUpdates,
          isNodeSelected: selectedNode === node,
          isNodeNested: isNodeNested,
          isNodeHovered: this.state.isNodeHovered,
          setIsNodeHovered: this.setIsNodeHovered
        });
      }
      var extensionHandlerResult = this.tryExtensionHandler(undefined);
      switch (node.type.name) {
        case 'extension':
        case 'bodiedExtension':
          return /*#__PURE__*/_react.default.createElement(_Extension.default, {
            node: node,
            getPos: this.props.getPos,
            references: references,
            extensionProvider: this.state.extensionProvider,
            handleContentDOMRef: handleContentDOMRef,
            view: editorView,
            editorAppearance: editorAppearance,
            hideFrame: (_this$state$_privateP = this.state._privateProps) === null || _this$state$_privateP === void 0 ? void 0 : _this$state$_privateP.__hideFrame,
            pluginInjectionApi: pluginInjectionApi,
            showMacroInteractionDesignUpdates: showMacroInteractionDesignUpdates,
            isNodeSelected: selectedNode === node,
            isNodeHovered: this.state.isNodeHovered,
            isNodeNested: isNodeNested,
            setIsNodeHovered: this.setIsNodeHovered
          }, extensionHandlerResult);
        case 'inlineExtension':
          return /*#__PURE__*/_react.default.createElement(_InlineExtension.default, {
            node: node,
            showMacroInteractionDesignUpdates: showMacroInteractionDesignUpdates,
            isNodeSelected: selectedNode === node,
            pluginInjectionApi: pluginInjectionApi,
            isNodeHovered: this.state.isNodeHovered,
            setIsNodeHovered: this.setIsNodeHovered
          }, extensionHandlerResult);
        default:
          return null;
      }
    }
  }, {
    key: "tryExtensionHandler",
    value: function tryExtensionHandler(actions) {
      var node = this.props.node;
      try {
        var extensionContent = this.handleExtension(node, actions);
        if (extensionContent && /*#__PURE__*/_react.default.isValidElement(extensionContent)) {
          return extensionContent;
        }
      } catch (e) {
        // eslint-disable-next-line no-console
        console.error('Provided extension handler has thrown an error\n', e);
        /** We don't want this error to block renderer */
        /** We keep rendering the default content */
      }
      return null;
    }
  }]);
  return ExtensionComponent;
}(_react.Component);