import _extends from "@babel/runtime/helpers/extends";
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import React from 'react';
import { ShadowObserver, shadowObserverClassNames } from './shadowObserver';
export const shadowClassNames = {
  RIGHT_SHADOW: 'right-shadow',
  LEFT_SHADOW: 'left-shadow'
};
export default function overflowShadow(Component, options) {
  return class OverflowShadow extends React.Component {
    constructor(...args) {
      super(...args);
      _defineProperty(this, "overflowContainerWidth", 0);
      _defineProperty(this, "state", {
        showLeftShadow: false,
        showRightShadow: false
      });
      _defineProperty(this, "handleScroll", event => {
        if (!this.overflowContainer || event.target !== this.overflowContainer || options.useShadowObserver) {
          return;
        }
        this.updateShadows();
      });
      _defineProperty(this, "updateShadows", () => {
        if (options.useShadowObserver) {
          return;
        }
        this.setState(prevState => {
          if (!this.overflowContainer) {
            return;
          }
          const diff = this.calcOverflowDiff();
          const showRightShadow = diff > 0 && diff > this.overflowContainer.scrollLeft;
          const showLeftShadow = this.showLeftShadow(this.overflowContainer);
          if (showLeftShadow !== prevState.showLeftShadow || showRightShadow !== this.state.showRightShadow) {
            return {
              showLeftShadow,
              showRightShadow
            };
          }
          return null;
        });
      });
      _defineProperty(this, "showLeftShadow", overflowContainer => {
        return !!overflowContainer && overflowContainer.scrollLeft > 0;
      });
      _defineProperty(this, "calcOverflowDiff", () => {
        if (!this.overflowContainer) {
          return 0;
        }
        this.diff = this.calcScrollableWidth();
        return this.diff - this.overflowContainer.offsetWidth;
      });
      _defineProperty(this, "calcScrollableWidth", () => {
        if (!this.scrollable && this.overflowContainer) {
          return this.overflowContainer.scrollWidth;
        }
        if (!this.scrollable) {
          return 0;
        }
        let width = 0;
        for (let i = 0; i < this.scrollable.length; i++) {
          const scrollableElement = this.scrollable[i];
          if (isElementNode(scrollableElement)) {
            width += scrollableElement.scrollWidth;
          }
        }
        return width;
      });
      _defineProperty(this, "handleContainer", container => {
        if (!container || this.container) {
          return;
        }
        this.container = container;
        this.overflowContainer = container.querySelector(options.overflowSelector);
        if (!this.overflowContainer) {
          this.overflowContainer = container;
        }
        if (options.useShadowObserver) {
          this.initShadowObserver();
          return;
        }
        this.updateShadows();
        // Ignored via go/ees005
        // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
        this.overflowContainer.addEventListener('scroll', this.handleScroll);
      });
    }
    componentWillUnmount() {
      if (options.useShadowObserver) {
        return this.shadowObserver && this.shadowObserver.dispose();
      }
      if (this.overflowContainer) {
        // Ignored via go/ees005
        // eslint-disable-next-line @repo/internal/dom-events/no-unsafe-event-listeners
        this.overflowContainer.removeEventListener('scroll', this.handleScroll);
      }
      this.updateShadows();
    }
    componentDidUpdate() {
      if (!options.useShadowObserver) {
        this.updateShadows();
      }
    }
    initShadowObserver() {
      if (this.shadowObserver || !this.overflowContainer) {
        return;
      }
      this.shadowObserver = new ShadowObserver({
        scrollContainer: this.overflowContainer,
        onUpdateShadows: shadowStates => {
          this.setState(prevState => {
            const {
              showLeftShadow,
              showRightShadow
            } = shadowStates;
            if (showLeftShadow !== prevState.showLeftShadow || showRightShadow !== prevState.showRightShadow) {
              return {
                showLeftShadow,
                showRightShadow
              };
            }
            return null;
          });
        }
      });
    }
    render() {
      var _this$props, _this$props2;
      const {
        showLeftShadow,
        showRightShadow
      } = this.state;
      const classNames = [!((_this$props = this.props) !== null && _this$props !== void 0 && _this$props.disableTableOverflowShadow) && showRightShadow && shadowClassNames.RIGHT_SHADOW, !((_this$props2 = this.props) !== null && _this$props2 !== void 0 && _this$props2.disableTableOverflowShadow) && showLeftShadow && shadowClassNames.LEFT_SHADOW, options.useShadowObserver && shadowObserverClassNames.SHADOW_CONTAINER].filter(Boolean).join(' ');

      /**
       * The widths have already been calculated to determine
       * showRightShadow and showLeftShadow. If either is true,
       * then the content is scrollable and we need to set the
       * tabIndex to 0 to allow the user to scroll the content
       * for a11y purposes.
       */
      const hasOverflowScroll = showRightShadow || showLeftShadow;
      return /*#__PURE__*/React.createElement(Component, _extends({
        handleRef: this.handleContainer,
        tabIndex: hasOverflowScroll ? 0 : undefined,
        shadowClassNames: classNames
        // eslint-disable-next-line react/jsx-props-no-spreading -- Spreading props to pass all component props through to wrapped generic component
      }, this.props));
    }
  };
}

// Helper function to check if the passed node is of Element class
function isElementNode(node) {
  return node.nodeType === 1;
}