import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
// (C) 2007-2026 GoodData Corporation
import { PureComponent, createRef } from "react";
import cx from "classnames";
import { Bubble } from "../Bubble/Bubble.js";
import { BubbleHoverTrigger } from "../Bubble/BubbleHoverTrigger.js";
// ShortenText adds ellipsis (…) in the middle of the string.
// SIDE_SCALE_RATIO is a constant which tells the percentage of
// of the string characters to be taken from both sides to produce
// final shortened string
function getElementWidth(element) {
    return Math.ceil(element.getBoundingClientRect().width);
}
export function getShortenedTitle(title, element, ellipsisPosition = "middle") {
    const elementWidth = getElementWidth(element);
    const { scrollWidth } = element;
    if (elementWidth >= scrollWidth) {
        return title;
    }
    const titleLength = title.length;
    const numChars = titleLength * (elementWidth / scrollWidth);
    if (ellipsisPosition === "middle") {
        const SIDE_SCALE_RATIO = 0.42;
        const numCharsSideStrip = Math.floor(numChars * SIDE_SCALE_RATIO);
        const pre = title.substr(0, numCharsSideStrip);
        const post = title.substr(titleLength - numCharsSideStrip, titleLength);
        return `${pre}…${post}`;
    }
    else {
        const SIDE_SCALE_RATIO = 1;
        const numCharsSideStrip = Math.floor(numChars * SIDE_SCALE_RATIO);
        const pre = title.substr(0, numCharsSideStrip - 3); // -3 for ellipsis
        return `${pre}…`;
    }
}
/**
 * To make this component work, parent container needs this:
 *      max-width: Xpx;
 *      white-space: nowrap;
 *
 * and the component itself needs:
 *      display: inline-block;
 *      width: 100%;
 *      white-space: nowrap;
 */
/**
 * @internal
 */
export class ShortenedText extends PureComponent {
    static defaultProps = {
        className: "",
        tagName: "span",
        tooltipAlignPoints: [{ align: "cr cl" }],
        tooltipVisibleOnMouseOver: false,
        getElement(context) {
            // Necessary for testing width in JSDOM env.
            return context.textRef.current;
        },
        displayTooltip: true,
        ellipsisPosition: "middle",
    };
    textRef = createRef();
    constructor(props) {
        super(props);
        this.state = {
            title: props.children,
            customTitle: false,
        };
    }
    componentDidMount() {
        this.checkTitle();
    }
    UNSAFE_componentWillReceiveProps(nextProps) {
        if (this.props.children !== nextProps.children) {
            this.setState({
                title: nextProps.children,
                customTitle: false,
            });
        }
    }
    componentDidUpdate() {
        if (this.state.customTitle) {
            return;
        }
        this.checkTitle();
    }
    checkTitle() {
        const element = this.props.getElement(this);
        const title = this.props.children;
        const elementWidth = getElementWidth(element);
        const ellipsisPosition = this.props.ellipsisPosition;
        if (elementWidth > 0 && elementWidth < element.scrollWidth) {
            this.setState({ title: getShortenedTitle(title, element, ellipsisPosition), customTitle: true });
        }
        else {
            this.setState({
                title: this.props.children,
                customTitle: false,
            });
        }
    }
    recomputeShortening() {
        this.checkTitle();
    }
    renderTextWithBubble() {
        return (_jsxs(BubbleHoverTrigger, { showDelay: 0, hideDelay: 0, eventsOnBubble: this.props.tooltipVisibleOnMouseOver, children: [
                _jsx(Bubble, { alignPoints: this.props.tooltipAlignPoints, children: this.state.customTitle ? this.props.children : "" }), this.renderText()] }));
    }
    renderText() {
        const TagName = this.props.tagName;
        const isShortened = this.state.customTitle;
        return (_jsx(TagName, { ref: this.textRef, className: cx(this.props.className, "shortened", {
                "is-shortened": isShortened,
                "is-whole": !isShortened,
            }), id: this.props.id, children: isShortened ? (_jsxs(_Fragment, { children: [
                    _jsx("span", { "aria-hidden": "true", children: this.state.title }), _jsx("span", { className: "sr-only", children: this.props.children })
                ] })) : (this.state.title) }));
    }
    render() {
        if (this.state.customTitle && this.props.displayTooltip) {
            return this.renderTextWithBubble();
        }
        return this.renderText();
    }
}
