#pragma once

#include <QObject>
#include <QStringList>
#include <QFutureWatcher>
#include <QUrl>

#include <MauiKit4/Core/mauilist.h>

#define PIX_QUERY_MAX_LIMIT 20000

namespace FMH
{
class FileLoader;
}

class QFileSystemWatcher;
class QTimer;

typedef QHash<QString, QString> GpsHash;
class GpsImages : public QObject
{
    Q_OBJECT
public:
    static GpsImages *getInstance();
    GpsImages();
    GpsHash data() const;
    QList<QString> cities() const;
    void insert(const QString &url, const QString &gpsId);
    QStringList urls(const QString &gpsId);
    QString gpsTag(const QString &url);
    bool contains(const QString &url);
    void clear();
    bool remove(const QString &url);
    QStringList values();
private:
    GpsHash m_data;
};

class Gallery : public MauiList
{
    Q_OBJECT
    Q_PROPERTY(QList<QUrl> urls READ urls WRITE setUrls NOTIFY urlsChanged)
    Q_PROPERTY(QList<QUrl> folders READ folders NOTIFY foldersChanged FINAL)
    Q_PROPERTY(QStringList cities READ cities NOTIFY citiesChanged FINAL)
    Q_PROPERTY(QStringList files READ files NOTIFY filesChanged FINAL)

    Q_PROPERTY(bool recursive READ recursive WRITE setRecursive NOTIFY recursiveChanged)
    Q_PROPERTY(bool autoReload READ autoReload WRITE setAutoReload NOTIFY autoReloadChanged)
    Q_PROPERTY(int limit READ limit WRITE setlimit NOTIFY limitChanged)

    Q_PROPERTY(Status status READ status NOTIFY statusChanged FINAL)
    Q_PROPERTY(QString error READ error NOTIFY errorChanged FINAL)

    Q_PROPERTY(bool activeGeolocationTags READ activeGeolocationTags WRITE setActiveGeolocationTags NOTIFY activeGeolocationTagsChanged)

public:
    enum Status
    {
        Ready,
        Loading,
        Error
    };
    Q_ENUM(Status)

    explicit Gallery(QObject * = nullptr);
    ~Gallery();

    void componentComplete() override;

    const FMH::MODEL_LIST &items() const override final;

    void setUrls(const QList<QUrl> &);
    QList<QUrl> urls() const;

    void setAutoReload(const bool &);
    bool autoReload() const;

    QList<QUrl> folders() const;

    bool recursive() const;

    int limit() const;

    QStringList files() const;

    const QStringList &cities() const;

    Status status() const;

    QString error() const;

    bool activeGeolocationTags() const;

private:
    FMH::FileLoader *m_fileLoader;
    QFileSystemWatcher *m_watcher;
    QFutureWatcher<void> *m_futureWatcher;

    QTimer *m_scanTimer;
    FMH::MODEL_LIST list = {};

    QList<QUrl> m_urls;
    QStringList m_cities;
    QList<QUrl> m_folders;

    bool m_autoReload;
    bool m_recursive;
    bool m_activeGeolocationTags = false;

    int m_limit = PIX_QUERY_MAX_LIMIT;

    Status m_status = Status::Error;
    QString m_error;

    void scan(const QList<QUrl> &, const bool & = true, const int & = PIX_QUERY_MAX_LIMIT);
    void scanGpsTags();

    void insert(const FMH::MODEL_LIST &);

    void insertFolder(const QUrl &);
    void insertCity(const QString &);
    void setCitiesModel();

    void setStatus(const Gallery::Status &, const QString& = QString());

Q_SIGNALS:
    void urlsChanged();
    void foldersChanged();
    void autoReloadChanged();
    void recursiveChanged(bool recursive);

    void limitChanged(int limit);

    void filesChanged();

    void citiesChanged();

    void statusChanged();
    void errorChanged(QString error);

    void activeGeolocationTagsChanged(bool activeGeolocationTags);

public Q_SLOTS:
    bool remove(const int &);
    bool deleteAt(const int &);

    void append(const QVariantMap &);
    void append(const QString &);

    void clear();
    void rescan();
    void load();

    void setRecursive(bool);
    void setlimit(int);

    int indexOfName(const QString &);
    void setActiveGeolocationTags(bool activeGeolocationTags);
    void reloadGpsTags();
    void updateGpsTag(const QString &url);
    void scanImagesText();

    static QVariantMap getFolderInfo(const QUrl &url);

};
