// Copyright (C) 2020 ~ 2021, Deepin Technology Co., Ltd. <support@deepin.org>
// SPDX-FileCopyrightText: 2022 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "tip.h"

#include <QDebug>
#include <QHBoxLayout>
#include <QLabel>
#include <QPainter>
#include <QPainterPath>
#include <QGraphicsDropShadowEffect>
#include <QPropertyAnimation>
#include <QGraphicsOpacityEffect>
#include <QDBusReply>

#include <DUtil>
#include <dthememanager.h>
#include <DLabel>
#include <DWindowManagerHelper>

DWIDGET_USE_NAMESPACE
namespace dmr {
class TipPrivate
{
public:
    explicit TipPrivate(Tip *parent) : q_ptr(parent) {}

    void setBackgroundImage(const QPixmap &srcPixmap);

    QBrush          background;
    int             radius              = 8;
    int             shadowWidth         = 20;
    QMargins        shadowMargins       = QMargins(20, 20, 20, 20);
    QColor          borderColor         = QColor(0, 0, 0, static_cast<int>(0.2 * 255));

    DLabel          *textLable          = nullptr;
    QFrame          *m_interFrame       = nullptr;


    Tip *q_ptr;
    Q_DECLARE_PUBLIC(Tip)
};


Tip::Tip(const QPixmap &icon, const QString &text, QWidget *parent)
    : QFrame(parent), d_ptr(new TipPrivate(this))
{
    qDebug() << "Initializing Tip widget with text:" << text;
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    DThemeManager::instance()->registerWidget(this);
#endif
    Q_D(Tip);

    setAttribute(Qt::WA_DeleteOnClose);
    setWindowFlags(Qt::ToolTip | Qt::CustomizeWindowHint);
    setAttribute(Qt::WA_TranslucentBackground);
    setObjectName("Tip");
    setContentsMargins(0, 0, 0, 0);

    auto layout = new QHBoxLayout(this);
    layout->setContentsMargins(7, 4, 7, 4);
    layout->setSpacing(0);

    d->m_interFrame = new QFrame(this);
    d->m_interFrame->setContentsMargins(0, 0, 0, 0);
    auto interlayout = new QHBoxLayout(d->m_interFrame);
    interlayout->setContentsMargins(0, 0, 0, 0);
    interlayout->setSpacing(5);
    auto iconLabel = new QLabel;
    iconLabel->setObjectName("TipIcon");
    iconLabel->setFixedSize(icon.size());
    if (icon.isNull()) {
        qDebug() << "No icon provided for tip";
        iconLabel->hide();
    } else {
        qDebug() << "Setting tip icon with size:" << icon.size();
        iconLabel->setPixmap(icon);
    }

    d->textLable = new DLabel(text);
    d->textLable->setObjectName("TipText");
    d->textLable->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
    d->textLable->setWordWrap(false);
    DFontSizeManager::instance()->bind(d->textLable, DFontSizeManager::T8);
    d->textLable->setForegroundRole(DPalette::ToolTipText);

    interlayout->addWidget(iconLabel, 0, Qt::AlignVCenter);
    interlayout->addWidget(d->textLable, 0, Qt::AlignVCenter);
    layout->addWidget(d->m_interFrame, 0, Qt::AlignVCenter);

    adjustSize();

    auto *bodyShadow = new QGraphicsDropShadowEffect(this);
    bodyShadow->setBlurRadius(10.0);
    bodyShadow->setColor(QColor(0, 0, 0, static_cast<int>(0.1 * 255)));
    bodyShadow->setOffset(0, 2.0);
    hide();

    bIsWM = DWindowManagerHelper::instance()->hasBlurWindow();
    qDebug() << "Window manager blur support:" << bIsWM;
    connect(DWindowManagerHelper::instance(), &DWindowManagerHelper::hasBlurWindowChanged, this, &Tip::slotWMChanged);
}

Tip::~Tip()
{
    qDebug() << "Tip widget destroyed";
}

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)  
void Tip::enterEvent(QEvent *e)
{
    qDebug() << "Entering enterEvent function";
    hide();

    QFrame::enterEvent(e);
}
#else
void Tip::enterEvent(QEnterEvent *e)
{
    qDebug() << "Entering enterEvent function";
    hide();

    QFrame::enterEvent(e);
}
#endif

QBrush Tip::background() const
{
    qDebug() << "Entering background function";
    Q_D(const Tip);
    return d->background;
}

void Tip::setText(const QString text)
{
    qDebug() << "Entering setText function";
    Q_D(const Tip);
    qDebug() << "Setting tip text:" << text;
    d->textLable->setText(text);
    m_strText = text;
    update();
}

int Tip::radius() const
{
    qDebug() << "Entering radius function";
    Q_D(const Tip);
    return d->radius;
}

QColor Tip::borderColor() const
{
    qDebug() << "Entering borderColor function";
    Q_D(const Tip);
    return d->borderColor;
}

void Tip::setBackground(QBrush background)
{
    Q_D(Tip);
    qDebug() << "Entering setBackground function";
    d->background = background;
}

void Tip::setRadius(int radius)
{
    Q_D(Tip);
    qDebug() << "Entering setRadius function";
    d->radius = radius;
}

void Tip::setBorderColor(QColor borderColor)
{
    qDebug() << "Entering setBorderColor function";
    Q_D(Tip);
    d->borderColor = borderColor;
}

void Tip::slotWMChanged()
{
    qDebug() << "Entering slotWMChanged function";
    bIsWM = DWindowManagerHelper::instance()->hasBlurWindow();
    qDebug() << "Window manager blur support changed:" << bIsWM;
}

void Tip::pop(QPoint center)
{
    qDebug() << "Pop tip at position:" << center;
    Q_D(Tip);
    this->show();
    center = center - QPoint(width() / 2, height() / 2);
    this->move(center);
}

#ifdef _OLD
void Tip::paintEvent(QPaintEvent *)
{
    qDebug() << "Entering paintEvent function";
    Q_D(Tip);

    QPainter painter(this);
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    painter.setRenderHints(QPainter::Antialiasing | QPainter::HighQualityAntialiasing);
#else
    painter.setRenderHint(QPainter::Antialiasing);
#endif
    auto radius = d->radius;
    auto penWidthf = 1.0;
    const QPalette pal = QGuiApplication::palette();//this->palette();
    QColor background = pal.color(QPalette::ToolTipBase);
    DPalette pa_name = DGuiApplicationHelper::instance()->palette(d->textLable);
    pa_name.setBrush(DPalette::Text, pa_name.color(DPalette::ToolTipText));
    pa_name.setBrush(DPalette::ToolTipText, pa_name.color(DPalette::ToolTipText));
    d->textLable->setForegroundRole(DPalette::Text);
    d->textLable->setForegroundRole(DPalette::ToolTipText);
    d->textLable->setPalette(pa_name);
    auto borderColor = d->borderColor;
    auto margin = 2.0;
    auto shadowMargins = QMarginsF(margin, margin, margin, margin);

    auto backgroundRect = QRectF(rect()).marginsRemoved(shadowMargins);
    QPainterPath backgroundPath;
    backgroundPath.addRoundedRect(backgroundRect, radius, radius);
    painter.fillPath(backgroundPath, background);

    QPainterPath borderPath;
    QRectF borderRect = QRectF(rect());
    auto borderRadius = radius;
    QMarginsF borderMargin(penWidthf / 2, penWidthf / 2, penWidthf / 2, penWidthf / 2);

    borderRadius += penWidthf / 2;
    borderRect = borderRect.marginsAdded(borderMargin).marginsRemoved(shadowMargins);
    borderPath.addRoundedRect(borderRect, borderRadius, borderRadius);
    QPen borderPen(borderColor);
    borderPen.setWidthF(penWidthf);
    painter.strokePath(borderPath, borderPen);
    qDebug() << "Exiting paintEvent function";
}
#else
void Tip::paintEvent(QPaintEvent *)
{
    qDebug() << "Entering paintEvent function";
    Q_D(Tip);
    QPainter pt(this);
    pt.setRenderHint(QPainter::Antialiasing);

    int transparency = 245;
    if (!bIsWM) {
        qDebug() << "Not bIsWM, setting transparency to 255";
        transparency = 255;
    }
    if (DGuiApplicationHelper::LightType == DGuiApplicationHelper::instance()->themeType()) {
        qDebug() << "LightType";
        pt.setPen(QColor(0, 0, 0, 10));
        pt.setBrush(QBrush(QColor(247, 247, 247, transparency)));
    } else if (DGuiApplicationHelper::DarkType == DGuiApplicationHelper::instance()->themeType()) {
        qDebug() << "DarkType";
        pt.setPen(QColor(255, 255, 255, 10));
        pt.setBrush(QBrush(QColor(42, 42, 42, transparency)));
    } else {
        qDebug() << "OtherType";
        pt.setPen(QColor(0, 0, 0, 10));
        pt.setBrush(QBrush(QColor(247, 247, 247, transparency)));
    }

    QRect rect = this->rect();
    QPainterPath painterPath;
    if (bIsWM) {
        qDebug() << "bIsWM";
        rect.setWidth(rect.width() - 1);
        rect.setHeight(rect.height() - 1);
        painterPath.addRoundedRect(rect, d->radius, d->radius);
    } else {
        qDebug() << "Not bIsWM";
        painterPath.addRect(rect);
    }
    pt.drawPath(painterPath);
}
#endif

void Tip::resizeEvent(QResizeEvent *ev)
{
    qDebug() << "Entering resizeEvent function";
    return QWidget::resizeEvent(ev);
}

void Tip::resetSize(const int maxWidth)
{
    qDebug() << "Entering resetSize function";
    Q_D(Tip);
    QFont font = DFontSizeManager::instance()->get(DFontSizeManager::T8);
    QFontMetrics fm(font);
    auto w = fm.boundingRect(d->textLable->text()).width();

    if (w >= maxWidth - 14) {
        qDebug() << "w >= maxWidth - 14";
        d->textLable->setWordWrap(true);
        this->setFixedWidth(maxWidth);
        d->textLable->setFixedWidth(maxWidth - 14);
    }
    qDebug() << "Exiting resetSize function";
}

}
