#include "desktopdatahandler.h"
#include <QThread>
#include <QDebug>

DesktopDataHandler::DesktopDataHandler(QObject *parent)
    : QObject(parent)
{
    qRegisterMetaType<QMap<quint32,QList<quint32> >>("QMap<quint32,QList<quint32> >");
    qRegisterMetaType<QMap<quint32,QList<quint32> >>("QMap<quint32, QList<QList<quint32>>>");
    qRegisterMetaType<QMap<quint32,UKUI::BaseItem*>>("QMap<quint32,UKUI::BaseItem*>");
    qRegisterMetaType<QMap<UKUI::Categories, QList<quint32>>>("QMap<UKUI::Categories, QList<quint32>>");
    qRegisterMetaType<QList<QList<quint32> >>("QList<QList<quint32> >");
    qRegisterMetaType<QList<quint32> >("QList<quint32>");
}

DesktopDataHandler::~DesktopDataHandler()
{
    m_dataBackend->deleteLater();
}

QString DesktopDataHandler::categoryName(int category) const
{
    if (!m_categories.contains(static_cast<UKUI::Categories>(category))) {
        return QString();
    }
    return m_categories.value(static_cast<UKUI::Categories>(category));
}

QList<quint32> DesktopDataHandler::apps() const
{
    return m_apps;
}

QMap<quint32, UKUI::BaseItem *> DesktopDataHandler::items() const
{
    return m_itemsData;
}

QMap<UKUI::Categories, QString> DesktopDataHandler::categories() const
{
    return m_categories;
}

QMap<UKUI::Categories, QList<quint32>> DesktopDataHandler::categoriesItems() const
{
    return m_categoriesItems;
}

void DesktopDataHandler::init()
{
    m_dataBackend = new UKUI::TabletDesktopBackend();
    m_pageData = m_dataBackend->getAllPageData();
    m_setData = m_dataBackend->getAllFlipSetsData();
    // taskbar data
    QList<QList<quint32>> taskBarData;
    taskBarData.push_back(m_dataBackend->getAllScrollSetsData().value(0));
    m_setData[0] = taskBarData;
    m_itemsData = m_dataBackend->getAllItemData();
    Q_EMIT desktopData(m_pageData, m_setData, m_itemsData);

    m_apps = m_dataBackend->getAllAppIdList();
    m_categories = m_dataBackend->getAllAppCategories();
    m_categoriesItems.clear();
    auto it = m_categories.constBegin();
    while (it != m_categories.constEnd()) {
        m_categoriesItems.insert(it.key(), m_dataBackend->getAppIdListAccordingCategory(it.key()));
        ++ it;
    }

    Q_EMIT categoriesData(m_categoriesItems);

    connect(m_dataBackend, &UKUI::TabletDesktopBackend::itemAdded,
            this, &DesktopDataHandler::addItem);
    connect(m_dataBackend, &UKUI::TabletDesktopBackend::iconThemeChanged,
            this, &DesktopDataHandler::iconThemeChanged);

    connect(m_dataBackend, &UKUI::TabletDesktopBackend::itemDeletedFromPage, [this](quint32 id, quint32 pageId) {
        Q_UNUSED(pageId)
        int groupId = groupIdOfItem(id);
        if (groupId > 0) {
            Q_EMIT appUninstalledFromGroup(id, groupId);
        } else {
           Q_EMIT appUninstalled(id);
        }
        /// \todo
        ///  需要优化，仅更新改动的数据即可
        updateDekstopData();
    });
    connect(m_dataBackend, &UKUI::TabletDesktopBackend::itemDeletedFromSet, [this](quint32 id, quint32 setId) {
        updateDekstopData();
        Q_EMIT appUninstalledFromGroup(id, setId);
    });

    connect(m_dataBackend, &UKUI::TabletDesktopBackend::taskBarAppChanged, this, &DesktopDataHandler::changeTaskBarApp);
    connect(this, &DesktopDataHandler::uninsatllApp, m_dataBackend, &UKUI::TabletDesktopBackend::uninsatllApp);
}

#if 0
void DesktopDataHandler::moveItem(int from, int to, int page, int groupId)
{
    if (groupId > 0) {
        m_setData[groupId][page].move(from, to);
        m_dataBackend->modifySetData(groupId, m_setData.value(groupId));
    }
}

void DesktopDataHandler::removeItem(int index, int page, int groupId)
{
    if (groupId > 0) {
        m_setData[groupId][page].removeAt(index);
        if (m_setData.value(groupId).at(page).isEmpty()) {
            m_setData[groupId].removeAt(page);
        }
        m_dataBackend->modifySetData(groupId, m_setData.value(groupId));
    }
}

void DesktopDataHandler::insertItem(int index, int page, int itemId, int groupId)
{
    if (groupId > 0) {
        // 将图标拖动至新建的页
        if (m_setData[groupId].count() == page) {
            m_setData[groupId].push_back(QList<quint32>());
        }
        m_setData[groupId][page].insert(index, itemId);
        m_dataBackend->modifySetData(groupId, m_setData.value(groupId));
    }
}
#endif

void DesktopDataHandler::setGroupName(const QString &name, int groupId)
{
    if (!m_setData.contains(groupId)) {
        return;
    }
    if (!m_dataBackend->modifySetName(groupId, name)) {
        qWarning() << "set group name failed: " << name << groupId;
    }
}

void DesktopDataHandler::updateGroup(const QList<QList<quint32> > &ids, int groupId)
{
    Q_ASSERT(groupId >= -1);
    // main page group
    if (groupId == -1) {
        /// \note from 0 index
        int pageIndex = 0;
        for (auto &pageIds : ids) {
            m_pageData[pageIndex] = pageIds;
            if (!m_dataBackend->setPageData(pageIndex, pageIds)) {
                qWarning() << __func__ << "修改page页数据失败";
                return;
            }
            ++ pageIndex;
        }

        // 应用移动后出现的空白页，要调用后台接口删除
        int removePageCount = m_pageData.count() - ids.count();
        for (int i = 0; i < removePageCount; i++) {
            qDebug() << "删除空白页--->" << m_pageData.count() - 1 << m_pageData.lastKey();
            m_dataBackend->deleteLauncherPage(m_pageData.count() - 1);
            m_pageData.remove(m_pageData.lastKey());
        }
    } else {
        m_setData[groupId] = ids;
        // task bar
        if (groupId == 0) {
            if (ids.isEmpty()) {
                qDebug() << "task bar data udpate: " << ids;
                if (!m_dataBackend->setScrollSetData(0, QList<quint32>())) {
                    qWarning() << __func__ << "修改scrollset数据失败";
                }
                return;
            }
            qDebug() << "task bar data udpate: " << ids.first();
            if (!m_dataBackend->setScrollSetData(0, ids.first())) {
                qWarning() << __func__ << "修改scrollset数据失败";
            }
        } else if (groupId > 0){
            if (!m_dataBackend->setFlipSetData(groupId, ids)) {
                qWarning() << __func__ << "修改flipset数据失败";
            }
        }
    }
}

void DesktopDataHandler::createGroup(quint32 groupId, const QList<quint32> &itemIdList, const QString &groupName)
{
    m_dataBackend->createGroup(groupId, itemIdList, groupName);
    m_setData.insert(groupId, QList<QList<quint32>>() << itemIdList);
}

void DesktopDataHandler::removeGroup(quint32 groupId)
{
    m_setData.remove(groupId);
    m_dataBackend->deleteGroup(groupId);
}

void DesktopDataHandler::updateDekstopData()
{
    m_pageData = m_dataBackend->getAllPageData();
    m_setData = m_dataBackend->getAllFlipSetsData();
    m_itemsData = m_dataBackend->getAllItemData();
    QList<QList<quint32>> taskBarData;
    taskBarData.push_back(m_dataBackend->getAllScrollSetsData().value(0));
    m_setData[0] = taskBarData;

    m_apps = m_dataBackend->getAllAppIdList();
    m_categories = m_dataBackend->getAllAppCategories();
    m_categoriesItems.clear();
    auto it = m_categories.constBegin();
    while (it != m_categories.constEnd()) {
        m_categoriesItems.insert(it.key(), m_dataBackend->getAppIdListAccordingCategory(it.key()));
        ++ it;
    }
}

void DesktopDataHandler::addItem(quint32 itemId, int page)
{
    bool newCategory = false;
    int indexOfAllCategory = 0;
    int indexOfCategory = 0;
    int category = 0;
    auto it = m_categories.constBegin();
    while (it != m_categories.constEnd()) {
        auto newCategoryItems = m_dataBackend->getAppIdListAccordingCategory(it.key());
        if (m_categoriesItems.value(it.key()) != newCategoryItems) {
            if (m_categoriesItems.value(it.key()).isEmpty()) {
                newCategory = true;
            } else {
                indexOfCategory = newCategoryItems.indexOf(itemId);
            }
            category = 1 + static_cast<int>(it.key());
            break;
        }
        ++ it;
    }
    updateDekstopData();
    indexOfAllCategory = m_apps.indexOf(itemId);

    Q_EMIT appInstalled(itemId, indexOfAllCategory, indexOfCategory, page, newCategory, category);
}

void DesktopDataHandler::removeItem(quint32 itemId, int page)
{
    Q_UNUSED(itemId)
    Q_UNUSED(page)
#if 0
    Q_ASSERT(m_pageData.contains(page) &&m_pageData.value(page).contains(itemId));
    m_pageData[page].removeOne(itemId);

    Q_EMIT itemRemoved(itemId, page);
#endif
    updateDekstopData();
}

void DesktopDataHandler::iconThemeChanged()
{
    m_itemsData = m_dataBackend->getAllItemData();
    Q_EMIT iconChanged();
}

void DesktopDataHandler::changeTaskBarApp(appChangeInfo appChangeData)
{
    qDebug() << "--->taskbarAppChangeData remove app itemid,changefromindex,toindex--->"
             << appChangeData.itemId << appChangeData.itemFromPage << appChangeData.itemFromPageIndex
             << appChangeData.itemToPage << appChangeData.itemToPageIndex;

    //任务栏移除应用
    if (appChangeData.isTaskbarDeleteApp && !appChangeData.isDesktopDeleteApp && !appChangeData.isExchangePosition) {

        m_setData[0][0].removeAt(appChangeData.itemFromPageIndex);

        m_pageData[appChangeData.itemToPage].push_back(appChangeData.itemId);

        Q_EMIT taskbarDataChange(appChangeData);
    }

    //任务栏添加应用
    if (!appChangeData.isTaskbarDeleteApp && appChangeData.isDesktopDeleteApp && !appChangeData.isExchangePosition) {

        for (int i = 0; i < m_pageData[appChangeData.itemFromPage].count(); i++) {
            if (m_pageData[appChangeData.itemFromPage].at(i) == appChangeData.itemId) {
                m_pageData[appChangeData.itemFromPage].removeAt(i);
                break;
            }
        }

        m_setData[0][0].insert(appChangeData.itemToPageIndex, appChangeData.itemId);
        Q_EMIT taskbarDataChange(appChangeData);
    }

    //任务栏交换应用
    if (!appChangeData.isTaskbarDeleteApp && !appChangeData.isDesktopDeleteApp && appChangeData.isExchangePosition) {
        m_setData[0][0].move(appChangeData.itemFromPageIndex, appChangeData.itemToPageIndex);

        Q_EMIT taskbarDataChange(appChangeData);
    }
}

int DesktopDataHandler::groupIdOfItem(int itemId)
{
    auto it = m_setData.constBegin();
    while(it != m_setData.constEnd()) {
        for (const auto &page : it.value()) {
            if (page.contains(itemId)) {
                return it.key();
            }
        }
        ++ it;
    }
    return -1;
}
