//
// Created by iaom on 2025/9/12.
//

#include "region.h"

#include <QCoreApplication>
#include <QEvent>
#include <QPainterPath>

namespace UkuiQuick {
class RectRegionPrivate
{
public:
    int m_x = 0;
    int m_y = 0;
    int m_width = 0;
    int m_height = 0;
    int m_radius = 0;
};

RectRegion::RectRegion(QObject *parent) : QObject(parent), d(new RectRegionPrivate)
{
}

RectRegion::~RectRegion()
{
    if (d) {
        delete d;
        d = nullptr;
    }
}

void RectRegion::setX(int x)
{
    if(d->m_x == x) {
        return;
    }
    d->m_x = x;
    Q_EMIT xChanged();
}

int RectRegion::x() const
{
    return d->m_x;
}

void RectRegion::setY(int y)
{
    if(d->m_y == y) {
        return;
    }
    d->m_y = y;
    Q_EMIT yChanged();
}

int RectRegion::y() const
{
    return d->m_y;
}

void RectRegion::setWidth(int width)
{
    if(d->m_width == width) {
        return;
    }
    d->m_width = width;
    Q_EMIT widthChanged();
}

int RectRegion::width() const
{
    return d->m_width;
}

void RectRegion::setHeight(int height)
{
    if(d->m_height == height) {
        return;
    }
    d->m_height = height;
    Q_EMIT heightChanged();
}

int RectRegion::height() const
{
    return d->m_height;
}

void RectRegion::setRadius(int radius)
{
    if(d->m_radius == radius) {
        return;
    }
    d->m_radius = radius;
    Q_EMIT radiusChanged();
}

int RectRegion::radius() const
{
    return d->m_radius;
}

class RegionPrivate : public QObject
{
    Q_OBJECT
public:
    RegionPrivate(Region *parent = nullptr);
    void onRectChanged();
    void updateRegion();
    QList<UkuiQuick::RectRegion *> m_rectRegions;
    QRegion m_region;
    bool m_requestUpdate = false;
    Region *q = nullptr;
};

RegionPrivate::RegionPrivate(Region* parent) : QObject(parent), q(parent)
{
}

void RegionPrivate::onRectChanged()
{
    if (!m_requestUpdate) {
        m_requestUpdate = true;;
        QCoreApplication::postEvent(q, new QEvent(QEvent::UpdateRequest));
    }
}

void RegionPrivate::updateRegion()
{
    m_region = QRegion();
    for (const auto rect : m_rectRegions) {
        QPainterPath path;
        path.addRoundedRect(rect->x(), rect->y(), rect->width(), rect->height(), rect->radius(), rect->radius());
        m_region += QRegion(path.toFillPolygon().toPolygon());
    }
    Q_EMIT q->regionChanged();
}

Region::Region(QObject* parent) : QObject(parent), d(new RegionPrivate(this))
{
}

void Region::appendRect(UkuiQuick::RectRegion* rect)
{
    if (!rect) {
        return;
    }
    d->m_rectRegions.append(rect);
    // 增加一个圆角矩形
    QPainterPath path;
    path.addRoundedRect(rect->x(), rect->y(), rect->width(), rect->height(), rect->radius(), rect->radius());
    d->m_region += QRegion(path.toFillPolygon().toPolygon());
    connect(rect, &RectRegion::xChanged, d, &RegionPrivate::onRectChanged);
    connect(rect, &RectRegion::yChanged, d, &RegionPrivate::onRectChanged);
    connect(rect, &RectRegion::widthChanged, d, &RegionPrivate::onRectChanged);
    connect(rect, &RectRegion::heightChanged, d, &RegionPrivate::onRectChanged);
    connect(rect, &RectRegion::radiusChanged, d, &RegionPrivate::onRectChanged);
    Q_EMIT regionChanged();
}

void Region::removeRect(UkuiQuick::RectRegion* rect)
{
    if (!rect) {
        return;
    }
    rect->disconnect(d);
    d->m_rectRegions.removeOne(rect);
    Q_EMIT regionChanged();
}

void Region::clear()
{
    for (const UkuiQuick::RectRegion* rect : d->m_rectRegions)
    {
        rect->disconnect(d);
    }
    d->m_rectRegions.clear();
}

QRegion Region::region() const
{
    return d->m_region;
}

bool Region::event(QEvent* event)
{
    if (event->type() == QEvent::UpdateRequest) {
        d->updateRegion();
        d->m_requestUpdate = false;
    }
    return QObject::event(event);
}
}
#include "region.moc"
