// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later

#include <QScrollBar>
#include <QToolButton>
#include <QHBoxLayout>
#include "wallpaperlist.h"
#include "private/wallpapersettings_p.h"
#include "desktoputils/ddpugin_eventinterface_helper.h"

#include <dfm-base/dfm_desktop_defines.h>
#include <dfm-framework/dpf.h>
#include <QTimer>
#include <QWidget>

#include "stubext.h"
#include <gtest/gtest.h>

DFMBASE_USE_NAMESPACE
DPF_USE_NAMESPACE
DDP_WALLPAERSETTING_USE_NAMESPACE
DWIDGET_USE_NAMESPACE

TEST(WallpaperList, init)
{
    stub_ext::StubExt stub;
    bool connect1 = false;
    bool connect2 = false;
    bool connect3 = false;
    bool connect4 = false;
    stub.set_lamda(&WallpaperList::updateItemThumb, [&connect1]() {
        connect1 = true;
    });
    auto startFunc = static_cast<void (QTimer::*)()>(&QTimer::start);
    stub.set_lamda(startFunc, [&connect2]() {
        connect2 = true;
    });
    stub.set_lamda(&WallpaperList::prevPage, [&connect3]() {
        connect3 = true;
    });
    stub.set_lamda(&WallpaperList::nextPage, [&connect4]() {
        connect4 = true;
    });

    WallpaperList *list;
    EXPECT_NO_FATAL_FAILURE(list = new WallpaperList);
    emit list->updateTimer->timeout(QTimer::QPrivateSignal());
    emit list->scrollAnimation.finished();
    emit list->prevButton.widget()->clicked();
    emit list->nextButton.widget()->clicked();

    EXPECT_TRUE(connect1);
    EXPECT_TRUE(connect2);
    EXPECT_TRUE(connect3);
    EXPECT_TRUE(connect4);
}

class UT_wallpaperList : public testing::Test
{
protected:
    virtual void SetUp() override
    {
        list = new WallpaperList;
    }
    virtual void TearDown() override
    {
        delete list;
        stub.clear();
    }
    WallpaperList *list = nullptr;
    stub_ext::StubExt stub;
};

TEST_F(UT_wallpaperList, MaskWidget)
{
    QWidget *maskWidget = new QWidget;
    list->setMaskWidget(maskWidget);
    EXPECT_EQ(list->widget(), maskWidget);
    list->removeMaskWidget();
    EXPECT_NE(list->widget(), maskWidget);
    EXPECT_EQ(list->widget(), list->contentWidget);
    delete maskWidget;
}

TEST_F(UT_wallpaperList, Item)
{
    QStringList itemDataList;

    bool connect1 = false;
    bool connect2 = false;
    bool connect3 = false;
    stub.set_lamda(&WallpaperList::onItemPressed, [&connect1]() {
        connect1 = true;
    });
    stub.set_lamda(&WallpaperList::onItemHoverIn, [&connect2]() {
        connect2 = true;
    });
    stub.set_lamda(&WallpaperList::onItemHoverOut, [&connect3]() {
        connect3 = true;
    });

    itemDataList << "test1"
                 << "test2"
                 << "test3";
    for (auto itemData : itemDataList)
        list->addItem(itemData);

    EXPECT_EQ(list->items.size(), 3);
    WallpaperItem *item = new WallpaperItem;
    emit list->items.at(0)->pressed(item);
    emit list->items.at(0)->hoverIn(item);
    emit list->items.at(0)->hoverOut(item);
    EXPECT_TRUE(connect1);
    EXPECT_TRUE(connect2);
    EXPECT_TRUE(connect3);

    list->removeItem("test2");
    EXPECT_EQ(list->items.size(), 2);
    for (auto item : list->items)
        EXPECT_NE(item->itemData(), "test2");
    delete item;
}

TEST_F(UT_wallpaperList, keypressEvent)
{
    auto now = list->currentIndex;
    QKeyEvent *mouseEvent = new QKeyEvent(QEvent::Type::KeyPress, 0, Qt::KeyboardModifier::AltModifier);
    mouseEvent->k = Qt::Key_Right;
    int ret = now;
    stub.set_lamda(&WallpaperList::setCurrentIndex, [&ret](WallpaperList *self, int index) {
        __DBG_STUB_INVOKE__
        Q_UNUSED(self);
        ret = index;
        return;
    });
    list->keyPressEvent(mouseEvent);
    EXPECT_EQ(now, ret - 1);

    mouseEvent->k = Qt::Key_Left;
    list->keyPressEvent(mouseEvent);
    EXPECT_EQ(now, ret + 1);

    ret = now;
    mouseEvent->k = Qt::Key_1;
    list->keyPressEvent(mouseEvent);
    EXPECT_EQ(now, ret);
    delete mouseEvent;
}

TEST_F(UT_wallpaperList, gridSize)
{
    list->grid = QSize(10, 10);
    bool call = false;
    stub.set_lamda(&QWidget::adjustSize, [&call]() {
        call = true;
        return;
    });
    list->setGridSize(QSize(20, 20));
    EXPECT_EQ(list->gridSize(), QSize(20, 20));
    EXPECT_TRUE(call);
    call = false;

    list->setGridSize(QSize(20, 20));
    EXPECT_EQ(list->gridSize(), QSize(20, 20));
    EXPECT_FALSE(call);
}

TEST_F(UT_wallpaperList, clear)
{
    WallpaperItem *item1 = new WallpaperItem;
    WallpaperItem *item2 = new WallpaperItem;
    WallpaperItem *item3 = new WallpaperItem;
    list->items.append(item1);
    list->items.append(item2);
    list->items.append(item3);
    list->contentLayout->addWidget(item3);
    list->contentLayout->addWidget(item1);
    list->contentLayout->addWidget(item2);

    list->clear();
    EXPECT_TRUE(list->items.isEmpty());
    EXPECT_TRUE(list->contentLayout->isEmpty());

    delete item1;
    delete item2;
    delete item3;
}

TEST_F(UT_wallpaperList, setCurrentIndex)
{
    WallpaperItem *item1 = new WallpaperItem;
    WallpaperItem *item2 = new WallpaperItem;
    WallpaperItem *item3 = new WallpaperItem;
    list->items.append(item1);
    list->items.append(item2);
    list->items.append(item3);
    list->contentLayout->addWidget(item3);
    list->contentLayout->addWidget(item1);
    list->contentLayout->addWidget(item2);

    bool slideUp = false;
    stub.set_lamda(&WallpaperItem::slideUp, [&slideUp, item2](WallpaperItem *t) {
        if (t == item2)
            slideUp = true;
        return;
    });
    stub.set_lamda(&WallpaperItem::slideDown, []() {
        return;
    });

    WallpaperSettingsPrivate pr(nullptr);
    QObject::connect(list, &WallpaperList::itemPressed, &pr, &WallpaperSettingsPrivate::onItemPressed);
    bool emited = false;
    stub.set_lamda(&WallpaperSettingsPrivate::onItemPressed, [&emited]() {
        emited = true;
    });
    bool animationStart = false;
    stub.set_lamda(&QPropertyAnimation::start, [&animationStart]() {
        animationStart = true;
        return;
    });

    {
        list->setCurrentIndex(1);
        EXPECT_TRUE(slideUp);
        EXPECT_TRUE(emited);
        EXPECT_TRUE(animationStart);
        EXPECT_EQ(list->currentIndex, 1);
    }
    {
        slideUp = false;
        emited = false;
        animationStart = false;

        list->setCurrentIndex(4);
        EXPECT_FALSE(slideUp);
        EXPECT_FALSE(emited);
        EXPECT_FALSE(animationStart);
    }
    delete item1;
    delete item2;
    delete item3;
}

TEST_F(UT_wallpaperList, itemAt)
{
    WallpaperItem *item1 = new WallpaperItem;
    WallpaperItem *item2 = new WallpaperItem;
    list->contentLayout->addWidget(item1);
    list->contentLayout->addWidget(item2);

    EXPECT_EQ(list->itemAt(0), item1);
    EXPECT_EQ(list->itemAt(1), item2);
    EXPECT_EQ(list->itemAt(2), nullptr);

    delete item1;
    delete item2;
}

TEST_F(UT_wallpaperList, scrollList)
{
    bool emited = false;
    stub.set_lamda(&WallpaperList::mouseOverItemChanged, [&emited]() {
        __DBG_STUB_INVOKE__
        emited = true;
    });

    WallpaperItem *item = new WallpaperItem();
    list->prevItem = item;
    list->nextItem = item;
    list->scrollList(0,0);
    EXPECT_TRUE(emited);
    EXPECT_EQ(list->prevItem->wrapper->opacityValue,1);
    EXPECT_EQ(list->nextItem->wrapper->opacityValue,1);
    delete item;
}


TEST_F(UT_wallpaperList, Page)
{
    bool call = false;
    auto fun_type =static_cast<int(QSize::*)()const>(&QSize::width);
    stub.set_lamda(fun_type,[&call](){
        __DBG_STUB_INVOKE__
        call = true;
        return 1;
    });
    list->nextPage();
    list->prevPage();
    EXPECT_TRUE(call);
}

TEST_F(UT_wallpaperList, updateBothEndsItem)
{
    bool call = false;
    WallpaperItem *item1 = new WallpaperItem;
    WallpaperItem *item2 = new WallpaperItem;
    WallpaperItem *item3 = new WallpaperItem;
    list->items.append(item1);
    list->items.append(item2);
    list->items.append(item3);
    list->contentLayout->addWidget(item3);
    list->contentLayout->addWidget(item1);
    list->contentLayout->addWidget(item2);

    stub.set_lamda(&QAbstractSlider::value,[](){
       __DBG_STUB_INVOKE__
       return 1;
    });
    auto fun_type = static_cast<QWidget*(WallpaperList::*)(int ,int)const>(&WallpaperList::itemAt);
    stub.set_lamda(fun_type,[](WallpaperList* self, int x, int y){
       __DBG_STUB_INVOKE__
       return self->itemAt(0);
    });
    WallpaperItem *item = new WallpaperItem;
    list->prevItem = item;
    list->nextItem = item;
    list->updateBothEndsItem();
    EXPECT_FALSE(call);
    EXPECT_EQ(list->prevItem->wrapper->opacityValue,0.4);
    EXPECT_EQ(list->nextItem->wrapper->opacityValue,0.4);

    delete item;
    delete item1;
    delete item2;
    delete item3;
}

