pragma ComponentBehavior: Bound

import Quickshell
import Quickshell.Widgets
import QtQuick
import qs.Components
import qs.Config
import qs.Daemons
import qs.Helpers

Item {
	id: root

	readonly property int padding: Appearance.padding.smaller
	required property Item panels
	required property PersistentProperties visibilities

	anchors.bottom: parent.bottom
	anchors.right: parent.right
	anchors.top: parent.top
	implicitHeight: {
		const count = list.count;
		if (count === 0)
			return 0;

		let height = (count - 1) * Appearance.spacing.small;
		for (let i = 0; i < count; i++)
			height += (list.itemAtIndex(i) as NotifWrapper)?.nonAnimHeight ?? 0;

		if (panels.popouts.hasCurrent && (panels.popouts.currentCenter + (panels.popouts.current?.width / 2)) > panels.notifications.x || visibilities.dashboard)
			return 0;

		if (visibilities.osd) {
			const h = panels.osd.y - Appearance.spacing.small * 2 - padding * 2;
			if (height > h)
				height = h;
		}

		if (visibilities.session) {
			const h = panels.session.y - Appearance.spacing.small * 2 - padding * 2;
			if (height > h)
				height = h;
		}

		return Math.min(((QsWindow.window as QsWindow)?.screen?.height ?? 0) - 1 * 2, height + padding * 2);
	}
	implicitWidth: Config.notifs.sizes.width + padding * 2

	Behavior on implicitHeight {
		Anim {
		}
	}

	ClippingWrapperRectangle {
		anchors.fill: parent
		anchors.margins: root.padding
		color: "transparent"
		radius: Appearance.rounding.normal - root.padding

		CustomListView {
			id: list

			anchors.fill: parent
			cacheBuffer: (QsWindow.window as QsWindow)?.screen.height ?? 0
			orientation: Qt.Vertical
			spacing: 0

			delegate: NotifWrapper {
			}
			displaced: Transition {
				Anim {
					property: "y"
				}
			}
			model: ScriptModel {
				values: {
					const popups = NotifServer.popups.filter(n => !n.closed);

					if (!Config.notifs.showInFullscreen) {
						if (Hypr.monitorFor(root.panels.screen).activeWorkspace?.toplevels.values.some(t => t.lastIpcObject.fullscreen > 1) ?? false)
							return [];
					}
					return popups;
				}
			}
			move: Transition {
				Anim {
					property: "y"
				}
			}
		}
	}

	component Anim: NumberAnimation {
		duration: Appearance.anim.durations.expressiveDefaultSpatial
		easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
	}
	component NotifWrapper: Item {
		id: wrapper

		property int idx
		required property int index
		required property NotifServer.Notif modelData
		readonly property alias nonAnimHeight: notif.nonAnimHeight

		implicitHeight: notif.implicitHeight + (idx === 0 ? 0 : Appearance.spacing.small)
		implicitWidth: notif.implicitWidth

		ListView.onRemove: removeAnim.start()
		onIndexChanged: {
			if (index !== -1)
				idx = index;
		}

		SequentialAnimation {
			id: removeAnim

			PropertyAction {
				property: "ListView.delayRemove"
				target: wrapper
				value: true
			}

			PropertyAction {
				property: "enabled"
				target: wrapper
				value: false
			}

			PropertyAction {
				property: "implicitHeight"
				target: wrapper
				value: 0
			}

			PropertyAction {
				property: "z"
				target: wrapper
				value: 1
			}

			Anim {
				duration: MaterialEasing.expressiveEffectsTime
				easing.bezierCurve: MaterialEasing.expressiveEffects
				property: "x"
				target: notif
				to: (notif.x >= 0 ? Config.notifs.sizes.width : -Config.notifs.sizes.width) * 2
			}

			PropertyAction {
				property: "ListView.delayRemove"
				target: wrapper
				value: false
			}
		}

		ClippingRectangle {
			anchors.top: parent.top
			anchors.topMargin: wrapper.idx === 0 ? 0 : 8
			color: "transparent"
			implicitHeight: notif.implicitHeight
			implicitWidth: notif.implicitWidth
			radius: Appearance.rounding.small

			Notification {
				id: notif

				implicitWidth: root.implicitWidth - root.padding * 2
				modelData: wrapper.modelData
			}
		}
	}
}
