import {useEffect, useRef, useState, memo} from "@wordpress/element";
import {prepareChatbotMessage} from "../../../../../../../../../helpers";
import {LETTERS_TYPING_INTERVAL} from "./data";

const Stream = memo(function Stream({message, setIsTyping, messageListRef}) {
    const [content] = StreamingTextHook(message, setIsTyping, messageListRef);

    return <div className='lbaic-message-info' dangerouslySetInnerHTML={{__html: prepareChatbotMessage(content)}}></div>
});

export default Stream;

function StreamingTextHook(text, setIsTyping, chatBodyRef) {
    const [result, setResult] = useState('');
    const indexRef = useRef(0);
    const textRef = useRef(text);
    const typingTimeout = useRef(null);
    const chatBodyScrollHeightRef = useRef(chatBodyRef.current?.scrollHeight);

    useEffect(() => {
        // Add text
        textRef.current = text;

        const typeNextChar = () => {
            const currentText = textRef.current;
            const index = indexRef.current;

            if (index < currentText.length) {
                setResult(prevState => prevState + currentText[index]);
                indexRef.current++;

                typingTimeout.current = setTimeout(typeNextChar, LETTERS_TYPING_INTERVAL);
            } else {
                typingTimeout.current = null;
                // Typing ended
                if (typeof setIsTyping === 'function') {
                    setIsTyping(false);
                }
            }

            if (chatBodyRef.current) {
                // To avoid unnecessary scrolling
                if (chatBodyScrollHeightRef.current !== chatBodyRef.current.scrollHeight) {
                    // Scroll to the bottom
                    chatBodyRef.current.scrollTo({
                        top: chatBodyRef.current.scrollHeight,
                        behavior: 'smooth',
                    });
                    chatBodyScrollHeightRef.current = chatBodyRef.current.scrollHeight;
                }
            }
        };
        // Start or continue
        if (indexRef.current < textRef.current.length) {
            clearTimeout(typingTimeout.current)
            typingTimeout.current = setTimeout(typeNextChar, LETTERS_TYPING_INTERVAL);
            // Typing started
            if (typeof setIsTyping === 'function') {
                setIsTyping(true);
            }
        }

        return () => clearTimeout(typingTimeout.current);
    }, [text]);

    return [result];
}