#pragma once

#include <qeasingcurve.h>
#include <qobject.h>
#include <qqmlintegration.h>

namespace ZShell::config {

class AnimCurves;
class AnimDurations;

class AnimEasing : public QObject {
	Q_OBJECT
	QML_ANONYMOUS

	Q_PROPERTY(QEasingCurve emphasized READ emphasized NOTIFY curvesChanged)
	Q_PROPERTY(
		QEasingCurve emphasizedAccel READ emphasizedAccel NOTIFY curvesChanged)
	Q_PROPERTY(
		QEasingCurve emphasizedDecel READ emphasizedDecel NOTIFY curvesChanged)
	Q_PROPERTY(QEasingCurve standard READ standard NOTIFY curvesChanged)
	Q_PROPERTY(
		QEasingCurve standardAccel READ standardAccel NOTIFY curvesChanged)
	Q_PROPERTY(
		QEasingCurve standardDecel READ standardDecel NOTIFY curvesChanged)
	Q_PROPERTY(
		QEasingCurve expressiveFastSpatial READ expressiveFastSpatial NOTIFY
			curvesChanged)
	Q_PROPERTY(
		QEasingCurve expressiveDefaultSpatial READ expressiveDefaultSpatial
			NOTIFY curvesChanged)
	Q_PROPERTY(
		QEasingCurve expressiveSlowSpatial READ expressiveSlowSpatial NOTIFY
			curvesChanged)
	Q_PROPERTY(
		QEasingCurve expressiveFastEffects READ expressiveFastEffects NOTIFY
			curvesChanged)
	Q_PROPERTY(
		QEasingCurve expressiveDefaultEffects READ expressiveDefaultEffects
			NOTIFY curvesChanged)
	Q_PROPERTY(
		QEasingCurve expressiveSlowEffects READ expressiveSlowEffects NOTIFY
			curvesChanged)

	public:
	explicit AnimEasing(QObject* parent = nullptr) : QObject(parent) {}

	void bindCurves(AnimCurves* curves);

	[[nodiscard]] QEasingCurve emphasized() const { return m_emphasized; }
	[[nodiscard]] QEasingCurve emphasizedAccel() const {
		return m_emphasizedAccel;
	}
	[[nodiscard]] QEasingCurve emphasizedDecel() const {
		return m_emphasizedDecel;
	}
	[[nodiscard]] QEasingCurve standard() const { return m_standard; }
	[[nodiscard]] QEasingCurve standardAccel() const { return m_standardAccel; }
	[[nodiscard]] QEasingCurve standardDecel() const { return m_standardDecel; }
	[[nodiscard]] QEasingCurve expressiveFastSpatial() const {
		return m_expressiveFastSpatial;
	}
	[[nodiscard]] QEasingCurve expressiveDefaultSpatial() const {
		return m_expressiveDefaultSpatial;
	}
	[[nodiscard]] QEasingCurve expressiveSlowSpatial() const {
		return m_expressiveSlowSpatial;
	}
	[[nodiscard]] QEasingCurve expressiveFastEffects() const {
		return m_expressiveFastEffects;
	}
	[[nodiscard]] QEasingCurve expressiveDefaultEffects() const {
		return m_expressiveDefaultEffects;
	}
	[[nodiscard]] QEasingCurve expressiveSlowEffects() const {
		return m_expressiveSlowEffects;
	}

	signals:
	void curvesChanged();

	private:
	static QEasingCurve buildCurve(const QList<qreal>& points);
	void rebuildCurves();

	AnimCurves* m_curves = nullptr;
	QEasingCurve m_emphasized, m_emphasizedAccel, m_emphasizedDecel;
	QEasingCurve m_standard, m_standardAccel, m_standardDecel;
	QEasingCurve m_expressiveFastSpatial, m_expressiveDefaultSpatial,
		m_expressiveSlowSpatial;
	QEasingCurve m_expressiveFastEffects, m_expressiveDefaultEffects,
		m_expressiveSlowEffects;
};

} // namespace ZShell::config
