pragma ComponentBehavior: Bound

import qs.Components
import qs.Config
import qs.Daemons
import qs.Modules
import Quickshell
import QtQuick
import QtQuick.Layouts

CustomRect {
	id: root

	readonly property CustomText body: expandedContent.item?.body ?? null
	required property bool expanded
	required property NotifServer.Notif modelData
	readonly property real nonAnimHeight: expanded ? summary.implicitHeight + expandedContent.implicitHeight + expandedContent.anchors.topMargin + 10 * 2 : summaryHeightMetrics.height
	required property Props props
	required property var visibilities

	color: {
		const c = root.modelData?.urgency === "critical" ? DynamicColors.palette.m3secondaryContainer : DynamicColors.layer(DynamicColors.palette.m3surfaceContainerHigh, 2);
		return expanded ? c : Qt.alpha(c, 0);
	}
	implicitHeight: nonAnimHeight
	radius: 6
	state: expanded ? "expanded" : ""

	Behavior on implicitHeight {
		Anim {
			duration: MaterialEasing.expressiveEffectsTime
			easing.bezierCurve: MaterialEasing.expressiveEffects
		}
	}
	states: State {
		name: "expanded"

		PropertyChanges {
			compactBody.anchors.margins: 10
			dummySummary.anchors.margins: 10
			expandedContent.anchors.margins: 10
			summary.anchors.margins: 10
			summary.maximumLineCount: Number.MAX_SAFE_INTEGER
			summary.width: root.width - 10 * 2 - timeStr.implicitWidth - 7
			timeStr.anchors.margins: 10
		}
	}
	transitions: Transition {
		Anim {
			properties: "margins,width,maximumLineCount"
		}
	}

	TextMetrics {
		id: summaryHeightMetrics

		font: summary.font
		text: " " // Use this height to prevent weird characters from changing the line height
	}

	CustomText {
		id: summary

		anchors.left: parent.left
		anchors.top: parent.top
		color: root.modelData?.urgency === "critical" ? DynamicColors.palette.m3onSecondaryContainer : DynamicColors.palette.m3onSurface
		elide: Text.ElideRight
		maximumLineCount: 1
		text: root.modelData?.summary ?? ""
		width: parent.width
		wrapMode: Text.WordWrap
	}

	CustomText {
		id: dummySummary

		anchors.left: parent.left
		anchors.top: parent.top
		text: root.modelData?.summary ?? ""
		visible: false
	}

	WrappedLoader {
		id: compactBody

		anchors.left: dummySummary.right
		anchors.leftMargin: 7
		anchors.right: parent.right
		anchors.top: parent.top
		shouldBeActive: !root.expanded

		sourceComponent: CustomText {
			color: root.modelData?.urgency === "critical" ? DynamicColors.palette.m3secondary : DynamicColors.palette.m3outline
			elide: Text.ElideRight
			text: String(root.modelData?.body ?? "").replace(/\n/g, " ")
			textFormat: Text.StyledText
		}
	}

	WrappedLoader {
		id: timeStr

		anchors.right: parent.right
		anchors.top: parent.top
		shouldBeActive: root.expanded

		sourceComponent: CustomText {
			animate: true
			color: DynamicColors.palette.m3outline
			font.pointSize: 11
			text: root.modelData?.timeStr ?? ""
		}
	}

	WrappedLoader {
		id: expandedContent

		anchors.left: parent.left
		anchors.right: parent.right
		anchors.top: summary.bottom
		anchors.topMargin: 7 / 2
		shouldBeActive: root.expanded

		sourceComponent: ColumnLayout {
			readonly property alias body: body

			spacing: 10

			CustomText {
				id: body

				Layout.fillWidth: true
				color: root.modelData?.urgency === "critical" ? DynamicColors.palette.m3secondary : DynamicColors.palette.m3onSurface
				text: String(root.modelData?.body ?? "").replace(/(.)\n(?!\n)/g, "$1\n\n") || qsTr("No body given")
				textFormat: Text.MarkdownText
				wrapMode: Text.WordWrap

				onLinkActivated: link => {
					Quickshell.execDetached(["app2unit", "-O", "--", link]);
					root.visibilities.sidebar = false;
				}
			}

			NotifActionList {
				notif: root.modelData
			}
		}
	}

	component WrappedLoader: Loader {
		id: comp

		required property bool shouldBeActive

		active: false
		opacity: 0

		states: State {
			name: "active"
			when: comp.shouldBeActive

			PropertyChanges {
				comp.active: true
				comp.opacity: 1
			}
		}
		transitions: [
			Transition {
				from: ""
				to: "active"

				SequentialAnimation {
					PropertyAction {
						property: "active"
					}

					Anim {
						property: "opacity"
					}
				}
			},
			Transition {
				from: "active"
				to: ""

				SequentialAnimation {
					Anim {
						property: "opacity"
					}

					PropertyAction {
						property: "active"
					}
				}
			}
		]
	}
}
