// Copyright Mirage authors & contributors <https://github.com/mirukana/mirage>
// SPDX-License-Identifier: LGPL-3.0-or-later

import QtQuick 2.12
import QtQuick.Layouts 1.12
import "../../../Base"
import "../../.."

HRowLayout {
    id: historyContent

    readonly property var mentions: []

    readonly property string mentionsCSS: {
        const lines = []

        for (const [name, link] of mentions) {
            if (! link.match(/^https?:\/\/matrix.to\/#\/@.+/)) continue

            lines.push(
                `.mention[data-mention='${utils.escapeHtml(name)}'] ` +
                `{ color: ${utils.nameColor(name)} }`
            )
        }

        return "<style type='text/css'>" + lines.join("\n") + "</style>"
    }
    readonly property string diffCSS: {
        const lines = [
            "del { background-color: #f8d7da; color: #721c24; text-decoration: line-through; }",
            "ins { background-color: #d4edda; color: #155724; text-decoration: underline; }",
        ]
        return "<style type='text/css'>" + lines.join("\n") + "</style>"
    }


    readonly property string senderText: ""
    property string contentText: model.content_diff
    readonly property string timeText: utils.formatTime(model.date, false)

    readonly property bool pureMedia: false

    readonly property bool hoveredSelectable: contentHover.hovered
    readonly property string hoveredLink:
        linksRepeater.lastHovered && linksRepeater.lastHovered.hovered ?
        linksRepeater.lastHovered.mediaUrl :
        contentLabel.hoveredLink

    readonly property alias contentLabel: contentLabel

    readonly property int xOffset: 0

    readonly property int maxMessageWidth:
        contentText.includes("<pre>") || contentText.includes("<table>") ?
        -1 :
        window.settings.Chat.max_messages_line_length < 0 ?
        -1 :
        Math.ceil(
            mainUI.fontMetrics.averageCharacterWidth *
            window.settings.Chat.max_messages_line_length
        )

    readonly property alias selectedText: contentLabel.selectedPlainText

    spacing: theme.chat.message.horizontalSpacing
    layoutDirection: Qt.LeftToRight

    HColumnLayout {
        id: contentColumn

        Layout.fillWidth: true
        Layout.alignment: Qt.AlignVCenter

        HSelectableLabel {
            id: contentLabel
            visible: ! pureMedia
            enableLinkActivation: ! historyList.selectedCount

            selectByMouse:
                historyList.selectedCount <= 1 &&
                historyDelegate.checked &&
                textSelectionBlocker.point.scenePosition === Qt.point(0, 0)

            topPadding: theme.chat.message.verticalSpacing
            bottomPadding: topPadding
            leftPadding: historyContent.spacing
            rightPadding: leftPadding

            color: theme.chat.message.body

            font.italic: false
            wrapMode: TextEdit.Wrap
            textFormat: Text.RichText
            text:
                // CSS
                theme.chat.message.styleInclude + mentionsCSS + diffCSS +

                // Sender name & message body
                (
                    compact && contentText.match(/^\s*<(p|h[1-6])>/) ?
                    contentText.replace(
                        /(^\s*<(p|h[1-6])>)/, "$1" + senderText,
                    ) :
                    senderText + contentText
                ) +

                // Time
                // For some reason, if there's only one space,
                // times will be on their own lines most of the time.
                "  " +
                `<font size=${theme.fontSize.small}px ` +
                      `color=${theme.chat.message.date}>` +
                timeText +
                "</font>"

            transform: Translate { x: xOffset }

            Layout.maximumWidth: historyContent.maxMessageWidth
            Layout.fillWidth: true

            onSelectedTextChanged: if (selectedPlainText) {
                historyList.delegateWithSelectedText = model.id
                historyList.selectedText             = selectedPlainText
            } else if (historyList.delegateWithSelectedText === model.id) {
                historyList.delegateWithSelectedText = ""
                historyList.selectedText             = ""
            }

            Connections {
                target: historyList
                onCheckedChanged: contentLabel.deselect()
                onDelegateWithSelectedTextChanged: {
                    if (historyList.delegateWithSelectedText !== model.id)
                        contentLabel.deselect()
                }
            }

            HoverHandler { id: contentHover }

            PointHandler {
                id: mousePointHandler

                property bool checkedNow: false

                acceptedButtons: Qt.LeftButton
                acceptedModifiers: Qt.NoModifier
                acceptedPointerTypes:
                    PointerDevice.GenericPointer | PointerDevice.Eraser

                onActiveChanged: {
                    if (active &&
                            ! historyDelegate.checked &&
                            (! parent.hoveredLink ||
                            ! parent.enableLinkActivation)) {

                        historyList.check(model.index)
                        checkedNow = true
                    }

                    if (! active && historyDelegate.checked) {
                        checkedNow ?
                        checkedNow = false :
                        historyList.uncheck(model.index)
                    }
                }
            }

            PointHandler {
                id: mouseShiftPointHandler
                acceptedButtons: Qt.LeftButton
                acceptedModifiers: Qt.ShiftModifier
                acceptedPointerTypes:
                    PointerDevice.GenericPointer | PointerDevice.Eraser

                onActiveChanged: {
                    if (active &&
                            ! historyDelegate.checked &&
                            (! parent.hoveredLink ||
                            ! parent.enableLinkActivation)) {

                        historyList.checkFromLastToHere(model.index)
                    }
                }
            }

            TapHandler {
                id: touchTapHandler
                acceptedButtons: Qt.LeftButton
                acceptedPointerTypes: PointerDevice.Finger | PointerDevice.Pen
                onTapped:
                    if (! parent.hoveredLink || ! parent.enableLinkActivation)
                        historyDelegate.toggleChecked()
            }

            TapHandler {
                id: textSelectionBlocker
                acceptedPointerTypes: PointerDevice.Finger | PointerDevice.Pen
            }

            Rectangle {
                id: contentBackground
                width: Math.max(
                    parent.paintedWidth +
                    parent.leftPadding + parent.rightPadding,

                    linksRepeater.summedWidth +
                    (pureMedia ? 0 : parent.leftPadding + parent.rightPadding),
                )
                height: contentColumn.height
                radius: theme.chat.message.radius
                z: -100
                color: historyDelegate.checked &&
                       ! contentLabel.selectedPlainText &&
                       ! mousePointHandler.active &&
                       ! mouseShiftPointHandler.active ?
                       theme.chat.message.checkedBackground :

                       theme.chat.message.background
            }
        }

        HRepeater {
            id: linksRepeater

            property EventMediaLoader lastHovered: null

            model: {
                const links = historyDelegate.currentModel.links

                if (historyDelegate.currentModel.media_url)
                    links.push(historyDelegate.currentModel.media_url)

                return links
            }

            EventMediaLoader {
                singleMediaInfo: historyDelegate.currentModel
                mediaUrl: modelData
                showSender: pureMedia ? senderText : ""
                showDate: pureMedia ? timeText : ""
                showLocalEcho: pureMedia && (
                    singleMediaInfo.is_local_echo ||
                    singleMediaInfo.read_by_count
                ) ? stateText : ""

                transform: Translate { x: xOffset }

                onHoveredChanged: if (hovered) linksRepeater.lastHovered = this

                Layout.bottomMargin: pureMedia ? 0 : contentLabel.bottomPadding
                Layout.leftMargin: pureMedia ? 0 : historyContent.spacing
                Layout.rightMargin: pureMedia ? 0 : historyContent.spacing
                Layout.preferredWidth: item ? item.width : -1
                Layout.preferredHeight: item ? item.height : -1
            }
        }
    }

    HSpacer {}
}
