#ifndef NOTELISTMODEL_H // 头文件保护，防止重复包含
#define NOTELISTMODEL_H

#include <QAbstractListModel> // 包含QAbstractListModel类
#include "nodedata.h" // 包含NodeData类，用于存储笔记数据
#include "dbmanager.h" // 包含数据库管理器

class NoteListModel : public QAbstractListModel // 继承自QAbstractListModel
{
    Q_OBJECT // 宏，用于支持Qt的信号和槽机制

            public :
        // 定义笔记模型的角色枚举
        enum NoteRoles {
            NoteID = Qt::UserRole + 1, // 笔记ID角色
            NoteFullTitle, // 笔记完整标题角色
            NoteCreationDateTime, // 笔记创建日期时间角色
            NoteLastModificationDateTime, // 笔记最后修改日期时间角色
            NoteDeletionDateTime, // 笔记删除日期时间角色
            NoteContent, // 笔记内容角色
            NoteScrollbarPos, // 笔记滚动条位置角色
            NoteTagsList, // 笔记标签列表角色
            NoteIsTemp, // 笔记是否为临时笔记角色
            NoteParentName, // 笔记父级名称角色
            NoteTagListScrollbarPos, // 笔记标签列表滚动条位置角色
            NoteIsPinned // 笔记是否被钉住角色
        };

    // 构造函数，可以指定一个父对象
    explicit NoteListModel(QObject *parent = nullptr);
    // 析构函数
    ~NoteListModel();

    // 添加笔记，并返回新笔记的模型索引
    QModelIndex addNote(const NodeData &note);
    // 在指定行插入笔记，并返回新笔记的模型索引
    QModelIndex insertNote(const NodeData &note, int row);
    // 获取指定模型索引的笔记数据
    const NodeData &getNote(const QModelIndex &index) const;
    // 获取指定ID的笔记的模型索引
    QModelIndex getNoteIndex(int id) const;
    // 设置笔记列表和列表视图信息
    void setListNote(const QVector<NodeData> &notes, const ListViewInfo &inf);
    // 移除指定模型索引列表的笔记
    void removeNotes(const QModelIndexList &noteIndexes);
    // 移动行
    bool moveRow(const QModelIndex &sourceParent, int sourceRow,
                 const QModelIndex &destinationParent, int destinationChild);

    // 清空笔记列表
    void clearNotes();
    // 获取指定模型索引的数据
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    // 设置指定模型索引的数据
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
    // 获取指定模型索引的项标志
    Qt::ItemFlags flags(const QModelIndex &index) const override;
    // 获取行数
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    // 排序
    void sort(int column, Qt::SortOrder order) override;
    // 设置指定模型索引的笔记数据
    void setNoteData(const QModelIndex &index, const NodeData &note);

    // 获取支持的拖放操作
    virtual Qt::DropActions supportedDropActions() const override;
    // 获取支持的拖拽操作
    virtual Qt::DropActions supportedDragActions() const override;
    // 获取支持的MIME类型
    virtual QStringList mimeTypes() const override;
    // 获取指定模型索引列表的MIME数据
    virtual QMimeData *mimeData(const QModelIndexList &indexes) const override;
    // 处理MIME数据的拖放
    virtual bool dropMimeData(const QMimeData *mime, Qt::DropAction action, int row, int column,
                              const QModelIndex &parent) override;

    // 检查指定模型索引的笔记是否具有标签
    bool noteIsHaveTag(const QModelIndex &index) const;
    // 检查指定模型索引的笔记是否为第一个被钉住的笔记
    bool isFirstPinnedNote(const QModelIndex &index) const;
    // 检查指定模型索引的笔记是否为第一个未被钉住的笔记
    bool isFirstUnpinnedNote(const QModelIndex &index) const;
    // 获取第一个被钉住的笔记的模型索引
    QModelIndex getFirstPinnedNote() const;
    // 检查是否有被钉住的笔记
    bool hasPinnedNote() const;
    // 设置指定模型索引列表的笔记的钉住状态
    void setNotesIsPinned(const QModelIndexList &indexes, bool isPinned);

private:
    QVector<NodeData> m_noteList; // 笔记列表
    QVector<NodeData> m_pinnedList; // 被钉住的笔记列表
    ListViewInfo m_listViewInfo; // 列表视图信息

    // 更新被钉住的笔记的相对位置
    void updatePinnedRelativePosition();
    // 检查是否在所有笔记中
    bool isInAllNote() const;
    // 获取指定行的笔记数据的引用
    NodeData &getRef(int row);
    // 获取指定行的笔记数据的常量引用
    const NodeData &getRef(int row) const;

signals:
    // 行数发生变化时发出的信号
    void rowCountChanged();
    // 请求更新笔记的钉住状态时发出的信号
    void requestUpdatePinned(int noteId, bool isPinned);
    // 请求更新笔记的相对位置时发出的信号
    void requestUpdatePinnedRelPos(int noteId, int pos);
    // 请求更新笔记的相对位置（在所有笔记中）时发出的信号
    void requestUpdatePinnedRelPosAN(int noteId, int pos);
    // 请求移除笔记时发出的信号
    void requestRemoveNotes(QModelIndexList index);
    // 行插入时发出的信号
    void rowsInsertedC(const QModelIndexList &rows);
    // 行即将被移动时发出的信号
    void rowsAboutToBeMovedC(const QModelIndexList &source);
    // 行移动后发出的信号
    void rowsMovedC(const QModelIndexList &dest);
    // 请求关闭笔记编辑器时发出的信号
    void requestCloseNoteEditor(const QModelIndexList &indexes);
    // 请求打开笔记编辑器时发出的信号
    void requestOpenNoteEditor(const QModelIndexList &indexes);
    // 选择笔记时发出的信号
    void selectNotes(const QModelIndexList &indexes);

    // 重写QAbstractItemModel的接口
public:
    // 移除行
    bool removeRows(int row, int count, const QModelIndex &parent) override;
};

#endif // NOTELISTMODEL_H