/*
README:
This file contains two utilities:

1) [Sections for customitizing the ch-chat renderItem]
The following sections are being customized at the time of writting:
- actions: customActionsRender,
- codeBlock: customCodeBlockRender,
- content: customContentRender

What for?

- actions: In order to be able to customize the copy button, by adding a part
"copying" when the user copies the message. This additional part allows changing
the current button icon of "copy" to a "checked" icon.
- codeBlock: Same reason as "actions" section.
- content: Mercury includes a "header" section for the assistant message. This
header includes an avatar, the assistant name, and optionally the message time.
This header requires custom markup, and for this reason this section has to be
customized.

2) [Configuration for the ch-chat sendContainerLayout property]
The chat styles are designed for a specific layout, so users must use the sendContainerLayout provided by Mercury. Customizing it is not supported.
*/
import { html, nothing } from "lit";
// Side effect to define the animation for "waiting" messages.
import { customActionsRender } from "./actions.lit.js";
import { customCodeBlockRender } from "./code-block.lit.js";
import { customFileRenders } from "./file.lit.js";
import { DEFAULT_ASSISTANT_STATUS, getMessageContent, tokenMap } from "./utils.js";
import "./mer-animated-dots.js";
// 1) [Sections for customitizing the ch-chat renderItem.]
/**
 * Mercury section that includes the assistant the assistant name, and an optional message time.
 *
 * @param messageMetaData - Metadata containing agentName and time
 * @returns TemplateResult rendering the assistant message header
 */
const messageHeader = (message) => {
    if (message.role === "system" || message.role === "user") {
        return nothing; // TODO: Improve type safety in the ch-chat (nicolas-camera_globant)
    }
    const agentName = message.metadata?.agentName;
    const assistantId = agentName?.toLowerCase().replace(/ /g, "-");
    const messageTime = message.metadata?.time;
    return html `<div part="header assistant${assistantId ? ` header-${assistantId}` : ""}"><div part="header__start assistant"><div part="header__avatar-container assistant"><div part="header__avatar-border assistant"></div><div part="header__avatar-image assistant"></div></div><div part="header__role assistant">${agentName}</div>${message.role === "assistant" && message.status === "waiting"
        ? html `<mer-animated-dots></mer-animated-dots>`
        : nothing}</div>${messageTime
        ? html `<time datetime="${messageTime}" part="header__time assistant">${messageTime}</time>`
        : nothing}</div>`;
};
// customzied in order to add the custom "messageHeader"
const customAssistantContentRender = (message, chatRef, codeBlockRender) => {
    const messageContent = getMessageContent(message);
    return message.status === "waiting"
        ? html `<div class="assistant-loading" part="${tokenMap({
            [`assistant content waiting ${message.id}`]: true,
            ...(message.parts ? { [message.parts]: true } : {})
        })}">${messageContent}</div>`
        : html `<ch-markdown-viewer part="${tokenMap({
            [`assistant content ${message.id} ${message.status ?? DEFAULT_ASSISTANT_STATUS}`]: true,
            ...(message.parts ? { [message.parts]: true } : {})
        })}" .renderCode="${
        // WA: Define codeBlockRender as "never" to avoid types incompatibility:
        // codeBlockRender returns TemplateResult and renderCode expects TemplateResult | undefined
        // In Chameleon this type mismatch does not happens. TODO: Evaluate a solution in Chameleon.
        codeBlockRender(chatRef)}" .showIndicator="${message.status === "streaming"}" .theme="${chatRef.markdownTheme ?? undefined}" .value="${messageContent}"></ch-markdown-viewer>`;
};
// Customized in order to add the custom "messageHeader"
const customErrorContentRender = (message, chatRef, codeBlockRender) => {
    const errorContent = getMessageContent(message);
    return html `<ch-markdown-viewer part="${tokenMap({
        [`error content ${message.id}`]: true,
        ...(message.parts ? { [message.parts]: true } : {})
    })}" .renderCode="${
    // WA: Define codeBlockRender as "never" to avoid types incompatibility:
    // codeBlockRender returns TemplateResult and renderCode expects TemplateResult | undefined
    // In Chameleon this type mismatch does not happens. TODO: Evaluate a solution in Chameleon.
    codeBlockRender(chatRef)}" .theme="${chatRef.markdownTheme ?? undefined}" .value="${errorContent}"></ch-markdown-viewer>`;
};
// No modification. It is required to be defined.
const defaultSystemContentRender = () => "string | TemplateResult";
// No modification. It is required to be defined.
const defaultUserContentRender = (messageModel) => getMessageContent(messageModel) ?? "";
const contentRenderByRole = {
    // TODO: Check if each contentRender can be optional, since it may be not me required to implement
    // a custom render for each type of content. ie.: Mercury does not requres to customize "system" and "user"
    assistant: customAssistantContentRender,
    error: customErrorContentRender,
    system: defaultSystemContentRender, // No modification
    user: defaultUserContentRender // No modification
};
const customContentRender = (message, chatRef, codeBlockRender) => contentRenderByRole[message.role](message, chatRef, codeBlockRender);
export const renderItem = {
    actions: customActionsRender,
    contentBefore: messageHeader,
    codeBlock: customCodeBlockRender,
    content: customContentRender,
    file: customFileRenders
};
// 2) [Configuration for the ch-chat sendContainerLayout property]
export const sendContainerLayout = {
    sendInputAfter: [
        "attach-files-button",
        "live-audio-button",
        "send-button",
        "chat-attached-files-viewer"
    ],
    sendContainerAfter: ["live-audio-container"]
};
