#include "BarRow.h"

#include <algorithm>

#include <QHBoxLayout>
#include <QLabel>
#include <QPainter>
#include <QPaintEvent>
#include <QVBoxLayout>

namespace
{

// Height and corner radius of the fill bar, in device-independent pixels.
const int   kBarHeightPx   = 6;
const qreal kBarRadiusPx   = 3.0;

// Opacity of the unfilled track, over the card's background.
const int kTrackAlpha = 60;

}  // namespace


// The bar itself. Painted rather than assembled from a QProgressBar, because all it
// needs is a rounded track with a rounded fill and a style sheet cannot be relied on to
// leave a progress bar's groove and chunk alone across styles.
class BarRow::Bar : public QWidget
{
public:
    explicit Bar(QWidget* parent)
        : QWidget(parent)
        , m_fraction(0.0)
    {
        setFixedHeight(kBarHeightPx);
        setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    }

    void setFraction(double fraction)
    {
        m_fraction = std::max(0.0, std::min(1.0, fraction));
        update();
    }

    void setFillColor(const QColor& color)
    {
        m_fillColor = color;
        update();
    }

protected:
    void paintEvent(QPaintEvent* /*event*/) override
    {
        // The active group is asked for by name rather than taken from the current one,
        // which follows the window's focus: the inactive group's highlight is close
        // enough to the card's background that the bar reads as gone whenever the game
        // is tabbed away from or a modal dialog holds focus -- exactly when a player
        // watching a build finish is most likely to be looking at it.
        const QColor fill = m_fillColor.isValid()
            ? m_fillColor
            : palette().color(QPalette::Active, QPalette::Highlight);

        QColor track = fill;
        track.setAlpha(kTrackAlpha);

        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing, true);
        painter.setPen(Qt::NoPen);

        painter.setBrush(track);
        painter.drawRoundedRect(rect(), kBarRadiusPx, kBarRadiusPx);

        if (m_fraction > 0.0)
        {
            QRect filled = rect();
            filled.setWidth(static_cast<int>(filled.width() * m_fraction));
            painter.setBrush(fill);
            painter.drawRoundedRect(filled, kBarRadiusPx, kBarRadiusPx);
        }
    }

private:
    double m_fraction;
    QColor m_fillColor;
};


BarRow::BarRow(const QString& caption, QWidget* parent)
    : QWidget(parent)
{
    QVBoxLayout* layout = new QVBoxLayout(this);
    layout->setContentsMargins(0, 0, 0, 0);
    layout->setSpacing(2);

    QWidget* captionRow = new QWidget(this);
    QHBoxLayout* captionLayout = new QHBoxLayout(captionRow);
    captionLayout->setContentsMargins(0, 0, 0, 0);
    captionLayout->setSpacing(8);

    m_captionLabel = new QLabel(caption, captionRow);
    m_captionLabel->setVisible(!caption.isEmpty());
    m_valueLabel = new QLabel(captionRow);
    m_valueLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);

    captionLayout->addWidget(m_captionLabel);
    captionLayout->addStretch(1);
    captionLayout->addWidget(m_valueLabel);

    m_bar = new Bar(this);

    layout->addWidget(captionRow);
    layout->addWidget(m_bar);
}

void BarRow::setValue(double fraction, const QString& valueText)
{
    m_bar->setFraction(fraction);
    m_valueLabel->setText(valueText);
}

void BarRow::setFillColor(const QColor& color)
{
    m_bar->setFillColor(color);
}
