// SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
// SPDX-FileCopyrightText: 2024 Arjen Hiemstra <ahiemstra@heimr.nl>
//
// This file is automatically generated from autotest.cpp.j2.
// To regenerate, run `tools/propertygenerator/generate_properties.py`.

#include <QtTest>

#include <properties/ShadowProperty.h>

#include "CreateTestInstances.h"

using namespace Union::Properties;
using namespace Qt::StringLiterals;

class TestShadowProperty : public QObject
{
    Q_OBJECT
private Q_SLOTS:
    void testNull()
    {
        auto property = std::make_unique<ShadowProperty>();

        // A null instance should not have any values for its properties.
        QVERIFY(!property->offset());
        QVERIFY(!property->color().has_value());
        QVERIFY(!property->size().has_value());
        QVERIFY(!property->blur().has_value());
        QVERIFY(!property->left());
        QVERIFY(!property->right());
        QVERIFY(!property->top());
        QVERIFY(!property->bottom());
        QVERIFY(!property->topLeft());
        QVERIFY(!property->topRight());
        QVERIFY(!property->bottomLeft());
        QVERIFY(!property->bottomRight());
    }

    void testEmpty()
    {
        auto property = ShadowProperty::empty();

        // An empty instance should only have values that are considered "empty".
        QCOMPARE(*property->offset(), *OffsetProperty::empty());
        QCOMPARE(property->color().value(), emptyValue<Union::Color>());
        QCOMPARE(property->size().value(), emptyValue<qreal>());
        QCOMPARE(property->blur().value(), emptyValue<qreal>());
        QCOMPARE(*property->left(), *LineProperty::empty());
        QCOMPARE(*property->right(), *LineProperty::empty());
        QCOMPARE(*property->top(), *LineProperty::empty());
        QCOMPARE(*property->bottom(), *LineProperty::empty());
        QCOMPARE(*property->topLeft(), *CornerProperty::empty());
        QCOMPARE(*property->topRight(), *CornerProperty::empty());
        QCOMPARE(*property->bottomLeft(), *CornerProperty::empty());
        QCOMPARE(*property->bottomRight(), *CornerProperty::empty());
    }

    void testHasAnyValue()
    {
        auto property = std::make_unique<ShadowProperty>();

        // An empty instance should not have any values for its properties.
        QVERIFY(!property->hasAnyValue());

        {
            // Assigning an empty value to a property should have no effect.
            property->setOffset(std::make_unique<OffsetProperty>());
            QVERIFY(!property->hasAnyValue());

            property->setOffset(testOffsetPropertyInstance());
            QVERIFY(property->hasAnyValue());

            property->setOffset(nullptr);
            QVERIFY(!property->hasAnyValue());
        }
        {
            Union::Color value;
            property->setColor(value);
            QVERIFY(property->hasAnyValue());
            property->setColor(std::nullopt);
            QVERIFY(!property->hasAnyValue());
        }
        {
            qreal value;
            property->setSize(value);
            QVERIFY(property->hasAnyValue());
            property->setSize(std::nullopt);
            QVERIFY(!property->hasAnyValue());
        }
        {
            qreal value;
            property->setBlur(value);
            QVERIFY(property->hasAnyValue());
            property->setBlur(std::nullopt);
            QVERIFY(!property->hasAnyValue());
        }
        {
            // Assigning an empty value to a property should have no effect.
            property->setLeft(std::make_unique<LineProperty>());
            QVERIFY(!property->hasAnyValue());

            property->setLeft(testLinePropertyInstance());
            QVERIFY(property->hasAnyValue());

            property->setLeft(nullptr);
            QVERIFY(!property->hasAnyValue());
        }
        {
            // Assigning an empty value to a property should have no effect.
            property->setRight(std::make_unique<LineProperty>());
            QVERIFY(!property->hasAnyValue());

            property->setRight(testLinePropertyInstance());
            QVERIFY(property->hasAnyValue());

            property->setRight(nullptr);
            QVERIFY(!property->hasAnyValue());
        }
        {
            // Assigning an empty value to a property should have no effect.
            property->setTop(std::make_unique<LineProperty>());
            QVERIFY(!property->hasAnyValue());

            property->setTop(testLinePropertyInstance());
            QVERIFY(property->hasAnyValue());

            property->setTop(nullptr);
            QVERIFY(!property->hasAnyValue());
        }
        {
            // Assigning an empty value to a property should have no effect.
            property->setBottom(std::make_unique<LineProperty>());
            QVERIFY(!property->hasAnyValue());

            property->setBottom(testLinePropertyInstance());
            QVERIFY(property->hasAnyValue());

            property->setBottom(nullptr);
            QVERIFY(!property->hasAnyValue());
        }
        {
            // Assigning an empty value to a property should have no effect.
            property->setTopLeft(std::make_unique<CornerProperty>());
            QVERIFY(!property->hasAnyValue());

            property->setTopLeft(testCornerPropertyInstance());
            QVERIFY(property->hasAnyValue());

            property->setTopLeft(nullptr);
            QVERIFY(!property->hasAnyValue());
        }
        {
            // Assigning an empty value to a property should have no effect.
            property->setTopRight(std::make_unique<CornerProperty>());
            QVERIFY(!property->hasAnyValue());

            property->setTopRight(testCornerPropertyInstance());
            QVERIFY(property->hasAnyValue());

            property->setTopRight(nullptr);
            QVERIFY(!property->hasAnyValue());
        }
        {
            // Assigning an empty value to a property should have no effect.
            property->setBottomLeft(std::make_unique<CornerProperty>());
            QVERIFY(!property->hasAnyValue());

            property->setBottomLeft(testCornerPropertyInstance());
            QVERIFY(property->hasAnyValue());

            property->setBottomLeft(nullptr);
            QVERIFY(!property->hasAnyValue());
        }
        {
            // Assigning an empty value to a property should have no effect.
            property->setBottomRight(std::make_unique<CornerProperty>());
            QVERIFY(!property->hasAnyValue());

            property->setBottomRight(testCornerPropertyInstance());
            QVERIFY(property->hasAnyValue());

            property->setBottomRight(nullptr);
            QVERIFY(!property->hasAnyValue());
        }
    }

    void testResolveProperties()
    {
        auto source = std::make_unique<ShadowProperty>();
        auto destination = std::make_unique<ShadowProperty>();

        QVERIFY(!source->hasAnyValue());
        QVERIFY(!destination->hasAnyValue());

        // Calling resolve on empty source and destination should have no effect.
        ShadowProperty::resolveProperties(source.get(), destination.get());

        QVERIFY(!destination->hasAnyValue());

        source->setOffset(testOffsetPropertyInstance());
        source->setColor(Union::Color{});
        source->setSize(qreal{});
        source->setBlur(qreal{});
        source->setLeft(testLinePropertyInstance());
        source->setRight(testLinePropertyInstance());
        source->setTop(testLinePropertyInstance());
        source->setBottom(testLinePropertyInstance());
        source->setTopLeft(testCornerPropertyInstance());
        source->setTopRight(testCornerPropertyInstance());
        source->setBottomLeft(testCornerPropertyInstance());
        source->setBottomRight(testCornerPropertyInstance());

        QVERIFY(source->hasAnyValue());
        QVERIFY(!destination->hasAnyValue());

        ShadowProperty::resolveProperties(source.get(), destination.get());

        QVERIFY(destination->hasAnyValue());

        QCOMPARE(*destination->offset(), *source->offset());
        QCOMPARE(destination->color(), source->color());
        QCOMPARE(destination->size(), source->size());
        QCOMPARE(destination->blur(), source->blur());
        QCOMPARE(*destination->left(), *source->left());
        QCOMPARE(*destination->right(), *source->right());
        QCOMPARE(*destination->top(), *source->top());
        QCOMPARE(*destination->bottom(), *source->bottom());
        QCOMPARE(*destination->topLeft(), *source->topLeft());
        QCOMPARE(*destination->topRight(), *source->topRight());
        QCOMPARE(*destination->bottomLeft(), *source->bottomLeft());
        QCOMPARE(*destination->bottomRight(), *source->bottomRight());
    }

    void testDataStream()
    {
        auto group = testShadowPropertyInstance();

        QByteArray data;
        QDataStream writeStream(&data, QIODevice::WriteOnly);
        writeStream << group.get();

        QCOMPARE(writeStream.status(), QDataStream::Status::Ok);
        QVERIFY(data.size() > 0);

        QDataStream readStream(data);
        auto readGroup = std::make_unique<ShadowProperty>();
        readStream >> readGroup;

        QCOMPARE(readStream.status(), QDataStream::Status::Ok);
        QCOMPARE(*readGroup, *group);
    }
};

QTEST_MAIN(TestShadowProperty)

#include "TestShadowProperty.moc"