#include "platformwindow.h"
#include <QGuiApplication>
#include <QScreen>
#include <QtPlatformHeaders/QXcbWindowFunctions>
#include <kwindowsystem.h>
#include "global-settings.h"
#include "common.h"

#include "file-action-controler.h"
#include "global-settings-adapter.h"
#include "peony-desktop-application.h"
#include "desktop-item-proxy-model.h"
#include "advanced-desktop-item-model.h"
#include "file-info.h"
#include "file-utils.h"
#include "background-manager.h"
#include "windowmanager/windowmanager.h"
#include "screen-manager.h"
#include "theme-style.h"

#ifdef KY_SDK_WAYLANDHELPER
#include <kysdk/applications/ukuiwindowhelper/ukuiwindowhelper.h>
#endif

#include <QFontMetrics>
#include <QFont>
#include <QApplication>
#include <QQuickItem>
#include <QQmlContext>
#include <QQmlEngine>
#include <QMimeData>

using namespace Peony;

static bool iconSizeLessThan (const QPair<QPoint, QString>& p1, const QPair<QPoint, QString>& p2)
{
    if (p1.first.x() > p2.first.x())
        return false;

    if (p1.first.x() < p2.first.x())
        return true;

    if ((p1.first.x() == p2.first.x()))
        return p1.first.y() < p2.first.y();

    return true;
}

PlatformWindow::PlatformWindow(int id,  QScreen* screen, QWindow *parent)
    : QQuickView(parent)
{
    setScreen(screen);

    setColor(Qt::transparent);
    setFlags(flags() | Qt::FramelessWindowHint);
#ifdef KY_SDK_WAYLANDHELPER
    m_wmHelper = new UkuiWindowHelper(this);
    m_wmHelper->setWindowRole(UkuiWindowHelper::WindowRole::Desktop);
    m_wmHelper->setSkipSwitcher(true);
    m_wmHelper->setSkipTaskBar(true);
#endif

    qInfo() << "create new window on "<<screen->name()<<id<<screen->geometry() <<id;
    m_screen = screen;
    setGeometry(screen->geometry());

    m_model = PeonyDesktopApplication::getModel();
    m_proxyModel = new DesktopItemProxyModel(m_model);
    m_proxyModel->setSourceModel(m_model);
    m_proxyModel->setId(id);

    connect(m_proxyModel, &DesktopItemProxyModel::rowsInserted, this, &PlatformWindow::rowsInserted);
    connect(m_model, &AdvancedDesktopItemModel::sig_fileRemoved, this, &PlatformWindow::fileRemoved);
    connect(m_model, &AdvancedDesktopItemModel::refreshed, this, &PlatformWindow::reloadData);
    connect(m_model, &AdvancedDesktopItemModel::idChanged, this, &PlatformWindow::idChanged);
    connect(m_model, &AdvancedDesktopItemModel::invalidateFilterRequest, m_proxyModel, &DesktopItemProxyModel::invalidateModel);

    connect(m_proxyModel, &DesktopItemProxyModel::datechange, m_model, &Peony::AdvancedDesktopItemModel::setdata);
    connect(m_proxyModel, &DesktopItemProxyModel::showHiddenFile, this, &PlatformWindow::showHiddenFile);
    connect(m_proxyModel, &DesktopItemProxyModel::showStandardFile, this, &PlatformWindow::showStandardFile);
    connect(m_proxyModel, &DesktopItemProxyModel::drop, this, &PlatformWindow::drop);

    connect(this, &PlatformWindow::viewUpdated, m_proxyModel, &DesktopItemProxyModel::viewUpdated);

    FileActionController *controller = FileActionController::getInstance();
    GlobalSettingsAdapter *settingsAdapter = GlobalSettingsAdapter::getInstance();

    rootContext()->setContextProperty("mymodel", m_model);
    rootContext()->setContextProperty("myProxyModel", m_proxyModel);
    rootContext()->setContextProperty("controller", controller);
    rootContext()->setContextProperty("globalSettings", settingsAdapter);
    rootContext()->setContextProperty("backgroundManager", BackgroundManager::globalInstance());
    rootContext()->setContextProperty("themeStyle", ThemeStyle::instance());

    m_gridSize = controller->getGridSize();
    QMargins margins = GlobalSettingsAdapter::getInstance()->panelMargins();
    QRect rect = screen->geometry();
    m_availableColumnCount = (rect.width() - margins.left() - margins.right()) / m_gridSize.width();
    m_availableRowCount = (rect.height() - margins.top() - margins.bottom()) / m_gridSize.height();

    QObject::connect(controller, &FileActionController::gridSizeChanged,
                     this, [=](){
        m_gridSize = controller->getGridSize();

        ajustIconsOnScreenSize();
        checkItemsOver();
    });

    connect(m_model, &AdvancedDesktopItemModel::refreshed, controller, &FileActionController::finishRefresh);
    connect(this, &QQuickView::statusChanged, this, [=](QQuickView::Status status) {
         if (status == QQuickView::Ready) {
             qDebug() << "QML loaded, setting final geometry"<<screen->geometry();
             setGeometry(screen->geometry());
             if (rootObject()) {
                 rootObject()->setState("Show");
             }
         }
     });

    connect(GlobalSettingsAdapter::getInstance(), &GlobalSettingsAdapter::valueChanged, this, [=](const QString &key){
        if (key == DESKTOP_USE_AUTO_LAYOUT) {
            bool desktopAutoLayout = GlobalSettingsAdapter::getInstance()->getValue(DESKTOP_USE_AUTO_LAYOUT).toBool();
            if (desktopAutoLayout) {
                m_itemPosHash.clear();
                m_autoArrange.clear();
                m_storageBox.clear();
                m_resolutionItemPosHash.clear();
                auto sortedUris = layoutItems();
            }
        }
    });

    connect(GlobalSettingsAdapter::getInstance(), &GlobalSettingsAdapter::panelMarginsChanged, this, [=](){
        ajustIconsOnScreenSize();
        checkItemsOver();
    });

    const QUrl url(QStringLiteral("qrc:/qml-desktop/DesktopView.qml"));
    setSource(url);

    setResizeMode(QQuickView::SizeRootObjectToView);
    qDebug() << "gridSize:"<<m_gridSize;
    showFullScreen();
}

void PlatformWindow::rowsInserted(const QModelIndex &parent, int first, int last)
{
    QString firstEditUri;
    QStringList& editUris = FileActionController::getInstance()->urisToEdit();
    if (editUris.isEmpty()) {
        return;
    }
    firstEditUri = Peony::FileUtils::urlDecode(editUris.first());
    for (int row = first; row <= last; ++row) {
        QModelIndex proxyIndex = m_proxyModel->index(row, 0, parent);
        QModelIndex sourceIndex = m_proxyModel->mapToSource(proxyIndex);

        QString uri = m_model->data(sourceIndex, UriRole).toString();
        qDebug() << "Inserted item (source):" << uri;
        QString infoUri = Peony::FileUtils::urlDecode(uri);
        qDebug() << "fileCreated editUri:"<<firstEditUri<<infoUri;
        if (firstEditUri == infoUri ) {
            QTimer::singleShot(100, this, [=]() {
                Q_EMIT FileActionController::getInstance()->edit(uri);
            });
            editUris.clear();
        }
    }
}

void PlatformWindow::updateWindowGeometry()
{
    if (!m_screen) {
        qWarning() << "PlatformaWindow Screen is null.";
        return;
    }

    if (m_screen->geometry() == geometry()) {
        qInfo() << "geometry of PlatformaWindow is the sanme as geometry of Screen."<<geometry();
        return;
    }

    qDebug() << "displayMode:"<<ScreenManager::getInstance()->displayMode();

    if (ScreenManager::getInstance()->displayMode() == ScreenManager::Mirror && m_proxyModel->id() != 0) {
        qDebug() << "geometry of screen when Mirror "<<m_screen->geometry()<<this->geometry();
         //镜像下也需要更新位置，切换扩展或者单屏下可能不会有geometry信号变化
        this->setGeometry(m_screen->geometry());
        this->ajustIconsOnScreenSize();
        lower();
#ifndef KY_SDK_WAYLANDHELPER
        ScreenManager::getInstance()->getWindowById(0)->raise();
#else
        ScreenManager::getInstance()->getWindowById(0)->requestActivate();
#endif
        return;
    }
    if (m_proxyModel->id() == 0) {
#ifndef KY_SDK_WAYLANDHELPER
        raise();
#else
        this->requestActivate();
#endif
    }
    qDebug() << "geometry: "<<m_screen->geometry();

    this->setGeometry(m_screen->geometry());
    this->ajustIconsOnScreenSize();
    this->requestUpdate();
}

//void PlatformWindow::resizeEvent(QResizeEvent *ev)
//{
//    if (!this->screen()) {
//        qWarning() << "PlatformaWindow Screen is null.";
//        return;
//    }
//    qWarning() << "resize: "<<this->screen()->geometry()<<this->screen()<<m_proxyModel->id();
//    this->setGeometry(this->screen()->geometry());
//    this->ajustIconsOnScreenSize();
//    this->requestUpdate();
//    QQuickView::resizeEvent(ev);
//}

void PlatformWindow::updateView()
{
    m_itemPosHash.clear();
    m_autoArrange.clear();
    m_storageBox.clear();
    m_resolutionItemPosHash.clear();
    m_proxyModel->invalidate();

    this->ajustIconsOnScreenSize();
    this->checkItemsOver();

    Q_EMIT viewUpdated();
}

void PlatformWindow::ajustIconsOnScreenSize()
{
    QMargins margins = GlobalSettingsAdapter::getInstance()->panelMargins();
    QRect rect = this->geometry();
    m_availableColumnCount = (rect.width() - margins.left() - margins.right()) / m_gridSize.width();
    m_availableRowCount = (rect.height() - margins.top() - margins.bottom()) / m_gridSize.height();

    m_itemPosHash.clear();
    if (GlobalSettingsAdapter::getInstance()->useAutoLayout()) {
        if (m_autoArrange.count() != m_proxyModel->rowCount()) {
            layoutItems();
        } else {
            relayoutExsitingItemsAndUpdate(m_autoArrange);
        }
        return;
    }
    QStringList needChanged;
    for (int row = 0; row < m_proxyModel->rowCount(); row++) {
        auto index = m_proxyModel->index(row, 0, QModelIndex());
        QString uri = index.data(UriRole).toString();
        QPoint pos = index.data(PositionRole).toPoint();
        m_itemPosHash.insert(uri, pos);
        if (isInvalidPoint(pos)) {
            needChanged.append(uri);
            if (!m_resolutionItemPosHash.contains(uri)) {
                // remember item position before resolution changed.
                m_resolutionItemPosHash.insert(uri, pos);
            }
        }
    }

    qInfo()<<"need changed item"<<needChanged << " resolution item" << m_resolutionItemPosHash;

    if (!needChanged.isEmpty()) {
        qInfo()<<"屏幕过小，有元素超过屏幕范围" ;
        relayoutExsitingItems(needChanged);
    } else {
        qInfo()<<"没有元素超过屏幕范围， 尝试恢复超过屏幕范围的元素" <<m_resolutionItemPosHash;
        QStringList itemNeedBeRelayout;
        for (auto uri : m_resolutionItemPosHash.keys()) {
            auto pos = m_resolutionItemPosHash.value(uri);
            if (!m_itemPosHash.contains(uri)) {
                m_resolutionItemPosHash.remove(uri);
                continue;
            }
            if (isInvalidPoint(pos)) {
                itemNeedBeRelayout.append(uri);
            } else if (!m_itemPosHash.values().contains(pos)) {
                m_resolutionItemPosHash.remove(uri);
                m_itemPosHash.insert(uri, pos);
            }
        }
        relayoutExsitingItems(itemNeedBeRelayout);
    }

    for (int row = 0; row < m_proxyModel->rowCount(); row++) {
        auto index = m_proxyModel->index(row, 0, QModelIndex());
        QString uri = index.data(UriRole).toString();
        QPoint pos = m_itemPosHash.value(uri);
        int id = index.data(ScreenIdRole).toInt();
        m_proxyModel->setData(index, pos, PositionRole);
        setFileMetaInfoPos(uri, pos);
        if (m_resolutionItemPosHash.contains(uri)) {
            QPoint reolutionItemPos = m_resolutionItemPosHash.value(uri);
            QStringList exceptedPos;
            exceptedPos<<QString::number(reolutionItemPos.x());
            exceptedPos<<QString::number(reolutionItemPos.y());
            exceptedPos<<QString::number(id);
            m_proxyModel->setData(index, exceptedPos, ExceptedPositionRole);
        }
    }
}

void PlatformWindow::relayoutExsitingItems(const QStringList &uris)
{
    if (uris.isEmpty() || m_itemPosHash.isEmpty()) {
        return;
    }
    for (auto uri : uris) {
        m_itemPosHash.remove(uri);
    }
    auto allFileUris = getAllFileUris();

    QPoint startPos = QPoint();
    int i = 0;
    for (; i < uris.count(); i++) {
        QString uri = uris[i];
        if (!allFileUris.contains(uri))
            continue;
        startPos = findNextEmptyGridPos(startPos);
        if (isInvalidPoint(startPos)) {
            break;
        }
        setFileMetaInfoPos(uri, startPos);
        m_storageBox.removeOne(uri);
    }

    for(; i < uris.count(); i++) {
        QString uri = uris[i];
        setFileMetaInfoPos(uri, QPoint(0, 0));
        if (!m_storageBox.contains(uri)) {
            m_storageBox.append(uri);
        }
    }
}

const QStringList PlatformWindow::getAllFileUris()
{
    QStringList uris;
    for (int i = 0; i < m_proxyModel->rowCount(); i++) {
        auto index = m_proxyModel->index(i, 0);
        uris<<index.data(Qt::UserRole).toString();
    }
    return uris;
}

void PlatformWindow::setFileMetaInfoPos(const QString &uri, const QPoint &pos)
{
    m_itemPosHash.insert(uri, pos);
    QPoint currentPos(pos.x()*m_gridSize.width(), pos.y()*m_gridSize.height());
    QRect rect(mapToGlobal(currentPos)*qApp->devicePixelRatio(), m_gridSize*qApp->devicePixelRatio());
    FileInfo::fromUri(uri).get()->setProperty("iconGeometry", rect);
}

QPoint PlatformWindow::findNextEmptyGridPos(const QPoint &startGridPos)
{
    for (int column = 0; column < m_availableColumnCount; column++) {
        for (int row = 0; row < m_availableRowCount; row++) {
            QPoint pos = QPoint(column, row);
            if (gridPosLesserThan(pos, startGridPos))
                continue;
            if (m_itemPosHash.keys(pos).isEmpty())
                return pos;
        }
    }
    return invalidPoint();
}

bool PlatformWindow::isInvalidPoint(const QPoint &point)
{
    return point.x() < 0 || point.x() >= m_availableColumnCount || point.y() < 0 || point.y() >= m_availableRowCount;
}

QPoint PlatformWindow::invalidPoint() const
{
    return QPoint(-1, -1);
}

QPoint PlatformWindow::getGridPosFromMousePos(const QPoint &mousePos)
{
    int x = mousePos.x()/m_gridSize.width();
//    if (layoutDirection() == Qt::RightToLeft) {
//        int vewportX = viewport()->rect().topRight().x();
//        x = (vewportX - mousePos.x())/m_gridSize.width();
//    }
    return QPoint(x, mousePos.y()/m_gridSize.height());
}

bool PlatformWindow::gridPosLesserThan(const QPoint &leftPos, const QPoint &rightPos)
{
    if (leftPos.x() < rightPos.x())
        return true;

    if (leftPos.x() > rightPos.x())
        return false;

    if (leftPos.y() < rightPos.y())
        return true;
    return false;
}

void PlatformWindow::checkItemsOver()
{
    QStringList primaryItem, extendItem;
    QStringList needRelayoutItems;
    for (int i = 0; i < m_proxyModel->rowCount(); i++) {
        QModelIndex index = m_proxyModel->index(i, 0);
        QString uri = index.data(Qt::UserRole).toString();
        QPoint pos = index.data(PositionRole).toPoint();
        auto overUris = m_itemPosHash.keys(pos);
        if (overUris.count() > 1) {
            auto extendPos = index.data(ExtendScreenPositionRole).toStringList();
            if (3 == extendPos.count() && 0 != extendPos[2].toInt()) {
                extendItem.append(uri);
            } else {
                primaryItem.append(uri);
            }
        }
    }
    primaryItem<<extendItem;
    for (auto uri : primaryItem) {
        if (needRelayoutItems.contains(uri)) {
            continue;
        }
        auto pos = m_itemPosHash.value(uri);
        auto list = m_itemPosHash.keys(pos);
        list.removeAll(uri);

        //按照model的index排序
        QStringList orderedList;
        for (auto& primaryUri : primaryItem) {
            if (list.contains(primaryUri)) {
                orderedList.append(primaryUri);
            }
        }
        needRelayoutItems << orderedList;
    }

    needRelayoutItems.removeDuplicates();
    qDebug() << "checkitemsover" <<needRelayoutItems;

    if (0 == needRelayoutItems.size()) {
        return;
    }

    relayoutExsitingItems(needRelayoutItems);

    for (int row = 0; row < m_proxyModel->rowCount(); row++) {
        auto index = m_proxyModel->index(row, 0, QModelIndex());
        auto uri = index.data(UriRole).toString();
        auto pos = m_itemPosHash.value(uri);
        m_proxyModel->setData(index, pos, PositionRole);
        setFileMetaInfoPos(uri, pos);
    }
}

bool PlatformWindow::isFull()
{
    //bug#123045 主屏桌面空间不足，新建的文件未放置到扩展屏桌面上
    qDebug() << "colNum:" <<m_availableColumnCount << "rowNum:"<< m_availableRowCount << "total:";// << m_proxy_model->rowCount();
    for (int column = 0; column < m_availableColumnCount; column++) {
        for (int row = 0; row < m_availableRowCount; row++) {
            QPoint pos = QPoint(column, row);
            if (m_itemPosHash.keys(pos).isEmpty())
                return false;
        }
    }
    return true;
}

QPoint PlatformWindow::checkGridPos(const QPoint pos)
{
    if (!isInvalidPoint(pos)) {
        return pos;
    }
    int col = pos.x() >= m_availableColumnCount ? m_availableColumnCount-1 : pos.x();
    int row = pos.y() >= m_availableRowCount ? m_availableRowCount-1 : pos.y();
    QPoint newPos = findNextEmptyGridPos(QPoint(col, row));
    return newPos;
}

void PlatformWindow::loadData()
{
    reloadData();
}

void PlatformWindow::setSortOrder(int sortOrder)
{
    m_itemPosHash.clear();
    m_autoArrange.clear();
    m_storageBox.clear();
    m_resolutionItemPosHash.clear();
    m_proxyModel->setSortOrder(sortOrder);
    m_proxyModel->sort(0, Qt::SortOrder(sortOrder));
    // 排序需要清空restore pos信息
    m_proxyModel->clearExpectedItemPosForCurrentView();
    for (int i = 0; i < m_proxyModel->rowCount(); i++) {
        auto index = m_proxyModel->index(i, 0);
        QString uri = index.data(Qt::UserRole).toString();

        int col = i/m_availableRowCount;
        int row = i%m_availableRowCount;
        if (col >= m_availableColumnCount) {
            row = 0;
            col = 0;
            m_storageBox.append(uri);
        }
        QPoint pos(col, row);
        m_proxyModel->setData(index,pos,PositionRole);
        m_autoArrange.append(uri);
        setFileMetaInfoPos(uri, pos);
    }

    Q_EMIT m_proxyModel->layoutUpdate();
}

void PlatformWindow::setSortType(int sortType)
{
    m_itemPosHash.clear();
    m_autoArrange.clear();
    m_storageBox.clear();
    m_resolutionItemPosHash.clear();
    m_proxyModel->setSortType(sortType);
    m_proxyModel->sort(1);
    m_proxyModel->sort(0, Qt::SortOrder(m_proxyModel->getSortOrder()));
    // 排序需要清空restore pos信息
    m_proxyModel->clearExpectedItemPosForCurrentView();
    for (int i = 0; i < m_proxyModel->rowCount(); i++) {
        auto index = m_proxyModel->index(i, 0);
        QString uri = index.data(Qt::UserRole).toString();
        int col = i/m_availableRowCount;
        int row = i%m_availableRowCount;
        if (col >= m_availableColumnCount) {
            row = 0;
            col = 0;
           m_storageBox.append(uri);
        }
        QPoint pos(col, row);
        m_proxyModel->setData(index,pos,PositionRole);
        m_autoArrange.append(uri);
        setFileMetaInfoPos(uri, pos);
    }
    Q_EMIT m_proxyModel->layoutUpdate();
}

void PlatformWindow::setId(int id)
{
    m_proxyModel->setId(id);
    m_proxyModel->invalidate();
}

int PlatformWindow::id()
{
    return m_proxyModel->id();
}

int PlatformWindow::dataCount() const
{
    return m_proxyModel->rowCount();
}

void PlatformWindow::invalidate()
{
    return m_proxyModel->invalidate();
}

QStringList PlatformWindow::layoutItems(bool closest)
{
    if (!closest) {
        QHash<QString, QPoint> extendMap;
        QHash<QString, QPoint> primaryItemMap;
        QList<QPair<QPoint, QString>> newPosition;
        QStringList overItem;
        for (int row = 0; row < m_proxyModel->rowCount(); row++) {
            auto index = m_proxyModel->index(row, 0, QModelIndex());
            auto uri = index.data(UriRole).toString();
            QPoint pos = index.data(PositionRole).toPoint();
            auto extendPos = index.data(ExtendScreenPositionRole).toStringList();
            if (3 == extendPos.count() && 0 != extendPos[2].toInt()) {
                extendMap.insert(uri, pos);
            } else {
                if (primaryItemMap.keys(pos).empty()) {
                    newPosition << QPair<QPoint, QString>(pos, uri);
                    primaryItemMap.insert(uri, pos);
                } else {
                    overItem.append(uri);
                }
            }
        }

        for (QString uri : extendMap.keys()) {
            QPoint pos = extendMap.value(uri);
            if (primaryItemMap.keys(pos).isEmpty()) {
                newPosition << QPair<QPoint, QString>(pos, uri);
            } else {
                overItem.append(uri);
            }
        }

        if (!newPosition.isEmpty()) {

            std::stable_sort(newPosition.begin(), newPosition.end(), iconSizeLessThan);

            QStringList sortedUris;
            for (auto pair : newPosition) {
                if (m_storageBox.contains(pair.second)) {
                    overItem.prepend(pair.second);
                } else {
                    sortedUris.append(pair.second);
                }
            }
            sortedUris << overItem;
            sortedUris.removeDuplicates();
            qDebug() <<"--------------------layoutItems" <<sortedUris;
            relayoutExsitingItemsAndUpdate(sortedUris, false);
            return sortedUris;
        }
    } else {
        qInfo()<<"not supported yet";
    }
    return QStringList();
}

void PlatformWindow::relayoutExsitingItemsAndUpdate(const QStringList uris, bool forceUpdate)
{
    if (m_availableColumnCount == 1 && m_availableRowCount == 1)
        return;
    m_itemPosHash.clear();
    m_autoArrange.clear();
    m_storageBox.clear();
    int index = 0;
    //按照行和列顺序放置uri
    for (int column = 0; column < m_availableColumnCount && index < uris.size(); column++) {
        for (int row = 0; row < m_availableRowCount && index < uris.size(); row++) {
            auto uri = uris[index];
            QPoint pos = QPoint(column, row);
            setFileMetaInfoPos(uri, pos);
            m_autoArrange.append(uri);
            index++;
        }
    }

    for (; index < uris.size(); index++) {
        //满屏暂时都放到（0，0）位置
        auto uri = uris[index];
        QPoint pos = QPoint(0, 0);
        setFileMetaInfoPos(uri, pos);
        m_autoArrange.append(uri);
        m_storageBox.append(uri);
    }

    m_autoArrange.removeDuplicates();
    if (forceUpdate)
        m_proxyModel->invalidate();
    for (int row = 0; row < m_proxyModel->rowCount(); row++) {
        auto index = m_proxyModel->index(row, 0, QModelIndex());
        auto uri = index.data(UriRole).toString();
        if(!uris.contains(uri)) {
            qDebug() << "uri does exist:" <<uri;
            continue;
        }

        auto pos = m_itemPosHash.value(uri);
        m_proxyModel->setData(index, pos, PositionRole);
    }
    qDebug() << "PlatformWindow::relayoutExsitingItemsAndUpdat---------" <<m_itemPosHash;
}

void PlatformWindow::showHiddenFile()
{
    if (GlobalSettingsAdapter::getInstance()->useAutoLayout()) {
        if (m_autoArrange.count() != m_proxyModel->rowCount()) {
            layoutItems();
        }
        return;
    }

    // 非自动布局模式下，优先保留现有位置信息
    QHash<QString, QPoint> oldItemPosHash = m_itemPosHash;
    m_itemPosHash.clear();
    m_autoArrange.clear();
    QStringList needChanged;
    // 首先处理现有的图标位置，保持它们的位置优先
    for (int row = 0; row < m_proxyModel->rowCount(); row++) {
        auto index = m_proxyModel->index(row, 0, QModelIndex());
        QString uri = index.data(UriRole).toString();
        QPoint metaPos = index.data(PositionRole).toPoint();

        if (oldItemPosHash.contains(uri)) {
            m_itemPosHash.insert(uri, metaPos);
        } else {
            //新增隐藏图标与现有图标冲突，重排隐藏图标
            if (isInvalidPoint(metaPos) || !oldItemPosHash.keys(metaPos).isEmpty() ) {
                needChanged.append(uri);
            } else {
                m_itemPosHash.remove(uri);
                setFileMetaInfoPos(uri, metaPos);
            }
        }
    }
    qInfo()<<"need changed item"<<needChanged;
    relayoutExsitingItems(needChanged);

    for (auto uri : needChanged) {
        if (uri.isEmpty())
            continue;
        QModelIndex index = m_model->indexFromUri(uri);
        QPoint pos = m_itemPosHash.value(uri);
        m_model->setData(index, pos, PositionRole);
    }
    return;
}

void PlatformWindow::showStandardFile()
{
    if (GlobalSettingsAdapter::getInstance()->useAutoLayout()) {
        if (m_autoArrange.count() != m_proxyModel->rowCount()) {
            layoutItems();
            return;
        }
        return;
    }
    ajustIconsOnScreenSize();
    checkItemsOver();
    return;
}

bool PlatformWindow::fileRemoved(const QString &uri)
{
    qDebug() << "file removed"<<uri;
    bool isExist = m_autoArrange.contains(uri)? true : false;
    QPoint emptyPos = m_itemPosHash.value(uri);
    m_itemPosHash.remove(uri);
    m_resolutionItemPosHash.remove(uri);
    m_autoArrange.removeOne(uri);
    bool inBox = m_storageBox.removeOne(uri);

    if (GlobalSettingsAdapter::getInstance()->useAutoLayout() && isExist) {
        relayoutExsitingItemsAndUpdate(m_autoArrange, false);
        return true;
    }
    //重叠的重新分位置
    if (m_storageBox.isEmpty())
        return false;
    if (inBox)
        return true;

    QString relayoutUri =  m_storageBox.takeLast();
    if (!m_itemPosHash.contains(relayoutUri)) {
        return false;
    }
    QModelIndex index = m_model->indexFromUri(relayoutUri);
    m_model->setData(index, emptyPos, PositionRole);
    setFileMetaInfoPos(relayoutUri, emptyPos);
    return true;
}

bool PlatformWindow::filesRemoved(const QStringList &uris)
{
    qDebug() << "files removed"<<uris;
    bool isExist = false;
    QList<QPoint> emptyPosList;
    for (QString uri : uris) {
        isExist = m_autoArrange.contains(uri)? true : isExist;
        bool inBox = m_storageBox.removeOne(uri);
        if (!inBox) {
            QPoint pos = m_itemPosHash.value(uri);
            emptyPosList.append(pos);
        }
        m_itemPosHash.remove(uri);
        m_resolutionItemPosHash.remove(uri);
        m_autoArrange.removeOne(uri);
    }

    if (GlobalSettingsAdapter::getInstance()->useAutoLayout() && isExist) {
        relayoutExsitingItemsAndUpdate(m_autoArrange, false);
        return isExist;
    }

    for (QPoint emptyPos : emptyPosList) {
        //重叠的重新分位置
        if (m_storageBox.isEmpty())
            return true;

        QString relayoutUri =  m_storageBox.takeLast();
        if (!m_itemPosHash.contains(relayoutUri)) {
            return false;
        }
        QModelIndex index = m_model->indexFromUri(relayoutUri);
        m_model->setData(index, emptyPos, PositionRole);
        setFileMetaInfoPos(relayoutUri, emptyPos);
    }
    return isExist;
}

bool PlatformWindow::idChanged(int id, int oldId, const QStringList &uris)
{
    qDebug()<<"file created "<< id << " uri:" <<uris<<" current id" <<m_proxyModel->id()<<oldId;
    if (oldId != id && oldId == m_proxyModel->id()) {
        if (-1 == id ) {
            //移除oldId的屏幕，更新oldId的图标缓存
            m_proxyModel->invalidate();
            filesRemoved(uris);
            return true;
        }
    }
    if (id != m_proxyModel->id() || uris.isEmpty()) {
        return false;
    }
//    m_proxyModel->invalidate();
    bool forceUpdate = oldId != id ? true : false;
    for (auto uri : uris) {
        if (uri.isEmpty())
            continue;
    auto index = m_model->indexFromUri(uri);
    QPoint metaPos = m_model->data(index,PositionRole).toPoint();
    if (GlobalSettingsAdapter::getInstance()->useAutoLayout()) {
        if (!m_autoArrange.contains(uri)) {
            //自动排序下重命名导致出现重叠现象
            if (isInvalidPoint(metaPos)) {
                m_autoArrange.append(uri);
            } else {
                int i = metaPos.x() * m_availableRowCount +  metaPos.y();
                m_autoArrange.insert(i, uri);
            }
            relayoutExsitingItemsAndUpdate(m_autoArrange, forceUpdate);
            return true;
        }
        return false;
    }

    if (isInvalidPoint(metaPos) || !m_itemPosHash.keys(metaPos).isEmpty() ) {
        QPoint emptypos = findNextEmptyGridPos();
        if (emptypos.x() < 0) {
            qWarning()<<"no empty pos";
            //如果没有空位则后面的item不排序
            emptypos = QPoint(0, 0);
            if (!m_storageBox.contains(uri))
                m_storageBox.append(uri);
        }
        metaPos = emptypos;
        m_model->setData(index, metaPos, PositionRole);
        setFileMetaInfoPos(uri, metaPos);
    } else {
        m_itemPosHash.remove(uri);
        setFileMetaInfoPos(uri, metaPos);
    }
    m_model->setData(index, m_proxyModel->id(), ScreenIdRole);
    }
    if (forceUpdate)
        m_proxyModel->invalidate();
    return true;
}

void PlatformWindow::drop(const QStringList &selectedUris, Qt::DropAction action, int insertRow, const QPoint &offPos)
{
    bool isExist = getAllFileUris().contains(selectedUris.first());
    if (isExist) {
        if (GlobalSettingsAdapter::getInstance()->useAutoLayout()) {
            if (m_autoArrange.empty()) {
                qCritical()<<"sort list is empty"<<m_autoArrange<<"selected uris:"<<selectedUris;
                layoutItems();
                return;
            }
            QStringList destSortedUris = m_autoArrange;
            QStringList draggedUris;
            for (int i = 0; i < destSortedUris.count(); i++) {
                draggedUris.append(QString());
            }
            qDebug()<<"current uris:"<<m_autoArrange<<"selected uris:"<<selectedUris;
            for (QString uri : selectedUris) {
                int pos = destSortedUris.indexOf(uri);
                if (-1 == pos) {
                    qCritical()<<"get position of uri is -1:"<<m_autoArrange<<"currrent selected uri:"<<uri;
                    continue;
                }
                destSortedUris.replace(pos, QString());
                draggedUris.replace(pos, uri);
            }

            draggedUris.removeAll(QString());

            if (-1 == insertRow) {
                destSortedUris += draggedUris;
            } else {
                auto index = m_proxyModel->index(insertRow, 0, QModelIndex());
                QString currentHoverUri = index.data(UriRole).toString();
                int insertedPos = destSortedUris.indexOf(currentHoverUri);
                qDebug()<<"insert pos: "<<insertedPos<<currentHoverUri;
                if (insertedPos >= 0 && insertedPos <= destSortedUris.size()) {
                    destSortedUris.reserve(destSortedUris.size() + draggedUris.size());
                    for (const QString &uri : draggedUris) {
                        destSortedUris.insert(insertedPos++, uri);
                    }
                } else if (insertedPos < 0){
                    destSortedUris = m_autoArrange;
                } else {
                    destSortedUris += draggedUris;
                }
            }

            destSortedUris.removeAll(QString());
            destSortedUris.removeDuplicates();
            qDebug()<<"relayout: "<<destSortedUris;

            relayoutExsitingItemsAndUpdate(destSortedUris, false);
        } else {
            qDebug() << "非自动排序 拖拽:" <<selectedUris<< " 行为："<<action<<"插入行:"<<insertRow<<"偏移量："<<offPos;
            for (QString uri : selectedUris) {
                m_itemPosHash.remove(uri);
            }
            QHash<QString, QModelIndex> relayoutIndexes;
            for (int row = 0; row < m_proxyModel->rowCount(); row++) {
                auto index = m_proxyModel->index(row, 0, QModelIndex());
                QString uri = index.data(UriRole).toString();
                if (selectedUris.contains(uri)) {
                    QPoint pos = index.data(PositionRole).toPoint();
                    if (!isInvalidPoint(pos)) {
                        qDebug() << " 拖拽:" <<uri<< " 拖拽前坐标："<<pos;
                        pos += offPos;
                        qDebug() << " 拖拽后坐标："<<pos;
                        if (isInvalidPoint(pos) || !m_itemPosHash.keys(pos).isEmpty()) {
                            relayoutIndexes.insert(uri, index);
                            continue;
                        }
                    } else {
                        relayoutIndexes.insert(uri, index);
                        continue;
                    }
                    setFileMetaInfoPos(uri, pos);
                    m_proxyModel->setData(index, pos, PositionRole);
                }
            }
            for (QString uri : relayoutIndexes.keys()) {
                auto index = relayoutIndexes.value(uri);
                QPoint dropedGridPos = index.data(PositionRole).toPoint();
                if (!isInvalidPoint(dropedGridPos) && m_itemPosHash.keys(dropedGridPos+offPos).isEmpty()) {
                    dropedGridPos += offPos;
                }
                QPoint pos = findNextEmptyGridPos(dropedGridPos);
                if (!isInvalidPoint(pos)) {
                    setFileMetaInfoPos(uri, pos);
                    m_proxyModel->setData(index, pos, PositionRole);
                }
            }
        }

    } else {
        dragFromOtherScreen(selectedUris, insertRow, offPos);
    }

}

bool PlatformWindow::dragFromOtherScreen(QStringList selectedUris, int insertRow, const QPoint &offPos)
{
    int oldId = 0;
    if (GlobalSettingsAdapter::getInstance()->useAutoLayout()) {
        qDebug() << "跨屏 自动排序 拖拽:" <<selectedUris<<"插入行:"<<insertRow<<"偏移量："<<offPos;

        for (int row = 0; row < m_model->rowCount(); row++) {
            auto index = m_model->index(row, 0, QModelIndex());
            QString uri = index.data(UriRole).toString();
            if (selectedUris.contains(uri)) {
                oldId = m_model->data(index, ScreenIdRole).toInt();
                m_model->setData(index, m_proxyModel->id(), ScreenIdRole);
            }
        }
        QStringList destSortedUris = m_autoArrange;
        if (-1 == insertRow) {
            destSortedUris.append(selectedUris);
        } else {
            auto index = m_proxyModel->index(insertRow, 0, QModelIndex());
            QString currentHoverUri = index.data(UriRole).toString();
            int insertedPos = destSortedUris.indexOf(currentHoverUri);
            qDebug()<<"insert pos: "<<insertedPos<<currentHoverUri;
            if (insertedPos >= 0 && insertedPos <= destSortedUris.size()) {
                destSortedUris.reserve(destSortedUris.size() + selectedUris.size());
                for (const QString &uri : selectedUris) {
                    destSortedUris.insert(insertedPos++, uri);
                }
            }
        }
        destSortedUris.removeDuplicates();
        relayoutExsitingItemsAndUpdate(destSortedUris);
        Q_EMIT m_model->idChanged(-1, oldId, selectedUris);
        return true;
    } else {
        qDebug() << "跨屏 非自动排序 拖拽:" <<selectedUris<<"插入行:"<<insertRow<<"偏移量："<<offPos;

        QHash<QString, QModelIndex> relayoutIndexes;
        for (int row = 0; row < m_model->rowCount(); row++) {
            auto index = m_model->index(row, 0, QModelIndex());
            QString uri = index.data(UriRole).toString();
            if (selectedUris.contains(uri)) {
                oldId = m_model->data(index, ScreenIdRole).toInt();
                QPoint pos = index.data(PositionRole).toPoint();
                qDebug() << " 拖拽:" <<uri<< " 拖拽前坐标："<<pos;
                pos += offPos;
                qDebug() << " 拖拽后坐标："<<pos;
                if (isInvalidPoint(pos) || !m_itemPosHash.keys(pos).isEmpty()) {
                    relayoutIndexes.insert(uri, index);
                    continue;
                }
                setFileMetaInfoPos(uri, pos);
                m_model->setData(index, pos, PositionRole);
                m_model->setData(index, m_proxyModel->id(), ScreenIdRole);
            }
        }
        for (QString uri : relayoutIndexes.keys()) {
            auto index = relayoutIndexes.value(uri);
            QPoint dropedGridPos = index.data(PositionRole).toPoint();
            qDebug() <<"重排当前文件："<<uri<< " 重排当前坐标："<<dropedGridPos;
            dropedGridPos += offPos;
            qDebug() <<" 重排后坐标："<<dropedGridPos;
            QPoint pos = findNextEmptyGridPos(dropedGridPos);
            if (!isInvalidPoint(pos)) {
                setFileMetaInfoPos(uri, pos);
                m_model->setData(index, pos, PositionRole);
                m_model->setData(index, m_proxyModel->id(), ScreenIdRole);
            }
        }
        m_proxyModel->invalidate();
        Q_EMIT m_model->idChanged(-1, oldId, selectedUris);
        return true;
    }
    return false;
}

void PlatformWindow::reloadData()
{
    m_itemPosHash.clear();
    m_autoArrange.clear();
    m_storageBox.clear();
    if (GlobalSettingsAdapter::getInstance()->useAutoLayout()) {
        layoutItems();
        return ;
    }
    for (int row = 0; row < m_proxyModel->rowCount(); row++) {
        auto index = m_proxyModel->index(row, 0, QModelIndex());
        QString uri = index.data(UriRole).toString();
        QPoint pos = index.data(PositionRole).toPoint();
        setFileMetaInfoPos(uri, pos);
    }
    checkItemsOver();
}

bool PlatformWindow::checkEmptyPositon()
{
    if (m_autoArrange.isEmpty())
        return false;
    for (int col = 0; col < m_availableColumnCount; col++) {
        for (int row = 0; row < m_availableRowCount; row++) {
            if (col * m_availableRowCount + row + 1 > m_autoArrange.count()) {
                return false;
            }
            if (m_itemPosHash.keys(QPoint(col, row)).isEmpty()) {
                return true;
            }
        }
    }

    return false;
}
