#include <Graphics/Connection/ConnectionBox.hpp>

#include <utility>

#include <QtWidgets/QApplication>
#include <QtWidgets/QMessageBox>

#include <Graphics/Connection/InputConnectionBox.hpp>
#include <Graphics/Connection/OutputConnectionBox.hpp>
#include <Graphics/GraphicsBox.hpp>
#include <Graphics/GraphicsScene.hpp>
#include <QtWidgets/QMenu>

const QColor ConnectionBox::defaultColor = Qt::white;

ConnectionBox::ConnectionBox(GraphicsBox* parent, Type p_type)
    : QGraphicsRectItem(-8, -8, 16, 16, parent)
    , type(p_type)

{
    this->setBrush(ConnectionBox::defaultColor);
    this->setAcceptedMouseButtons(Qt::LeftButton);
}

void ConnectionBox::mousePressEvent(QGraphicsSceneMouseEvent* /*event*/) {
    this->setCursor(Qt::UpArrowCursor);

    Q_ASSERT(!this->tempLine);
    this->tempLine = this->scene()->addLine({this->scenePos(), this->scenePos()});
    this->tempLine->setZValue(2);
}

void ConnectionBox::mouseMoveEvent(QGraphicsSceneMouseEvent* event) {
    Q_ASSERT(this->tempLine);
    QLineF line = this->tempLine->line();
    line.setP2(event->scenePos());
    this->tempLine->setLine(line);
}

void ConnectionBox::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) {
    try {
        this->setCursor(Qt::ArrowCursor);

        Q_ASSERT(this->tempLine);
        delete this->tempLine;
        this->tempLine = nullptr;

        auto* other = dynamic_cast<ConnectionBox*>(this->scene()->itemAt(event->scenePos(), {}));
        if (other && other->getType() != this->getType())
        {
            // TODO improve this
            auto* a = this;
            auto* b = other;
            if (a->getType() != ConnectionBox::Type::Output)
                std::swap(a, b);

            auto* origin = dynamic_cast<OutputConnectionBox*>(a);
            auto* target = dynamic_cast<InputConnectionBox*>(b);

            new Connection(origin, target); //FIXME leak?
        }
    } catch ( ... ) {
/*
		std::stringstream ss;
		alib::ExceptionHandler::handle ( ss );
		QMessageBox::critical(this, "Error", ss.str ( ) );
*/
    }
}

void ConnectionBox::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) {
    QMenu menu;
    QAction* a = menu.addAction("&Disconnect");
    QObject::connect(a, SIGNAL(triggered()), this, SLOT(on_Disconnect()));
    menu.exec(event->screenPos());
    event->accept();
}

GraphicsBox* ConnectionBox::getParent() const {
    auto* parent = dynamic_cast<GraphicsBox*>(this->parentObject());
    Q_ASSERT(parent);
    return parent;
}
