#pragma once

#include "configobject.hpp"

#include <QByteArray>
#include <QFileSystemWatcher>
#include <QFuture>
#include <QMutex>
#include <QTimer>
#include <qqmlregistration.h>
#include <QtConcurrent/QtConcurrent>

class QQmlEngine;
class QJSEngine;

namespace ZShell::config {

class Appearance;
class Background;
class Bar;
class Clipboard;
class Colors;
class Dashboard;
class Display;
class Dock;
class General;
class Launcher;
class Llm;
class Lock;
class Notifs;
class Osd;
class Screenshot;
class Services;
class Sidebar;
class Utilities;

class Config : public ConfigObject {
	Q_OBJECT
	QML_ELEMENT
	QML_SINGLETON

	Q_MOC_INCLUDE("appearance.hpp")
	Q_MOC_INCLUDE("background.hpp")
	Q_MOC_INCLUDE("bar.hpp")
	Q_MOC_INCLUDE("clipboard.hpp")
	Q_MOC_INCLUDE("colors.hpp")
	Q_MOC_INCLUDE("dashboard.hpp")
	Q_MOC_INCLUDE("display.hpp")
	Q_MOC_INCLUDE("dock.hpp")
	Q_MOC_INCLUDE("general.hpp")
	Q_MOC_INCLUDE("launcher.hpp")
	Q_MOC_INCLUDE("llm.hpp")
	Q_MOC_INCLUDE("lock.hpp")
	Q_MOC_INCLUDE("notifs.hpp")
	Q_MOC_INCLUDE("osd.hpp")
	Q_MOC_INCLUDE("screenshot.hpp")
	Q_MOC_INCLUDE("services.hpp")
	Q_MOC_INCLUDE("sidebar.hpp")
	Q_MOC_INCLUDE("utilities.hpp")

	CONFIG_SUBOBJECT(Appearance, appearance)
	CONFIG_SUBOBJECT(Background, background)
	CONFIG_SUBOBJECT(Bar, bar)
	CONFIG_SUBOBJECT(Clipboard, clipboard)
	CONFIG_SUBOBJECT(Colors, colors)
	CONFIG_SUBOBJECT(Dashboard, dashboard)
	CONFIG_SUBOBJECT(Display, display)
	CONFIG_SUBOBJECT(Dock, dock)
	CONFIG_SUBOBJECT(General, general)
	CONFIG_SUBOBJECT(Launcher, launcher)
	CONFIG_SUBOBJECT(Llm, llm)
	CONFIG_SUBOBJECT(Lock, lock)
	CONFIG_SUBOBJECT(Notifs, notifs)
	CONFIG_SUBOBJECT(Osd, osd)
	CONFIG_SUBOBJECT(Screenshot, screenshot)
	CONFIG_SUBOBJECT(Services, services)
	CONFIG_SUBOBJECT(Sidebar, sidebar)
	CONFIG_SUBOBJECT(Utilities, utilities)

	public:
	explicit Config(QObject* parent = nullptr);
	static Config* create(QQmlEngine*, QJSEngine*);
	[[nodiscard]] static Config* instance();

	Q_INVOKABLE void load();
	Q_INVOKABLE void saveNow();
	Q_INVOKABLE void reloadAsync();

	private Q_SLOTS:
	void scheduleSave();
	void flushAsync();
	void onWatcherEvent(const QString& path);

	private:
	QString filePath() const;
	bool writeAtomically(const QByteArray& data);
	void updateWatch();
	void loadSync();
	void loadAsync();
	void connectAutoSave(ConfigNode* node);

	QTimer m_saveTimer;
	QTimer m_reloadTimer;
	QFileSystemWatcher m_watcher;

	QMutex m_writeMutex;
	QByteArray m_lastWriteHash;

	bool m_reloadPending = false;
	bool m_loading = false;
	bool m_firstLoadDone = false;
	QFuture<void> m_loadFuture;

	static Config* s_instance;
};

} // namespace ZShell::config
