#ifndef MODELMANAGER_P_H
#define MODELMANAGER_P_H

#include <QObject>
#include "modelmanager.h"

class DesktopDataHandler;
class AppManager;
class TaskBarManager;
class ModelManagerPrivate : public QObject
{
    Q_DECLARE_PUBLIC(ModelManager)
public:
    ModelManagerPrivate(ModelManager *parent);
    enum ParentItemType {
        Page,
        Group,
    };
    struct PlaceholderItemInfo {
        LauncherItem *placeholderItem = nullptr;
        int itemIndex = -1;
        int pageIndex = -1;
        int groupId = -1;
        ParentItemType parentItemType;
    };

    void initTaskBarData(const QList<quint32> &ids,
                         const QMap<quint32,
                         UKUI::BaseItem *> &itemData);

    LauncherItem *createLauncherItem(LauncherItem::ItemType type,
                                     UKUI::BaseItem *srcItem,
                                     int page);

    ///
    /// \brief layoutForAddPlaceholderItem 如果添加 placeholder item 的页当前已经是满屏,
    ///  则需要将最后一个 item 移动到下一个屏幕,需要重新布局
    /// \param page 当前插入 placeholder item 的页
    /// \param groupId placeholder item 所在的分组 id,默认为 -1,即不在分组内
    ///
    void layoutForAddPlaceholderItem(int page, int groupId = -1);

    ///
    /// \brief layoutForRemovePlaceholderItem 删除 placeholder item 之后需要重新布局还原位置
    ///
    void layoutForRemovePlaceholderItem();

    ///
    /// \brief layoutForReplacePlaceholderItem 拖动 item 放至 placeholder item 之后,恢复由于插入
    ///  placeholder item 产生的布局变化
    ///
    void layoutForReplacePlaceholderItem();

    LauncherItem *createAddIconItem(int pageIndex, int state = LauncherItem::Normal);
    LauncherItem *createAppIcon(int itemId, int pageIndex);

    ///
    /// \brief createPage 创建新页
    /// \param pageIndex 页索引
    /// \param groupId 页所在的分组
    /// \param state 页的状态，默认为 LauncherItem::Editable
    /// \return 返回创建的页model
    ///
    PageModel *createPage(int pageIndex,
                          int groupId,
                          int state = LauncherItem::Editable);
    void tryAddAddIcon(int page, int groupId);

    QPair<QString, QString> categoryIcon(int category);
    bool itemExists(int groupId, int itemId);

    ///
    /// \brief itemGroupId 查找item所在的group的id
    /// \param itemId
    /// \return 如果item不在分组内则返回-1
    ///
    int itemGroupId(int itemId);
    QList<quint32> groupIds(int groupId) const;
    ///
    /// \brief removeGroupItem 主要用于添加界面的数据操作
    /// \param itemId
    /// \param groupId
    ///
    void removeGroupItem(int itemId, int groupId);

    void removeItemFromCategory(int itemId);
    int categoryOfAddtionPage(int page);

    QList<int> selectedIds() const;

    bool categoryContainsItem(int itemId, int category);

    ///
    /// \brief autoPushBackItemForGroup
    /// \param itemId
    /// \param groupId
    /// \param startPageIndex
    /// \return
    ///
    int autoPushBackItemForGroup(int itemId,
                                 int groupId,
                                 int startPageIndex);

    ///
    /// \brief updateCategoriesItemsPageIndex update the pageIndex of item in \memberof categoryItemsModel
    /// \param startPageIndex
    /// \param diff
    ///
    void updateCategoriesItemsPageIndex(int startPageIndex, int diff);

    void initSelectedItemIds(int groupId);

    ///
    /// \brief availableId 找到一个有效可用的id
    /// \return
    ///
    int availableId();

    LauncherItem *item(int itemId);

    ///
    /// \brief setItemNameVisible 设置分组内的item的名称是否可见
    /// \param model 分组的model
    /// \param visible bool
    ///
    void setItemNameVisible(MultiPageModel *model, bool visible);

    ///
    /// \brief replaceGroupWithAppIcon 当分组内只有一个应用时，用分组内的应用替换掉分组
    /// \param groupId
    ///
    void replaceGroupWithAppIcon(int groupId);

    bool onlyOneItemInGroup(int groupId);

    int findTheSameNumber(const QList<int> &set1, const QList<int> &set2);

    bool placeholderAvailable();
    void clearPlaceholderItemInfo();

    ///
    /// \brief availableModel 根据groupId返回指定的model
    /// \param groupId 想要获取的分组model的id，获取主页的model时传-1
    /// \return 当groupId不为-1且未找到对应的分组model时返回nullptr
    ///
    MultiPageModel *availableModel(int groupId);

    ///
    /// \brief itemIndexIsValid 用于判断item对应的index和pageIndex是否合法
    /// \param itemIndex item在所在页的index
    /// \param pageIndex item所在页的indx
    /// \param model item所在的model
    /// \return 合法时返回true
    ///
    bool itemIndexIsValid(int itemIndex, int pageIndex, const MultiPageModel *model);

    ///
    /// \brief groupAddPage 分组创建新页
    /// \param groupId 分组的id
    /// \return
    ///
    void groupAddPage(int groupId);

    ///
    /// \brief removeEmptyPage 删除model的某一页后，它后面所有页的item的PageIndex要减1
    /// \param groupId 需要设置PageIndex的model
    /// \return
    ///
    void removeEmptyPage(MultiPageModel * const model);

    ///
    /// \brief findGroupPageIndexFromDesktop 通过groupId查找分组在桌面的pageIndex
    /// \param groupId 分组的groupId
    /// \return 分组在桌面的pageIndex
    ///
    int findGroupPageIndexFromDesktop(const int &groupId);

    ///
    /// \brief removeGroupFromDesktop 将分组从桌面删除
    /// \param groupId 分组的groupId
    ///
    void removeGroupFromDesktop(const int &groupId);

    ///
    /// \brief fillUpGroupEmptySpace 分组应用卸载，后一页应用向前补齐空位
    /// \param page 卸载的应用所在的page
    /// \param groupId
    ///
    void fillUpGroupEmptySpace(int page, int groupId);

    ///
    /// \brief getGroupState 获取分组当前的状态
    /// \param groupId 分组的groupId
    ///
    int getGroupState(const int &groupId);

    ///
    /// \brief gridCount 计算pageIndex页所占网格数
    /// \param groupId
    /// \param pageIndex
    /// \return
    ///
    int gridCount(const int &groupId, const int &pageIndex);

    ///
    /// \brief getAppWhiteList 获取应用白名单
    ///
    void getAppWhiteList();

    ///
    /// \brief isAppInTheWhiteList 应用是否在白名单内
    /// \param desktopname
    ///
    bool isAppInTheWhiteList(const QString &desktopname);

    MultiPageModel launcherModel;
    QMap<int, MultiPageModel *> groupModel;

    // 保存每个分组的每一页可容纳的item的最大数量
    QMap<int, int> maxItemCountAllowedInPageOfGroup;
    const int kMaxItemCountInGroupPage = 16;
    PlaceholderItemInfo placeholderItemInfo;

    CategoryModel categoryModel;
    MultiPageModel categoryItemsModel;

    //
    int currentCategoryOfAddion;

    QList<int> currentSelectedIds;
    const int kTaskBarGroupId = 0;

    /// \todo 根据配置文件修改配置
    int pageItemMaxCount = 24;
    bool needAddIcon = false;
    const int pageItemMaxOfAddition = 28;
    QList<int> editableContainerId = { 2, 4 ,0};
    ///

    // 由于 placeholder item 导致页面布局改变的页
    // 不包括当前放置 placeholder item 的页
    QStack<int> layoutChangedPages;

    int globalState = LauncherItem::Normal;

    DesktopDataHandler *dataHandler;
    AppManager *appManager;
    TaskBarManager *taskBarManager;

    ModelManager *q_ptr;
    QStringList m_appWhiteList;
};

#endif // MODELMANAGER_P_H
