// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
import React from 'react';
import { _formatString } from "../../../../acs-ui-common/src";
import parse, { Element as DOMElement } from 'html-react-parser';
import { attributesToProps } from 'html-react-parser';
import Linkify from 'react-linkify';
import { Link } from '@fluentui/react';
import LiveMessage from '../Announcer/LiveMessage';
import DOMPurify from 'dompurify';
import { messageTextContentStyles } from '../styles/MessageThread.styles';
/** @private */
export const ChatMessageContent = (props) => {
    switch (props.message.contentType) {
        case 'text':
            return MessageContentAsText(props);
        case 'html':
            return MessageContentAsRichTextHTML(props);
        case 'richtext/html':
            return MessageContentAsRichTextHTML(props);
        default:
            console.warn('unknown message content type');
            return React.createElement(React.Fragment, null);
    }
};
const MessageContentWithLiveAria = (props) => {
    return React.createElement("div", { "data-ui-status": props.message.status, role: "text", "aria-label": props.ariaLabel, className: props.className },
        React.createElement(LiveMessage, { message: props.liveMessage, ariaLive: "polite" }),
        props.content);
};
const MessageContentAsRichTextHTML = (props) => {
    return React.createElement(MessageContentWithLiveAria, { message: props.message, liveMessage: generateLiveMessage(props), ariaLabel: messageContentAriaText(props), content: processHtmlToReact(props) });
};
const MessageContentAsText = (props) => {
    return React.createElement(MessageContentWithLiveAria, { message: props.message, liveMessage: generateLiveMessage(props), ariaLabel: messageContentAriaText(props), className: messageTextContentStyles, content: React.createElement(Linkify, { componentDecorator: (decoratedHref, decoratedText, key) => {
                return React.createElement(Link, { target: "_blank", href: decoratedHref, key: key }, decoratedText);
            } }, props.message.content) });
};
const extractContentForAllyMessage = (props) => {
    var _a;
    if (props.message.content || props.message.attachments) {
        // Replace all <img> tags with 'image' for aria.
        const parsedContent = DOMPurify.sanitize((_a = props.message.content) !== null && _a !== void 0 ? _a : '', {
            ALLOWED_TAGS: ['img'],
            RETURN_DOM_FRAGMENT: true
        });
        parsedContent.childNodes.forEach(child => {
            if (child.nodeName.toLowerCase() !== 'img') {
                return;
            }
            const imageTextNode = document.createElement('div');
            imageTextNode.innerHTML = 'image ';
            parsedContent.replaceChild(imageTextNode, child);
        });
        // Inject message attachment count for aria.
        // this is only applying to file attachments not for inline images.
        if (props.message.attachments && props.message.attachments.length > 0) {
            const attachmentCardDescription = attachmentCardGroupDescription(props);
            const attachmentTextNode = document.createElement('div');
            attachmentTextNode.innerHTML = `${attachmentCardDescription}`;
            parsedContent.appendChild(attachmentTextNode);
        }
        // Strip all html tags from the content for aria.
        let message = DOMPurify.sanitize(parsedContent, {
            ALLOWED_TAGS: []
        });
        // decode HTML entities so that screen reader can read the content properly.
        message = decodeEntities(message);
        return message;
    }
    return '';
};
const generateLiveMessage = (props) => {
    const messageContent = extractContentForAllyMessage(props);
    if (props.message.editedOn) {
        const liveAuthor = _formatString(props.strings.editedMessageLiveAuthorIntro, {
            author: `${props.message.senderDisplayName}`
        });
        return `${props.message.mine ? props.strings.editedMessageLocalUserLiveAuthorIntro : liveAuthor} ${messageContent}`;
    }
    else {
        const liveAuthor = _formatString(props.strings.liveAuthorIntro, {
            author: `${props.message.senderDisplayName}`
        });
        return `${props.message.mine ? '' : liveAuthor} ${messageContent} `;
    }
};
const messageContentAriaText = (props) => {
    var _a, _b;
    const message = extractContentForAllyMessage(props);
    return props.message.mine ? _formatString(props.strings.messageContentMineAriaText, {
        status: (_a = props.message.status) !== null && _a !== void 0 ? _a : '',
        message: message
    }) : _formatString(props.strings.messageContentAriaText, {
        status: (_b = props.message.status) !== null && _b !== void 0 ? _b : '',
        author: `${props.message.senderDisplayName}`,
        message: message
    });
};
const attachmentCardGroupDescription = (props) => {
    const attachments = props.message.attachments;
    return getAttachmentCountLiveMessage(attachments !== null && attachments !== void 0 ? attachments : [], props.strings.attachmentCardGroupMessage);
};
/**
 * @private
 */
export const getAttachmentCountLiveMessage = (attachments, attachmentCardGroupMessage) => {
    if (attachments.length === 0) {
        return '';
    }
    return _formatString(attachmentCardGroupMessage, {
        attachmentCount: `${attachments.length}`
    });
};
const defaultOnRenderInlineImage = (inlineImage) => {
    return React.createElement("img", Object.assign({ key: inlineImage.imageAttributes.id, tabIndex: 0, "data-ui-id": inlineImage.imageAttributes.id }, inlineImage.imageAttributes));
};
const processHtmlToReact = (props) => {
    var _a;
    const options = {
        transform(reactNode, domNode) {
            var _a;
            if (domNode instanceof DOMElement && domNode.attribs) {
                // Transform custom rendering of mentions
                // Transform inline images
                if (domNode.name && domNode.name === 'img' && domNode.attribs && domNode.attribs.id) {
                    if (domNode.attribs.name) {
                        domNode.attribs['aria-label'] = domNode.attribs.name;
                    }
                    const imgProps = attributesToProps(domNode.attribs);
                    const inlineImageProps = {
                        messageId: props.message.messageId,
                        imageAttributes: imgProps
                    };
                    return ((_a = props.inlineImageOptions) === null || _a === void 0 ? void 0 : _a.onRenderInlineImage) ? props.inlineImageOptions.onRenderInlineImage(inlineImageProps, defaultOnRenderInlineImage) : defaultOnRenderInlineImage(inlineImageProps);
                }
                // Transform links to open in new tab
                if (domNode.name === 'a' && React.isValidElement(reactNode)) {
                    return React.cloneElement(reactNode, {
                        target: '_blank',
                        rel: 'noreferrer noopener'
                    });
                }
            }
            // Pass through the original node
            return reactNode;
        }
    };
    return React.createElement(React.Fragment, null, parse((_a = props.message.content) !== null && _a !== void 0 ? _a : '', options));
};
const decodeEntities = (encodedString) => {
    // This regular expression matches HTML entities.
    const translate_re = /&(nbsp|amp|quot|lt|gt);/g;
    // This object maps HTML entities to their respective characters.
    const translate = {
        nbsp: ' ',
        amp: '&',
        quot: '"',
        lt: '<',
        gt: '>'
    };
    return encodedString
        // Find all matches of HTML entities defined in translate_re and
        // replace them with the corresponding character from the translate object.
        .replace(translate_re, function (match, entity) {
        var _a;
        return (_a = translate[entity]) !== null && _a !== void 0 ? _a : match;
    })
        // Find numeric entities (e.g., &#65;)
        // and replace them with the equivalent character using the String.fromCharCode method,
        // which converts Unicode values into characters.
        .replace(/&#(\d+);/gi, function (match, numStr) {
        const num = parseInt(numStr, 10);
        return String.fromCharCode(num);
    });
};
//# sourceMappingURL=ChatMessageContent.js.map