#include <QGuiApplication>
#include <QtTest>

#include "shadowed-texture.h"
#include "scenegraph/shadowed-rectangle-node.h"
#include "scenegraph/shadowed-texture-node.h"

namespace {

class FakeTextureProvider : public QSGTextureProvider
{
public:
    QSGTexture *texture() const override
    {
        return nullptr;
    }
};

class FakeTextureItem : public QQuickItem
{
public:
    bool isTextureProvider() const override
    {
        return true;
    }

    QSGTextureProvider *textureProvider() const override
    {
        return const_cast<FakeTextureProvider *>(&provider);
    }

    mutable FakeTextureProvider provider;
};

class TestableShadowedTexture : public ShadowedTexture
{
public:
    using ShadowedTexture::ShadowedTexture;
    using ShadowedTexture::updatePaintNode;
};

}

class shadowed_texture_test : public QObject
{
    Q_OBJECT

private slots:
    void sourceSetterParentsAndSignals();
    void updatePaintNodeCreatesExpectedNodeTypes();
};

void shadowed_texture_test::sourceSetterParentsAndSignals()
{
    TestableShadowedTexture item;
    FakeTextureItem source;
    QSignalSpy sourceSpy(&item, &ShadowedTexture::sourceChanged);

    QVERIFY(item.source() == nullptr);

    item.setSource(nullptr);
    QCOMPARE(sourceSpy.count(), 0);

    item.setSource(&source);
    QCOMPARE(item.source(), static_cast<QQuickItem *>(&source));
    QCOMPARE(source.parentItem(), static_cast<QQuickItem *>(&item));
    QCOMPARE(sourceSpy.count(), 1);

    item.setSource(&source);
    QCOMPARE(sourceSpy.count(), 1);

    item.setSource(nullptr);
    QVERIFY(item.source() == nullptr);
    QCOMPARE(sourceSpy.count(), 2);
}

void shadowed_texture_test::updatePaintNodeCreatesExpectedNodeTypes()
{
    TestableShadowedTexture item;
    FakeTextureItem source;

    item.setWidth(60);
    item.setHeight(30);
    item.shadow()->setSize(8.0);
    item.shadow()->setYOffset(2.0);
    item.border()->setWidth(1.0);

    QSGNode *node = item.updatePaintNode(nullptr, nullptr);
    QVERIFY(dynamic_cast<ShadowedRectangleNode *>(node) != nullptr);
    QVERIFY(dynamic_cast<ShadowedTextureNode *>(node) == nullptr);

    item.setSource(&source);
    node = item.updatePaintNode(node, nullptr);
    QVERIFY(dynamic_cast<ShadowedTextureNode *>(node) != nullptr);

    QSGNode *sameNode = item.updatePaintNode(node, nullptr);
    QCOMPARE(sameNode, node);

    delete sameNode;
}

int main(int argc, char *argv[])
{
    qputenv("QT_QPA_PLATFORM", "offscreen");
    qputenv("QT_QPA_PLATFORMTHEME", "generic");
    qputenv("QT_FATAL_WARNINGS", "0");
    qputenv("QT_LOGGING_RULES", "qt.qpa.*=false");

    QGuiApplication app(argc, argv);
    shadowed_texture_test testCase;
    return QTest::qExec(&testCase, argc, argv);
}

#include "test-shadowed-texture.moc"
