import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
// (C) 2024-2025 GoodData Corporation
import { useCallback, useEffect, useRef, } from "react";
import cx from "classnames";
import { useIntl } from "react-intl";
import Markdown from "react-markdown";
import { IntlWrapper, LoadingComponent } from "@gooddata/sdk-ui";
import { useEvaluatedReferences } from "./hooks/useEvaluatedReferences.js";
import { rehypeReferences } from "./plugins/rehype-references.js";
import { remarkReferences } from "./plugins/remark-references.js";
// lineHeight from CSS, used to calculate max textarea height based on provided row count
const RICH_TEXT_TEXTAREA_ROW_HEIGHT = 19;
const RICH_TEXT_PLACEHOLDER = `
# Heading 1
**Bold**
* List
[link](http://thisisalink.com)
![image](http://url/img.png)
{metric/metric_id}
{label/label_id}
`;
function DefaultLoadingComponent() {
    return _jsx(LoadingComponent, {});
}
function RichTextCore({ value, execConfig, onChange, referencesEnabled, renderMode = "view", editPlaceholder, editRows, emptyElement, className, autoResize, rawContent, filters, isFiltersLoading, separators, onLoadingChanged, onError, LoadingComponent, }) {
    return (_jsxs("div", { className: cx([
            "gd-rich-text-content",
            `gd-rich-text-content-${renderMode}`,
            "s-rich-text",
            `s-rich-text-${renderMode}`,
            { "gd-visible-scrollbar": renderMode === "view" },
            className,
        ]), children: [renderMode === "edit" ? (_jsx(RichTextEdit, { value: value, onChange: (updatedValue) => onChange?.(updatedValue), placeholder: editPlaceholder, rows: editRows, autoResize: autoResize })) : (_jsx(RichTextView, { value: value, filters: filters, isFiltersLoading: isFiltersLoading, separators: separators, referencesEnabled: referencesEnabled, LoadingComponent: LoadingComponent, onLoadingChanged: onLoadingChanged, onError: onError, emptyElement: emptyElement, execConfig: execConfig })), rawContent?.show ? _jsx("input", { type: "hidden", value: value, ...rawContent.dataAttributes }) : null] }));
}
function RichTextEdit({ value, onChange, placeholder, rows = 10, autoResize = false }) {
    const textareaRef = useRef(null);
    const intl = useIntl();
    const placeholderText = placeholder ?? `${intl.formatMessage({ id: "richText.placeholder" })}\n${RICH_TEXT_PLACEHOLDER}`;
    const moveCaretToEnd = (event) => {
        const { value } = event.target;
        const position = value.length;
        event.target.setSelectionRange(position, position);
    };
    const handleInput = useCallback(() => {
        if (autoResize) {
            const textarea = textareaRef.current;
            if (!textarea) {
                return;
            }
            // Reset height to calculate new content height
            textarea.style.height = "auto";
            // Get the scroll height to adjust dynamically
            const scrollHeight = textarea.scrollHeight;
            // Set maxHeight equivalent to the number of provided rows
            const maxHeight = RICH_TEXT_TEXTAREA_ROW_HEIGHT * rows;
            // Apply height up to maxHeight, and allow scrolling if content exceeds it
            textarea.style.height = `${Math.min(scrollHeight, maxHeight)}px`;
            textarea.style.overflowY = scrollHeight > maxHeight ? "scroll" : "hidden";
        }
    }, [autoResize, rows]);
    // the effect will be called just once during initialization to set the textarea height
    useEffect(() => {
        handleInput();
    }, [handleInput]);
    return (_jsx("textarea", { ref: textareaRef, className: "gd-visible-scrollbar", value: value, autoFocus: true, placeholder: placeholderText, onChange: (event) => onChange(event.target.value), onInput: handleInput, rows: autoResize ? 1 : rows, onFocus: moveCaretToEnd }));
}
const imageStyle = { maxWidth: "100%" };
function ImageComponent(props) {
    return _jsx("img", { style: imageStyle, ...props });
}
function AnchorComponent(props) {
    return _jsx("a", { target: "_blank", rel: "noopener noreferrer", ...props });
}
function RichTextView({ value, referencesEnabled, emptyElement, filters, isFiltersLoading, separators, execConfig, onError, onLoadingChanged, LoadingComponent = DefaultLoadingComponent, }) {
    const intl = useIntl();
    const { loading, metrics, isEmptyValue, error } = useEvaluatedReferences(value, filters ?? [], {
        enabled: referencesEnabled ?? false,
        isFiltersLoading,
        ...execConfig,
    });
    useEffect(() => {
        onLoadingChanged?.({
            isLoading: loading,
        });
    }, [onLoadingChanged, loading]);
    useEffect(() => {
        if (error) {
            onError?.(error);
        }
    }, [error, onError]);
    if (isEmptyValue && emptyElement) {
        return emptyElement;
    }
    if (loading) {
        return _jsx(LoadingComponent, {});
    }
    return (_jsx(Markdown, { components: { img: ImageComponent, a: AnchorComponent }, remarkPlugins: referencesEnabled ? [remarkReferences()] : [], rehypePlugins: referencesEnabled ? [rehypeReferences(intl, metrics, separators)] : [], children: value }));
}
/**
 * @internal
 */
export function RichText(props) {
    return (_jsx(IntlWrapper, { children: _jsx(RichTextCore, { ...props }) }));
}
