#include "graphingarea.h"
#include <QPainter>
#include <QPaintEvent>

GraphingArea::GraphingArea(QWidget* parent) :
    QWidget(parent), _numBars(0), _leftOffset(0), _rightOffset(0)
{
    setAttribute(Qt::WA_StaticContents);
    resizeEvent(nullptr);
}

void GraphingArea::clear()
{
    _image.fill(Qt::white);
    update();
}

void GraphingArea::drawFreeAndTotalBar(qreal free, qreal total, std::size_t bar, std::size_t numBars)
{
    if (total <= 0) { return; }
    drawBar(total, total, bar, numBars, Qt::red);
    drawBar(free, total, bar, numBars, Qt::blue);
    update();
}

void GraphingArea::drawSpeedBar(qreal minSpeed, qreal avgSpeed, qreal maxSpeed, qreal speedLimit,
                                std::size_t bar, std::size_t numBars)
{
    if (maxSpeed <= 0) { return; }
    drawBar(maxSpeed, speedLimit, bar, numBars, Qt::darkGray);
    drawBar(avgSpeed, speedLimit, bar, numBars, Qt::gray);
    drawBar(minSpeed, speedLimit, bar, numBars, Qt::lightGray);
    update();
}

void GraphingArea::drawBar(qreal value, qreal maxValue, std::size_t bar, std::size_t numBars,
                           Qt::GlobalColor color)
{
    ensureImageIsLargeEnough(numBars, height());
    _numBars = numBars;

    qreal barWidth = 1;
    qreal barHeight = std::min((qreal)height() * value / maxValue, (qreal)height());
    qreal left = bar;
    qreal top = height() - barHeight;
    QRectF rect(left, top, barWidth, barHeight);

    QPainter painter(&_image);
    painter.setPen(Qt::NoPen);
    painter.setBrush( QBrush(color, Qt::SolidPattern) );
    painter.drawRect(rect);
}

void GraphingArea::paintEvent(QPaintEvent* event)
{
    QRect target = event->rect();
    target.setLeft ( std::max(target.left(), _leftOffset) );
    target.setRight( std::min(target.right(), width() - _rightOffset) );

    qreal left = pixelToBar(target.left());
    qreal right = pixelToBar(target.right());
    QRectF source(left, 0.0, right-left, height());

    QPainter painter(this);
    painter.drawImage(target, _image, source);
}

void GraphingArea::resizeEvent(QResizeEvent* event)
{
    ensureImageIsLargeEnough(std::max(_numBars+1, width()), height());
    if (event) { QWidget::resizeEvent(event); }
}

void GraphingArea::ensureImageIsLargeEnough(int minWidth, int minHeight)
{
    if (minWidth > _image.width() || minHeight > _image.height()) {
        int w = std::max(minWidth + 128,  _image.width());
        int h = std::max(minHeight + 128, _image.height());
        _image = QImage(w, h, QImage::Format_RGB32);
        _image.fill(Qt::white);
    }
}

int GraphingArea::canvasWidth() const
{
    return width() - _leftOffset - _rightOffset;
}
int GraphingArea::graphWidth() const
{
    return _numBars+1;
}

qreal GraphingArea::pixelToBar(qreal px) const
{
    return (px - _leftOffset) * (qreal)graphWidth() / canvasWidth();
}
qreal GraphingArea::barToPixel(qreal bar) const
{
    return _leftOffset + bar * (qreal)canvasWidth() / graphWidth();
}
