#include "pluginitem.h"
#include <QWindow>
#include <QSGNinePatchNode>
#include <QQuickWindow>
#include <QDebug>
#include <QPushButton>
#include <QTimer>
#include <QBitmap>
#include "qwidgetpluginmanager.h"

PluginItem::PluginItem(QQuickItem *parent)
    : QQuickItem(parent),
      m_widgetVisible(true),
      m_index(0)
{
    setFlag(QQuickItem::ItemHasContents, true);
    setAcceptedMouseButtons(Qt::AllButtons);
    connect(this, &PluginItem::xChanged, [this] {
        auto pos = parentItem()->mapToItem(m_mapItem, QPointF(x(), y()));
        m_widgetImage = QImage();
        polish();
        pluginMgr.movePlugin(m_pluginName, pos.x(), pos.y());
        pluginMgr.showPlugin(m_pluginName);
    });
}

PluginItem::~PluginItem()
{
}

bool PluginItem::widgetVisible() const
{
    return m_widgetVisible;
}

QQuickItem *PluginItem::mapItem() const
{
    return m_mapItem;
}

QQuickWindow *PluginItem::rootWindow() const
{
    return m_rootWindow;
}

int PluginItem::index() const
{
    return m_index;
}

QString PluginItem::pluginName() const
{
    return m_pluginName;
}

void PluginItem::setWidgetVisible(bool widgetVisible)
{
    if (!pluginMgr.containsPlugin(m_pluginName)) {
        return;
    }

    if (m_widgetVisible != widgetVisible) {
        m_widgetVisible = widgetVisible;
        if (widgetVisible) {
            auto pos = parentItem()->mapToItem(m_mapItem, QPointF(x(), y()));
            polish();
            pluginMgr.movePlugin(m_pluginName, pos.x(), pos.y());
            pluginMgr.showPlugin(m_pluginName);
        } else {
            polish();
            pluginMgr.hidePlugin(m_pluginName);
        }
        Q_EMIT widgetVisibleChanged();
    }
}

void PluginItem::setMapItem(QQuickItem *item)
{
    if (m_mapItem != item) {
        m_mapItem = item;
        Q_EMIT mapItemChanged();
    }
}

void PluginItem::setIndex(int index)
{
    if (m_index != index) {
        m_index = index;
        Q_EMIT indexChanged();
    }
}

void PluginItem::setPluginName(const QString &pluginName)
{
    if (m_pluginName != pluginName) {
        m_pluginName = pluginName;
        Q_EMIT pluginNameChanged();
    }
}

void PluginItem::setRootWindow(QQuickWindow *rootWindow)
{
    m_rootWindow = rootWindow;

    pluginMgr.createPlugin(m_pluginName, this->width(), this->height());
    pluginMgr.plugin(m_pluginName)->setFixedSize(this->width(), this->height());
    pluginMgr.setPluginRootWindow(m_pluginName, rootWindow);
    if (m_widgetVisible && m_mapItem) {
        auto pos = parentItem()->mapToItem(m_mapItem, QPointF(x(), y()));
        polish();
        pluginMgr.movePlugin(m_pluginName, pos.x(), pos.y());
        pluginMgr.showPlugin(m_pluginName);
    }
}

void PluginItem::updatePolish()
{
    if (!pluginMgr.containsPlugin(m_pluginName)) {
        return;
    }

    QPixmap pixmap = pluginMgr.plugin(m_pluginName)->plugin()->grab();
    m_widgetImage = pixmap.toImage();
    QQuickItem::update();
}

QSGNode *PluginItem::updatePaintNode(QSGNode *node, UpdatePaintNodeData *)
{
    if (m_widgetImage.isNull()) {
        delete node;
        return nullptr;
    }

    QSGNinePatchNode *styleNode = static_cast<QSGNinePatchNode *>(node);
    if (!styleNode) {
        styleNode = window()->createNinePatchNode();
    }

    styleNode->setTexture(window()->createTextureFromImage(m_widgetImage, QQuickWindow::TextureHasAlphaChannel));
    styleNode->setBounds(boundingRect());
    styleNode->setDevicePixelRatio(window()->devicePixelRatio());
    styleNode->update();

    return styleNode;
}
