#ifndef TABLEMODEL_H
#define TABLEMODEL_H

#include <QAbstractItemModel>
#include <QModelIndex>
#include <QVariant>
#include <QSqlQuery>
#include <QSqlDatabase>
#include <QUrl>

#include "yacreader_global_gui.h"

class ComicDB;

class ComicItem;

using namespace YACReader;

class ComicModel : public QAbstractItemModel
{
    Q_OBJECT

public:
    enum Columns {
        Number = 0,
        Title,
        FileName,
        NumPages,
        Id,
        Parent_Id,
        Path,
        Hash,
        ReadColumn,
        CurrentPage,
        Rating,
        HasBeenOpened,
        PublicationDate,
        Added,
        Type,
        LastTimeOpened,
        Series,
        Volume,
        StoryArc,
    };

    enum CalculatedColumns {
        Size = Columns::StoryArc + 1,
    };

    enum Roles {
        NumberRole = Qt::UserRole + 1,
        TitleRole,
        FileNameRole,
        NumPagesRole,
        IdRole,
        Parent_IdRole,
        PathRole,
        HashRole,
        ReadColumnRole,
        CurrentPageRole,
        RatingRole,
        HasBeenOpenedRole,
        CoverPathRole,
        PublicationDateRole,
        ReadableTitle,
        AddedRole,
        TypeRole,
        ShowRecentRole,
        RecentRangeRole,
        SizeRole,
        SeriesRole,
        VolumeRole,
        StoryArcRole,
    };

    enum Mode {
        Folder,
        Favorites,
        Reading,
        Recent,
        Label,
        ReadingList,
        SearchResult
    };

public:
    explicit ComicModel(QObject *parent = nullptr);
    ~ComicModel() override;

    QVariant data(const QModelIndex &index, int role) const override;
    Qt::ItemFlags flags(const QModelIndex &index) const override;
    QVariant headerData(int section, Qt::Orientation orientation,
                        int role = Qt::DisplayRole) const override;
    QModelIndex index(int row, int column,
                      const QModelIndex &parent = QModelIndex()) const override;
    QModelIndex parent(const QModelIndex &index) const override;
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    int columnCount(const QModelIndex &parent = QModelIndex()) const override;
    bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) const override;
    bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) override;
    bool canBeResorted();
    QMimeData *mimeData(const QModelIndexList &indexes) const override;
    QStringList mimeTypes() const override;

    void setupFolderModelData(unsigned long long int parentFolder, const QString &databasePath);
    void setupLabelModelData(unsigned long long int parentLabel, const QString &databasePath);
    void setupReadingListModelData(unsigned long long int parentReadingList, const QString &databasePath);
    void setupFavoritesModelData(const QString &databasePath);
    void setupReadingModelData(const QString &databasePath);
    void setupRecentModelData(const QString &databasePath);

    // Métodos de conveniencia
    QStringList getPaths(const QString &_source);
    QString getComicPath(QModelIndex mi);
    QString getCurrentPath() { return QString(_databasePath).remove("/.yacreaderlibrary"); }
    ComicDB getComic(const QModelIndex &mi); //--> para la edición
    // ComicDB getComic(int row);
    QVector<YACReaderComicReadStatus> getReadList();
    QVector<YACReaderComicReadStatus> setAllComicsRead(YACReaderComicReadStatus readStatus);
    QList<ComicDB> getComics(QList<QModelIndex> list); //--> recupera la información común a los comics seleccionados
    QList<ComicDB> getAllComics();
    QModelIndex getIndexFromId(quint64 id);
    QList<QModelIndex> getIndexesFromIds(const QList<qulonglong> &comicIds);
    // setcomicInfo(QModelIndex & mi); --> inserta en la base datos
    // setComicInfoForAllComics(); --> inserta la información común a todos los cómics de una sola vez.
    // setComicInfoForSelectedComis(QList<QModelIndex> list); -->inserta la información común para los comics seleccionados
    QVector<YACReaderComicReadStatus> setComicsRead(QList<QModelIndex> list, YACReaderComicReadStatus read);
    void setComicsType(QList<QModelIndex> list, FileType type);
    qint64 asignNumbers(QList<QModelIndex> list, int startingNumber);
    // void remove(ComicDB * comic, int row);
    void removeInTransaction(int row);
    void reloadContinueReading();
    void reload();
    void reload(const ComicDB &comic);
    void resetComicRating(const QModelIndex &mi);
    void notifyCoverChange(const ComicDB &comic);

    Q_INVOKABLE QUrl getCoverUrlPathForComicHash(const QString &hash) const;

    void addComicsToFavorites(const QList<QModelIndex> &comicsList);
    void addComicsToLabel(const QList<QModelIndex> &comicsList, qulonglong labelId);
    void addComicsToReadingList(const QList<QModelIndex> &comicsList, qulonglong readingListId);

    void deleteComicsFromFavorites(const QList<QModelIndex> &comicsList);
    void deleteComicsFromReading(const QList<QModelIndex> &comicsList);
    void deleteComicsFromSpecialList(const QList<QModelIndex> &comicsList, qulonglong specialListId);
    void deleteComicsFromLabel(const QList<QModelIndex> &comicsList, qulonglong labelId);
    void deleteComicsFromReadingList(const QList<QModelIndex> &comicsList, qulonglong readingListId);

    void deleteComicsFromModel(const QList<QModelIndex> &comicsList);

    bool isFavorite(const QModelIndex &index);

    ComicModel::Mode getMode() { return mode; }
    unsigned long long int getSourceId() { return sourceId; }

    void setShowRecent(bool visible);
    void setRecentRange(int days);

    QHash<int, QByteArray> roleNames() const override;

public slots:
    void remove(int row);
    void startTransaction();
    void finishTransaction();
    void updateRating(int rating, QModelIndex mi);

    void addComicsToFavorites(const QList<qulonglong> &comicIds);
    void addComicsToLabel(const QList<qulonglong> &comicIds, qulonglong labelId);
    void addComicsToReadingList(const QList<qulonglong> &comicIds, qulonglong readingListId);

    void setModelData(QList<ComicItem *> *data, const QString &databasePath);

protected:
private:
    QList<ComicItem *> createModelData(QSqlQuery &sqlquery) const;
    QList<ComicItem *> createModelDataForList(QSqlQuery &sqlquery) const;

    QList<ComicItem *> createFolderModelData(unsigned long long parentLabel, const QString &databasePath) const;
    QList<ComicItem *> createLabelModelData(unsigned long long parentLabel, const QString &databasePath) const;
    QList<ComicItem *> createReadingListData(unsigned long long parentReadingList, const QString &databasePath, bool &enableResorting) const;
    QList<ComicItem *> createFavoritesModelData(const QString &databasePath) const;
    QList<ComicItem *> createReadingModelData(const QString &databasePath) const;
    QList<ComicItem *> createRecentModelData(const QString &databasePath) const;

    void takeData(const QList<ComicItem *> &data);
    void takeUpdatedData(const QList<ComicItem *> &updatedData, std::function<bool(ComicItem *, ComicItem *)> comparator);
    ComicDB _getComic(const QModelIndex &mi);
    QList<ComicItem *> _data;

    QString _databasePath;
    QString _databaseConnection;

    bool enableResorting;
    Mode mode;
    qulonglong sourceId;
    QString localizedDate(const QString &dbDate) const;

    bool showRecent;
    qlonglong recentDays;

signals:
    void isEmpty();
    void searchNumResults(int);
    void resortedIndexes(QList<int>);
    void newSelectedIndex(const QModelIndex &);
};

#endif
