#pragma once

#include <QtQuick/qquickitem.h>
#include <qcontainerfwd.h>
#include <qobject.h>
#include <qqmlintegration.h>
#include <qtmetamacros.h>
#include <qvariant.h>

namespace ZShell {

class ZUtils : public QObject {
	Q_OBJECT
	QML_ELEMENT
	QML_SINGLETON

	Q_PROPERTY(QString version READ version CONSTANT)
	Q_PROPERTY(QString qtVersion READ qtVersion CONSTANT)

	public:
	// clang-format off
	Q_INVOKABLE void saveItem(QQuickItem* target, const QUrl& path);
	Q_INVOKABLE void saveItem(QQuickItem* target, const QUrl& path, const QRect& rect);
	Q_INVOKABLE void saveItem(QQuickItem* target, const QUrl& path, QJSValue onSaved);
	Q_INVOKABLE void saveItem(QQuickItem* target, const QUrl& path, QJSValue onSaved, QJSValue onFailed);
	Q_INVOKABLE void saveItem(QQuickItem* target, const QUrl& path, const QRect& rect, QJSValue onSaved);
	Q_INVOKABLE void saveItem(QQuickItem* target, const QUrl& path, const QRect& rect, QJSValue onSaved, QJSValue onFailed);
	// clang-format on

	Q_INVOKABLE static bool copyFile(
		const QUrl& source, const QUrl& target, bool overwrite = true);
	Q_INVOKABLE static bool deleteFile(const QUrl& path);
	Q_INVOKABLE static QString toLocalFile(const QUrl& url);

	Q_INVOKABLE static qreal clamp(qreal value, qreal min, qreal max);

	Q_INVOKABLE static QString enumToString(
		QObject* target,
		const QString& property,
		const QVariant& value = QVariant());

	Q_INVOKABLE static QString gitRevision();
	Q_INVOKABLE static QString readTextFile(const QString& path);
	Q_INVOKABLE static bool writeTextFile(
		const QString& path, const QString& text);
	Q_INVOKABLE static QStringList listFiles(
		const QString& dir, const QString& suffix);

	Q_INVOKABLE static QQuickItem* findChild(
		QQuickItem* root, const QString& name);
	Q_INVOKABLE static QList<QQuickItem*> findChildren(
		QQuickItem* root, const QString& name);
	Q_INVOKABLE static QList<QQuickItem*> findChildrenMatching(
		QQuickItem* root, const QString& pattern);

	[[nodiscard]] QString version() const;
	[[nodiscard]] QString qtVersion() const;
};

} // namespace ZShell
