#ifndef NODETREEMODEL_H
#define NODETREEMODEL_H

#include <QAbstractItemModel>
#include <QModelIndex>
#include <QVariant>
#include <QHash>
#include <QVector>

#include "nodedata.h"
#include "dbmanager.h"
#include "nodepath.h"
// NodeItem 命名空间，定义角色和类型枚举
namespace NodeItem {
enum Roles {
    ItemType = Qt::UserRole, // 项类型
    DisplayText = Qt::DisplayRole, // 显示文本
    Icon = Qt::DecorationRole, // 图标
    TagColor = Qt::UserRole + 1, // 标签颜色
    IsExpandable, // 是否可展开
    AbsPath, // 绝对路径
    RelPos, // 相对位置
    ChildCount, // 子项数量
    NodeId // 节点ID
};
enum Type {
    AllNoteButton = 1, // 所有笔记按钮
    TrashButton, // 垃圾桶按钮
    FolderSeparator, // 文件夹分隔符
    TagSeparator, // 标签分隔符
    FolderItem, // 文件夹项
    NoteItem, // 笔记项
    TagItem, // 标签项
    RootItem // 根项
};
} // namespace NodeItem

class NodeTreeItem// NodeTreeItem 类，表示树中的一个节点
{
public:
    explicit NodeTreeItem(const QHash<NodeItem::Roles, QVariant> &data,
                          NodeTreeItem *parentItem = nullptr); // 构造函数
    ~NodeTreeItem(); // 析构函数

    void appendChild(NodeTreeItem *child); // 添加子节点
    void insertChild(int row, NodeTreeItem *child); // 在指定位置插入子节点
    NodeTreeItem *child(int row); // 获取指定位置的子节点
    void removeChild(int row); // 移除指定位置的子节点
    NodeTreeItem *takeChildAt(int row); // 移除并返回指定位置的子节点
    int childCount() const; // 获取子节点数量
    int columnCount() const; // 获取列数
    int recursiveNodeCount() const; // 递归获取节点数量
    void recursiveUpdateFolderPath(const QString &oldP, const QString &newP); // 递归更新文件夹路径
    QVariant data(NodeItem::Roles role) const; // 获取指定角色的数据
    void setData(NodeItem::Roles role, const QVariant &d); // 设置指定角色的数据
    int row() const; // 获取当前节点的行号
    NodeTreeItem *parentItem(); // 获取父节点
    void setParentItem(NodeTreeItem *parentItem); // 设置父节点
    void moveChild(int from, int to); // 移动子节点
    void recursiveSort(); // 递归排序

private:
    QVector<NodeTreeItem *> m_childItems; // 子节点列表
    QHash<NodeItem::Roles, QVariant> m_itemData; // 节点数据
    NodeTreeItem *m_parentItem; // 父节点
};

class NodeTreeModel : public QAbstractItemModel// NodeTreeModel 类，继承自 QAbstractItemModel
{
    Q_OBJECT
public:
    explicit NodeTreeModel(QObject *parent = nullptr); // 构造函数
    ~NodeTreeModel(); // 析构函数

    void
    appendChildNodeToParent(const QModelIndex &parentIndex,
                            const QHash<NodeItem::Roles, QVariant> &data); // 向父节点添加子节点
    QModelIndex rootIndex() const; // 获取根节点索引
    QModelIndex folderIndexFromIdPath(const NodePath &idPath); // 根据ID路径获取文件夹索引
    QModelIndex tagIndexFromId(int id); // 根据ID获取标签索引
    QString getNewFolderPlaceholderName(const QModelIndex &parentIndex); // 获取新文件夹占位符名称
    QString getNewTagPlaceholderName(); // 获取新标签占位符名称
    QVector<QModelIndex> getSeparatorIndex(); // 获取分隔符索引
    QModelIndex getDefaultNotesIndex(); // 获取默认笔记索引
    QModelIndex getAllNotesButtonIndex(); // 获取所有笔记按钮索引
    QModelIndex getTrashButtonIndex(); // 获取垃圾桶按钮索引
    void deleteRow(const QModelIndex &rowIndex, const QModelIndex &parentIndex); // 删除行

public slots:
    void setTreeData(const NodeTagTreeData &treeData); // 设置树数据

    // QAbstractItemModel interface接口实现
public:
    virtual QModelIndex index(int row, int column,
                              const QModelIndex &parent) const override; // 获取索引
    virtual QModelIndex parent(const QModelIndex &index) const override; // 获取父索引
    virtual int rowCount(const QModelIndex &parent) const override; // 获取行数
    virtual int columnCount(const QModelIndex &parent) const override; // 获取列数
    virtual QVariant data(const QModelIndex &index, int role) const override; // 获取数据
    virtual Qt::ItemFlags flags(const QModelIndex &index) const override; // 获取项目标志
    virtual bool setData(const QModelIndex &index, const QVariant &value,
                         int role) override; // 设置数据
    virtual Qt::DropActions supportedDropActions() const override; // 支持的拖放动作
    virtual Qt::DropActions supportedDragActions() const override; // 支持的拖动动作
    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; // 处理拖放数据

signals:
    void topLevelItemLayoutChanged(); // 顶层项目布局变化信号
    void requestExpand(const QString &indexPath); // 请求展开信号
    void requestMoveNode(int nodeId, int targetId); // 请求移动节点信号
    void requestUpdateNodeRelativePosition(int nodeId,
                                           int relativePosition); // 请求更新节点相对位置信号
    void requestUpdateTagRelativePosition(int nodeId,
                                          int relativePosition); // 请求更新标签相对位置信号
    void requestUpdateAbsPath(const QString &oldPath,
                              const QString &newPath); // 请求更新绝对路径信号
    void dropFolderSuccessful(const QString &paths); // 文件夹拖放成功信号
    void dropTagsSuccessful(const QSet<int> &ids); // 标签拖放成功信号
    void requestMoveFolderToTrash(const QModelIndex &index); // 请求移动文件夹到垃圾桶信号

private:
    NodeTreeItem *rootItem; // 根节点
    void loadNodeTree(const QVector<NodeData> &nodeData, NodeTreeItem *rootNode); // 加载节点树
    void appendAllNotesAndTrashButton(NodeTreeItem *rootNode); // 添加所有笔记和垃圾桶按钮
    void appendFolderSeparator(NodeTreeItem *rootNode); // 添加文件夹分隔符
    void appendTagsSeparator(NodeTreeItem *rootNode); // 添加标签分隔符
    void loadTagList(const QVector<TagData> &tagData, NodeTreeItem *rootNode); // 加载标签列表
    void updateChildRelativePosition(NodeTreeItem *parent,
                                     const NodeItem::Type type); // 更新子节点相对位置
};

#endif // NODETREEMODEL_H
