#include <Graphics/GraphicsBox.hpp>

#include <utility>

#include <QtCore/QRectF>
#include <QtGui/QPainter>
#include <QtWidgets/QStyleOptionGraphicsItem>

#include <Graphics/Connection/InputConnectionBox.hpp>
#include <Graphics/Connection/OutputConnectionBox.hpp>

std::vector<GraphicsBox*> GraphicsBox::allGraphicsBoxes;

GraphicsBox::GraphicsBox(std::unique_ptr<ModelBox> p_modelBox, QPointF pos)
    : color(Qt::blue)
    , text(QString::fromStdString(p_modelBox->getName()))
    , modelBox(std::move(p_modelBox))
{
    GraphicsBox::allGraphicsBoxes.push_back(this);

    this->font.setBold(true);
    this->font.setPixelSize(18);

    this->setPos(pos);
    this->setFlags(ItemIsMovable);
    this->setZValue(1);

    this->boundRect = QFontMetrics(this->font).boundingRect(this->text);
    this->boundRect.setHeight(std::max(this->boundRect.height(), std::max(this->modelBox->getMaxInputCount(), size_t(1)) * 16.0));
    this->boundRect.adjust(-20, -20, 20, 20);

    size_t maxInputCount = this->modelBox->getMaxInputCount();
    for (size_t i = 0; i < maxInputCount; ++i)
    {
        auto* box = new InputConnectionBox(this, i);
        box->setPos(this->boundRect.left(), this->boundRect.top() + ((i + 1) * this->boundRect.height()) / float(maxInputCount + 1));
        this->inputConnectionBoxes.push_back(box);
    }

    if (this->modelBox->canHaveOutput()) {
        this->outputConnectionBox = new OutputConnectionBox(this);
        this->outputConnectionBox->setPos(this->boundRect.right(), this->boundRect.top() + this->boundRect.height() / 2.0);
    }
}

GraphicsBox::~GraphicsBox() {
    auto& bv = GraphicsBox::allGraphicsBoxes;
    bv.erase(std::remove(bv.begin(), bv.end(), this), bv.end());
}

QRectF GraphicsBox::boundingRect() const {
    return this->boundRect;
}

void GraphicsBox::paint(QPainter* painter, const QStyleOptionGraphicsItem* /*option*/, QWidget* /*widget*/) {
    painter->setFont(this->font);
    painter->setPen(Qt::white);
    painter->fillRect(this->boundRect, this->color);
    painter->drawText(this->boundRect, Qt::AlignCenter, this->text);
}

const std::vector<InputConnectionBox*>& GraphicsBox::getInputConnectionBoxes() const {
    return inputConnectionBoxes;
}

OutputConnectionBox* GraphicsBox::getOutputConnectionBox() const {
    return outputConnectionBox;
}
