import React from 'react';
import { fg } from '@atlaskit/platform-feature-flags';
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
import ReactNodeView from '../react-node-view';
import { Extension } from './Extension';
import { ExtensionNodeWrapper } from './ExtensionNodeWrapper';
// getInlineNodeViewProducer is a new api to use instead of ReactNodeView
// when creating inline node views, however, it is difficult to test the impact
// on selections when migrating inlineExtension to use the new api.
// The ReactNodeView api will be visited in the second phase of the selections
// project whilst investigating block nodes. We will revisit the Extension node view there too.
export class ExtensionNode extends ReactNodeView {
  ignoreMutation(mutation) {
    // Extensions can perform async operations that will change the DOM.
    // To avoid having their tree rebuilt, we need to ignore the mutation
    // for atom based extensions if its not a layout, we need to give
    // children a chance to recalc
    return this.node.type.isAtom || mutation.type !== 'selection' && mutation.attributeName !== 'data-layout';
  }

  // Reserve height by setting a minimum height for the extension node view element
  createDomRef() {
    if (!fg('confluence_connect_macro_preset_height')) {
      return super.createDomRef();
    }
    if (!this.node.isInline) {
      var _this$reactComponentP, _this$reactComponentP2, _this$reactComponentP3;
      const htmlElement = document.createElement('div');
      const extensionHeight = (_this$reactComponentP = this.reactComponentProps) === null || _this$reactComponentP === void 0 ? void 0 : (_this$reactComponentP2 = _this$reactComponentP.extensionNodeViewOptions) === null || _this$reactComponentP2 === void 0 ? void 0 : (_this$reactComponentP3 = _this$reactComponentP2.getExtensionHeight) === null || _this$reactComponentP3 === void 0 ? void 0 : _this$reactComponentP3.call(_this$reactComponentP2, this.node);
      if (extensionHeight) {
        htmlElement.style.setProperty('min-height', `${extensionHeight}px`);
      }
      return htmlElement;
    }
    const htmlElement = document.createElement('span');
    return htmlElement;
  }

  /**
   * When interacting with input elements inside an extension's body, the events
   * bubble up to the editor and get handled by it. This almost always gets in the way
   * of being able to actually interact with said input in the extension, i.e.
   * typing inside a text field (in an extension body) will print the text in the editor
   * content area instead. This change prevents the editor view from trying to handle these events,
   * when the target of the event is an input element, so the extension can.
   */
  stopEvent(event) {
    if (fg('forge-ui-extensionnodeview-stop-event-for-textarea')) {
      return event.target instanceof HTMLInputElement || event.target instanceof HTMLTextAreaElement;
    }
    return event.target instanceof HTMLInputElement;
  }
  getContentDOM() {
    var _this$reactComponentP4, _this$reactComponentP5;
    if (this.node.isInline) {
      return;
    }
    const contentDomWrapper = document.createElement('div');
    contentDomWrapper.className = `${this.node.type.name}-content-dom-wrapper`;
    const isBodiedExtension = this.node.type.name === 'bodiedExtension';
    const showMacroInteractionDesignUpdates = (_this$reactComponentP4 = this.reactComponentProps) === null || _this$reactComponentP4 === void 0 ? void 0 : (_this$reactComponentP5 = _this$reactComponentP4.macroInteractionDesignFeatureFlags) === null || _this$reactComponentP5 === void 0 ? void 0 : _this$reactComponentP5.showMacroInteractionDesignUpdates;
    if (isBodiedExtension && showMacroInteractionDesignUpdates && expValEquals('platform_editor_bodiedextension_layoutshift_fix', 'isEnabled', true)) {
      // Create outer wrapper to hold space for the lozenge
      const outerWrapper = document.createElement('div');
      outerWrapper.className = `${this.node.type.name}-content-outer-wrapper`;

      // Create inner wrapper to position inner content
      const innerWrapper = document.createElement('div');
      innerWrapper.className = `${this.node.type.name}-content-inner-wrapper`;
      innerWrapper.appendChild(contentDomWrapper);
      outerWrapper.appendChild(innerWrapper);
      return {
        dom: outerWrapper,
        contentDOM: contentDomWrapper
      };
    }
    return {
      dom: contentDomWrapper
    };
  }
  render(props, forwardRef) {
    var _props$extensionNodeV;
    return /*#__PURE__*/React.createElement(ExtensionNodeWrapper, {
      nodeType: this.node.type.name,
      macroInteractionDesignFeatureFlags: props.macroInteractionDesignFeatureFlags
    }, /*#__PURE__*/React.createElement(Extension, {
      editorView: this.view,
      node: this.node,
      eventDispatcher: this.eventDispatcher
      // The getPos arg is always a function when used with nodes
      // the version of the types we use has a union with the type
      // for marks.
      // This has been fixed in later versions of the definitly typed
      // types (and also in prosmirror-views inbuilt types).
      // https://github.com/DefinitelyTyped/DefinitelyTyped/pull/57384
      ,
      getPos: this.getPos,
      providerFactory: props.providerFactory,
      handleContentDOMRef: forwardRef,
      extensionHandlers: props.extensionHandlers,
      editorAppearance: (_props$extensionNodeV = props.extensionNodeViewOptions) === null || _props$extensionNodeV === void 0 ? void 0 : _props$extensionNodeV.appearance,
      pluginInjectionApi: props.pluginInjectionApi,
      macroInteractionDesignFeatureFlags: props.macroInteractionDesignFeatureFlags,
      showLivePagesBodiedMacrosRendererView: props.showLivePagesBodiedMacrosRendererView,
      showUpdatedLivePages1PBodiedExtensionUI: props.showUpdatedLivePages1PBodiedExtensionUI,
      rendererExtensionHandlers: props.rendererExtensionHandlers
    }));
  }
}
export default function ExtensionNodeView(portalProviderAPI, eventDispatcher, providerFactory, extensionHandlers, extensionNodeViewOptions, pluginInjectionApi, macroInteractionDesignFeatureFlags, showLivePagesBodiedMacrosRendererView, showUpdatedLivePages1PBodiedExtensionUI, rendererExtensionHandlers) {
  return (node, view, getPos) => {
    return new ExtensionNode(node, view, getPos, portalProviderAPI, eventDispatcher, {
      providerFactory,
      extensionHandlers,
      extensionNodeViewOptions,
      pluginInjectionApi,
      macroInteractionDesignFeatureFlags,
      showLivePagesBodiedMacrosRendererView,
      showUpdatedLivePages1PBodiedExtensionUI,
      rendererExtensionHandlers
    }).init();
  };
}