import React from 'react';
import debounce from 'lodash/debounce';
import shallowEqual from 'shallowequal';
import { st, classes } from './Ellipsis.st.css.js';
import Tooltip from '../../Tooltip';
import { ZIndex } from '../ZIndex';
import TextComponent from './components/TextComponent';
class Ellipsis extends React.PureComponent {
    constructor(props) {
        super(props);
        /**
         * Once text component has rendered,
         * Update text content and tooltip active state
         * @private
         */
        this._onTextRendered = () => {
            const { isActive, textContent } = this.state;
            const newTextContent = this._getTextContent();
            const shouldBeActive = this._checkShouldBeActive();
            const newState = {
                textRendered: true,
                ...(newTextContent !== textContent
                    ? { textContent: newTextContent }
                    : {}),
                ...(shouldBeActive !== isActive ? { isActive: shouldBeActive } : {}),
            };
            this.setState(oldState => ({ ...oldState, ...newState }));
        };
        /**
         * An ellipsis is considered active when either the text's scroll width/height is wider than it's container or itself.
         * @private
         */
        this._updateIsActive = () => {
            const { isActive } = this.state;
            const shouldBeActive = this._checkShouldBeActive();
            if (shouldBeActive !== isActive) {
                this.setState({ isActive: shouldBeActive });
            }
        };
        this._getTextContent = () => {
            const { current: textElement } = this.ref;
            return textElement && textElement.textContent;
        };
        this._checkShouldBeActive = () => this._isOverflowingHorizontally() || this._isOverflowingVertically();
        this._isOverflowingHorizontally = () => {
            const { current: textElement } = this.ref;
            const { ellipsis } = this.props;
            const parentWidth = textElement?.parentElement?.offsetWidth;
            return !!(ellipsis &&
                textElement &&
                ((parentWidth && textElement.scrollWidth - parentWidth > 1) ||
                    textElement.offsetWidth < textElement.scrollWidth));
        };
        this._isOverflowingVertically = () => {
            const { current: textElement } = this.ref;
            const { ellipsis, maxLines } = this.props;
            const parentHeight = textElement?.parentElement?.offsetHeight;
            return !!(maxLines &&
                maxLines > 1 &&
                ellipsis &&
                textElement &&
                ((parentHeight && textElement.scrollHeight - parentHeight > 1) ||
                    textElement.offsetHeight < textElement.scrollHeight));
        };
        /**
         * A callback for resizing the window, must be debounced in order to improve performance.
         * @private
         */
        this._debouncedUpdate = debounce(this._updateIsActive, 100);
        this.state = {
            isActive: false,
            textContent: null,
            textRendered: false,
        };
        this.ref = React.createRef();
        this.tooltipRef = React.createRef();
    }
    componentDidMount() {
        window.addEventListener('resize', this._debouncedUpdate);
        this.props.onEllipsisStateChange?.(this.state.isActive);
    }
    _renderText() {
        const { render, ellipsis, maxLines } = this.props;
        const { textRendered, isActive } = this.state;
        return (React.createElement(TextComponent, { render, ellipsis, maxLines, textRendered, onTextRendered: this._onTextRendered, textElementRef: this.ref, isEllipsisActive: isActive, tooltipRef: this.tooltipRef }));
    }
    render() {
        const { appendTo, wrapperClassName, disabled, enterDelay, exitDelay, fixed, flip, maxWidth, moveArrowTo, moveBy, onHide, onShow, placement, showTooltip, textAlign, zIndex, size, interactive, } = this.props;
        const { isActive, textContent } = this.state;
        return showTooltip && isActive ? (React.createElement(Tooltip, { ref: this.tooltipRef, className: st(classes.tooltip, wrapperClassName), content: textContent, appendTo,
            disabled,
            enterDelay,
            exitDelay,
            fixed,
            flip,
            maxWidth,
            moveArrowTo,
            moveBy,
            onHide,
            onShow,
            placement,
            textAlign,
            zIndex,
            size,
            interactive }, this._renderText())) : (this._renderText());
    }
    static getDerivedStateFromProps(props, state) {
        const { render, ellipsis, maxLines } = props;
        const textPropsChanged = state.prevRender !== render ||
            state.prevEllipsis !== ellipsis ||
            state.prevMaxLines !== maxLines;
        if (!textPropsChanged) {
            return null;
        }
        // Text changed, initialize textRendered state
        return {
            textRendered: false,
            prevRender: render,
            prevEllipsis: ellipsis,
            prevMaxLines: maxLines,
        };
    }
    componentDidUpdate(prevProps, prevState) {
        const { textRendered, isActive } = this.state;
        if (textRendered && !shallowEqual(prevProps, this.props)) {
            this._updateIsActive();
        }
        if (prevState.isActive !== isActive && this.props.onEllipsisStateChange) {
            this.props.onEllipsisStateChange(this.state.isActive);
        }
    }
    componentWillUnmount() {
        this._debouncedUpdate.cancel();
        window.removeEventListener('resize', this._debouncedUpdate);
    }
}
Ellipsis.defaultProps = {
    ellipsis: false,
    appendTo: 'window',
    flip: false,
    fixed: false,
    placement: 'top',
    zIndex: ZIndex.tooltip,
    enterDelay: 0,
    exitDelay: 0,
    showTooltip: true,
};
export default Ellipsis;
//# sourceMappingURL=Ellipsis.js.map