#include "ConnectionGeometry.hpp"

#include "StyleCollection.hpp"

#include <cmath>
using QtNodes::ConnectionGeometry;
using QtNodes::PortType;
ConnectionGeometry::ConnectionGeometry()
    : _in(0, 0), _out(0, 0)
      //, _animationPhase(0)
      ,
      _lineWidth(3.0), _hovered(false)
{
}
QPointF const &ConnectionGeometry::getEndPoint(PortType portType) const
{
    Q_ASSERT(portType != PortType::None);
    return (portType == PortType::Out ? _out : _in);
}
void ConnectionGeometry::setEndPoint(PortType portType, QPointF const &point)
{
    switch (portType)
    {
        case PortType::Out: _out = point; break;
        case PortType::In: _in = point; break;
        default: break;
    }
}
void ConnectionGeometry::moveEndPoint(PortType portType, QPointF const &offset)
{
    switch (portType)
    {
        case PortType::Out: _out += offset; break;
        case PortType::In: _in += offset; break;
        default: break;
    }
}
QRectF ConnectionGeometry::boundingRect() const
{
    auto points = pointsC1C2();
    QRectF basicRect = QRectF(_out, _in).normalized();
    QRectF c1c2Rect = QRectF(points.first, points.second).normalized();
    auto const &connectionStyle = StyleCollection::connectionStyle();
    float const diam = connectionStyle.pointDiameter();
    QRectF commonRect = basicRect.united(c1c2Rect);
    QPointF const cornerOffset(diam, diam);
    commonRect.setTopLeft(commonRect.topLeft() - cornerOffset);
    commonRect.setBottomRight(commonRect.bottomRight() + 2 * cornerOffset);
    return commonRect;
}
std::pair<QPointF, QPointF> ConnectionGeometry::pointsC1C2() const
{
    const double defaultOffset = 200;
    double xDistance = _in.x() - _out.x();
    double horizontalOffset = qMin(defaultOffset, std::abs(xDistance));
    double verticalOffset = 0;
    double ratioX = 0.5;
    if (xDistance <= 0)
    {
        double yDistance = _in.y() - _out.y() + 20;
        double vector = yDistance < 0 ? -1.0 : 1.0;
        verticalOffset = qMin(defaultOffset, std::abs(yDistance)) * vector;
        ratioX = 1.0;
    }
    horizontalOffset *= ratioX;
    QPointF c1(_out.x() + horizontalOffset, _out.y() + verticalOffset);
    QPointF c2(_in.x() - horizontalOffset, _in.y() - verticalOffset);
    return std::make_pair(c1, c2);
}
