import QtQuick
import ZShell.Config
import qs.Services

Item {
	id: root

	property alias anim: marqueeAnim
	property bool animate: false
	property color color: Colors.palette.m3onSurface
	property int fadeStrengthAnimMs: 180
	property real fadeStrengthIdle: 0.0
	property real fadeStrengthMoving: 1.0
	property alias font: elideText.font
	property int gap: 40
	property alias horizontalAlignment: elideText.horizontalAlignment
	property bool leftFadeEnabled: false
	property real leftFadeStrength: overflowing && leftFadeEnabled ? fadeStrengthMoving : fadeStrengthIdle
	property int leftFadeWidth: 28
	property bool marqueeEnabled: true
	readonly property bool overflowing: metrics.width > content.width
	property int pauseMs: 1200
	property real pixelsPerSecond: 40
	property real rightFadeStrength: overflowing ? fadeStrengthMoving : fadeStrengthIdle
	property int rightFadeWidth: 28
	property bool sliding: false
	property alias text: elideText.text
	property bool vertical: false

	function durationForDistance(px): int {
		return Math.max(1, Math.round(Math.abs(px) / root.pixelsPerSecond * 1000));
	}

	function resetMarquee() {
		marqueeAnim.stop();
		strip.x = 0;
		root.sliding = false;
		root.leftFadeEnabled = false;

		if (root.marqueeEnabled && root.overflowing && root.visible) {
			marqueeAnim.restart();
		}
	}

	clip: false
	implicitHeight: vertical ? elideText.implicitWidth : elideText.implicitHeight
	implicitWidth: vertical ? elideText.implicitHeight : elideText.implicitWidth

	Behavior on leftFadeStrength {
		Anim {
		}
	}
	Behavior on rightFadeStrength {
		Anim {
		}
	}

	onHeightChanged: resetMarquee()
	onTextChanged: resetMarquee()
	onVerticalChanged: resetMarquee()
	onVisibleChanged: if (!visible)
		resetMarquee()
	onWidthChanged: resetMarquee()

	Item {
		id: content

		anchors.centerIn: parent
		height: root.vertical ? root.width : root.height
		width: root.vertical ? root.height : root.width

		transform: Rotation {
			angle: root.vertical ? -90 : 0
			origin.x: content.width / 2
			origin.y: content.height / 2
		}

		TextMetrics {
			id: metrics

			font: elideText.font
			text: elideText.text
		}

		CustomText {
			id: elideText

			anchors.verticalCenter: parent.verticalCenter
			animate: root.animate
			animateProp: "scale,opacity"
			color: root.color
			elide: Text.ElideNone
			visible: !root.overflowing
			width: content.width
		}

		Item {
			id: marqueeViewport

			anchors.fill: parent
			clip: false
			layer.enabled: true
			visible: root.overflowing

			layer.effect: OpacityMask {
				maskSource: rightFadeMask
			}

			Item {
				id: strip

				anchors.verticalCenter: parent.verticalCenter
				height: t1.implicitHeight
				width: t1.width + root.gap + t2.width
				x: 0

				CustomText {
					id: t1

					animate: root.animate
					animateProp: "opacity"
					color: root.color
					font.pointSize: elideText.font.pointSize
					text: elideText.text
				}

				CustomText {
					id: t2

					animate: root.animate
					animateProp: "opacity"
					color: root.color
					font.pointSize: elideText.font.pointSize
					text: t1.text
					x: t1.width + root.gap
				}
			}

			SequentialAnimation {
				id: marqueeAnim

				running: false

				onFinished: pauseTimer.restart()

				ScriptAction {
					script: {
						root.sliding = true;
						root.leftFadeEnabled = true;
					}
				}

				Anim {
					duration: root.durationForDistance(t1.width)
					easing.bezierCurve: Easing.Linear
					easing.type: Easing.Linear
					from: 0
					property: "x"
					target: strip
					to: -t1.width
				}

				ScriptAction {
					script: {
						root.leftFadeEnabled = false;
					}
				}

				Anim {
					duration: root.durationForDistance(root.gap)
					easing.bezierCurve: Easing.Linear
					easing.type: Easing.Linear
					from: -t1.width
					property: "x"
					target: strip
					to: -(t1.width + root.gap)
				}

				ScriptAction {
					script: {
						root.sliding = false;
						strip.x = 0;
					}
				}
			}

			Timer {
				id: pauseTimer

				interval: root.pauseMs
				repeat: false
				running: true

				onTriggered: {
					if (root.marqueeEnabled)
						marqueeAnim.start();
				}
			}
		}

		Rectangle {
			id: rightFadeMask

			readonly property real fadeStartPos: {
				const w = Math.max(1, width);
				return Math.max(0, Math.min(1, (w - root.rightFadeWidth) / w));
			}
			readonly property real leftFadeEndPos: {
				const w = Math.max(1, width);
				return Math.max(0, Math.min(1, root.leftFadeWidth / w));
			}

			anchors.fill: marqueeViewport
			layer.enabled: true
			visible: false

			gradient: Gradient {
				orientation: Gradient.Horizontal

				GradientStop {
					color: Qt.rgba(1, 1, 1, 1.0 - root.leftFadeStrength)
					position: 0.0
				}

				GradientStop {
					color: Qt.rgba(1, 1, 1, 1.0)
					position: rightFadeMask.leftFadeEndPos
				}

				GradientStop {
					color: Qt.rgba(1, 1, 1, 1.0)
					position: rightFadeMask.fadeStartPos
				}

				GradientStop {
					color: Qt.rgba(1, 1, 1, 1.0 - root.rightFadeStrength)
					position: 1.0
				}
			}
		}
	}
}
