// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import { Stack, FocusZone, Spinner, useTheme } from '@fluentui/react';
import { TextField } from '@fluentui/react';
import React, { useEffect, useRef, useState, useCallback } from 'react';
import { useMemo } from 'react';
import { _Caption } from './Caption';
import { captionContainerClassName, captionsBannerClassName, captionsBannerFullHeightClassName, captionsContainerClassName, hiddenAnnouncementClassName, loadingBannerFullHeightStyles, loadingBannerStyles } from './styles/Captions.style';
import { rttDisclosureBannerClassName } from './styles/Captions.style';
import { useLocale } from '../localization';
import { RealTimeText } from './RealTimeText';
import { _RTTDisclosureBanner } from './RTTDisclosureBanner';
import { sortCaptionsAndRealTimeTexts } from './utils/sortCaptionsAndRealTimeTexts';
import { expandIconClassName, bannerTitleContainerClassName, realTimeTextInputBoxStyles } from './styles/Captions.style';
import { titleClassName } from './styles/CaptionsSettingsModal.styles';
import { Text, IconButton } from '@fluentui/react';
const SCROLL_OFFSET_ALLOWANCE = 20;
/**
 * @public
 * A component for displaying a CaptionsBanner with user icon, displayName and captions text.
 */
export const CaptionsBanner = (props) => {
    var _a, _b, _c;
    const { captions, realTimeTexts, isCaptionsOn, startCaptionsInProgress, onRenderAvatar, formFactor = 'default', captionsOptions, isRealTimeTextOn, onSendRealTimeText, latestLocalRealTimeText } = props;
    const localeStrings = useLocale().strings.captionsBanner;
    const strings = Object.assign(Object.assign({}, localeStrings), props.strings);
    const captionsScrollDivRef = useRef(null);
    const [isAtBottomOfScroll, setIsAtBottomOfScroll] = useState(true);
    const theme = useTheme();
    const [expandBannerHeight, setExpandBannerHeight] = useState(false);
    const [announcedRTT, setAnnouncedRTT] = useState([]);
    const [announcedCaption, setAnnouncedCaption] = useState([]);
    const [captionAnnouncementText, setCaptionAnnouncementText] = useState([]);
    const [rttAnnouncementText, setRTTAnnouncementText] = useState([]);
    const getTitle = () => {
        var _a, _b, _c;
        if (isCaptionsOn && isRealTimeTextOn) {
            return (_a = strings.captionsAndRealTimeTextContainerTitle) !== null && _a !== void 0 ? _a : '';
        }
        else if (isCaptionsOn) {
            return (_b = strings.captionsOnlyContainerTitle) !== null && _b !== void 0 ? _b : '';
        }
        else if (isRealTimeTextOn) {
            return (_c = strings.realTimeTextOnlyContainerTitle) !== null && _c !== void 0 ? _c : '';
        }
        return '';
    };
    // merge realtimetexts and captions into one array based on timestamp
    // Combine captions and realTimeTexts into one list
    const combinedList = useMemo(() => {
        var _a;
        return sortCaptionsAndRealTimeTexts(captions, (_a = realTimeTexts === null || realTimeTexts === void 0 ? void 0 : realTimeTexts.completedMessages) !== null && _a !== void 0 ? _a : []);
    }, [captions, realTimeTexts === null || realTimeTexts === void 0 ? void 0 : realTimeTexts.completedMessages]);
    const mergedCaptions = useMemo(() => {
        var _a;
        return [...combinedList, ...((_a = realTimeTexts === null || realTimeTexts === void 0 ? void 0 : realTimeTexts.currentInProgress) !== null && _a !== void 0 ? _a : []), realTimeTexts === null || realTimeTexts === void 0 ? void 0 : realTimeTexts.myInProgress].slice(-50);
    }, [combinedList, realTimeTexts]);
    const scrollToBottom = () => {
        if (captionsScrollDivRef.current) {
            captionsScrollDivRef.current.scrollTop = captionsScrollDivRef.current.scrollHeight;
        }
    };
    const handleScrollToTheBottom = useCallback(() => {
        if (!captionsScrollDivRef.current) {
            return;
        }
        const atBottom = Math.ceil(captionsScrollDivRef.current.scrollTop) >= captionsScrollDivRef.current.scrollHeight - captionsScrollDivRef.current.clientHeight - SCROLL_OFFSET_ALLOWANCE;
        setIsAtBottomOfScroll(atBottom);
    }, []);
    useEffect(() => {
        const captionsScrollDiv = captionsScrollDivRef.current;
        captionsScrollDiv === null || captionsScrollDiv === void 0 ? void 0 : captionsScrollDiv.addEventListener('scroll', handleScrollToTheBottom);
        return () => {
            captionsScrollDiv === null || captionsScrollDiv === void 0 ? void 0 : captionsScrollDiv.removeEventListener('scroll', handleScrollToTheBottom);
        };
    }, [handleScrollToTheBottom, isCaptionsOn, isRealTimeTextOn]);
    useEffect(() => {
        // only auto scroll to bottom is already is at bottom of scroll before new caption comes in
        if (isAtBottomOfScroll) {
            scrollToBottom();
        }
    }, [captions, realTimeTexts, isAtBottomOfScroll]);
    const [textFieldValue, setTextFieldValue] = useState('');
    useEffect(() => {
        // if the latest real time text sent by myself is final, clear the text field
        if (latestLocalRealTimeText && !latestLocalRealTimeText.isTyping) {
            setTextFieldValue('');
        }
    }, [latestLocalRealTimeText]);
    useEffect(() => {
        if (realTimeTexts === null || realTimeTexts === void 0 ? void 0 : realTimeTexts.completedMessages) {
            //filter out the messages that have already been announced
            const rTTMessagesToAnnounce = realTimeTexts.completedMessages.filter(message => !announcedRTT.includes(message.id));
            if (rTTMessagesToAnnounce.length > 0) {
                setRTTAnnouncementText(rTTMessagesToAnnounce);
                setAnnouncedRTT(prev => [...prev, ...rTTMessagesToAnnounce.map(message => message.id)]);
            }
        }
        if (captions.length > 0) {
            // filter out the captions that have already been announced
            const captionsToAnnounce = captions.filter(caption => !announcedCaption.includes(caption.id) && caption.isFinalized);
            if (captionsToAnnounce.length > 0) {
                setCaptionAnnouncementText(captionsToAnnounce);
                setAnnouncedCaption(prev => [...prev, ...captionsToAnnounce.map(caption => caption.id)]);
            }
        }
    }, [captions, realTimeTexts === null || realTimeTexts === void 0 ? void 0 : realTimeTexts.completedMessages, announcedRTT, announcedCaption]);
    const handleKeyDown = (event) => {
        if (event.key === 'Enter') {
            event.preventDefault();
            if (textFieldValue && onSendRealTimeText) {
                onSendRealTimeText(textFieldValue, true);
                setTextFieldValue('');
            }
        }
    };
    const realTimeTextDisclosureBannerStrings = {
        bannerTitle: (_a = strings.realTimeTextBannerTitle) !== null && _a !== void 0 ? _a : '',
        bannerContent: (_b = strings.realTimeTextBannerContent) !== null && _b !== void 0 ? _b : '',
        bannerLinkLabel: (_c = strings.realTimeTextBannerLinkLabel) !== null && _c !== void 0 ? _c : ''
    };
    const captionsAndRealTimeText = () => {
        return React.createElement(React.Fragment, null, mergedCaptions.filter(caption => caption).map(caption => {
            if ('message' in caption) {
                return React.createElement("div", { key: `RealTimeText - ${caption.id}`, className: captionContainerClassName, "data-is-focusable": true },
                    React.createElement(RealTimeText, Object.assign({}, caption)));
            }
            return React.createElement("div", { key: `Captions - ${caption.id}`, className: captionContainerClassName, "data-is-focusable": true },
                React.createElement(_Caption, Object.assign({}, caption, { onRenderAvatar: onRenderAvatar })));
        }));
    };
    return React.createElement(React.Fragment, null, (startCaptionsInProgress || isCaptionsOn || isRealTimeTextOn) && React.createElement(FocusZone, { shouldFocusOnMount: true, className: captionsContainerClassName, "data-ui-id": "captions-banner" },
        (rttAnnouncementText.length > 0 || (captionAnnouncementText === null || captionAnnouncementText === void 0 ? void 0 : captionAnnouncementText.length) > 0) && React.createElement("div", { "aria-live": "assertive", role: "alert", "aria-atomic": "true", className: hiddenAnnouncementClassName },
            React.createElement("span", null, rttAnnouncementText.map(text => React.createElement("span", null,
                strings.realTimeTextBannerTitle,
                " ",
                text.displayName,
                ": ",
                text.message))),
            React.createElement("span", null, captionAnnouncementText.map(text => React.createElement("span", null,
                strings.captionsOnlyContainerTitle,
                " ",
                text.displayName,
                ": ",
                text.captionText)))),
        (isCaptionsOn || isRealTimeTextOn) && formFactor === 'compact' && React.createElement(Stack, { horizontal: true, horizontalAlign: "space-between", verticalAlign: "center", className: bannerTitleContainerClassName },
            React.createElement(Text, { className: titleClassName }, getTitle()),
            React.createElement(IconButton, { "data-ui-id": "captions-banner-expand-icon", iconProps: {
                    iconName: expandBannerHeight ? 'MinimizeIcon' : 'ExpandIcon'
                }, ariaLabel: expandBannerHeight ? strings.minimizeButtonAriaLabel : strings.expandButtonAriaLabel, onClick: () => setExpandBannerHeight(!expandBannerHeight), styles: expandIconClassName(theme) })),
        (isCaptionsOn || isRealTimeTextOn) && React.createElement("div", { ref: captionsScrollDivRef, className: (captionsOptions === null || captionsOptions === void 0 ? void 0 : captionsOptions.height) === 'full' ? captionsBannerFullHeightClassName(theme) : captionsBannerClassName(formFactor, expandBannerHeight), "data-ui-id": "captions-banner-inner", "data-is-focusable": true },
            isRealTimeTextOn && React.createElement(Stack, { className: rttDisclosureBannerClassName() },
                React.createElement(_RTTDisclosureBanner, { strings: realTimeTextDisclosureBannerStrings })),
            captionsAndRealTimeText()),
        isRealTimeTextOn && onSendRealTimeText && React.createElement(TextField, { styles: realTimeTextInputBoxStyles(theme), placeholder: strings.realTimeTextInputBoxDefaultText, value: textFieldValue, onKeyDown: handleKeyDown, onChange: (_, newValue) => {
                setTextFieldValue(newValue || '');
                onSendRealTimeText(newValue || '', false);
            }, maxLength: 2000, errorMessage: textFieldValue.length >= 2000 ? strings.realTimeTextInputErrorMessage : undefined }),
        !isCaptionsOn && !isRealTimeTextOn && React.createElement(Stack, { verticalAlign: "center", styles: (captionsOptions === null || captionsOptions === void 0 ? void 0 : captionsOptions.height) === 'full' ? loadingBannerFullHeightStyles(theme) : loadingBannerStyles(formFactor), "data-is-focusable": true },
            React.createElement(Spinner, { label: strings === null || strings === void 0 ? void 0 : strings.captionsBannerSpinnerText, ariaLive: "assertive", labelPosition: "right" }))));
};
//# sourceMappingURL=CaptionsBanner.js.map