#include "MegaDelegateHoverManager.h"

#include <QMouseEvent>
#include <QChildEvent>
#include <QApplication>

MegaDelegateHoverManager::MegaDelegateHoverManager() : mView(nullptr)
{}

void MegaDelegateHoverManager::setView(QAbstractItemView *view)
{
    if(mView)
    {
        mView->viewport()->removeEventFilter(this);
    }

    mView = view;
    mView->setMouseTracking(true);
    mView->viewport()->installEventFilter(this);
}

bool MegaDelegateHoverManager::eventFilter(QObject *watched, QEvent *event)
{
    if (event)
    {
        if(auto mouseEvent = dynamic_cast<QMouseEvent*>(event))
        {
            auto index = mView->indexAt(mouseEvent->pos());

            if(mCurrentIndex.row() != index.row()
                    || mCurrentIndex.parent() != index.parent())
            {
                sendEvent(MegaDelegateHoverEvent::Leave);
                mCurrentIndex = index;
                sendEvent(MegaDelegateHoverEvent::Enter);
            }

            sendEvent(MegaDelegateHoverEvent::MouseMove, mouseEvent->pos());
        }
        else
        {
            if(event->type() == QEvent::Enter)
            {
                if(auto enterEvent = dynamic_cast<QEnterEvent*>(event))
                {
                    mCurrentIndex = mView->indexAt(enterEvent->pos());
                    sendEvent(MegaDelegateHoverEvent::Enter);
                }
            }
            else if(event->type() == QEvent::Leave || event->type() == QEvent::Wheel)
            {
                sendEvent(MegaDelegateHoverEvent::Leave);
                mCurrentIndex = QModelIndex();
            }
            else if(event->type() == QEvent::ChildAdded)
            {
                if(auto childEvent = dynamic_cast<QChildEvent*>(event))
                {
                    if(auto editor = dynamic_cast<QWidget*>(childEvent->child()))
                    {
                        editor->setMouseTracking(true);
                    }
                }
            }
        }
    }
    return QObject::eventFilter(watched, event);
}

void MegaDelegateHoverManager::sendEvent(QEvent::Type eventType, const QPoint& point)
{
    if(mCurrentIndex.row() >= 0)
    {
        auto delegate = mView->itemDelegateForColumn(mCurrentIndex.column());
        if(!delegate)
        {
            delegate = mView->itemDelegate();
        }

        if(delegate)
        {
            auto hoverEvent = new MegaDelegateHoverEvent(eventType);
            hoverEvent->setIndex(mCurrentIndex);
            hoverEvent->setRect(mView->visualRect(mCurrentIndex));
            if (!point.isNull())
            {
                hoverEvent->setMousePos(point - hoverEvent->rect().topLeft());
            }

            QApplication::postEvent(delegate, hoverEvent);
        }
    }
}
