#include "arrowobj.h"
#include "misc.h"

#include <QDebug>
#include <QGraphicsScene>

/////////////////////////////////////////////////////////////////
// ArrowObj
/////////////////////////////////////////////////////////////////

ArrowObj::ArrowObj(MapObj *parent) : MapObj(parent) { init(); }

ArrowObj::~ArrowObj()
{
    delete arrowBegin;
    delete arrowEnd;
    delete line;
}

void ArrowObj::init()
{
    QPen pen;

    pen.setStyle(Qt::SolidLine);
    arrowBegin = scene()->addPolygon(QPolygonF(), pen);
    arrowBegin->setZValue(dZ_XLINK);
    arrowEnd = scene()->addPolygon(QPolygonF(), pen);
    arrowEnd->setZValue(dZ_XLINK);

    line = scene()->addLine(QLineF(), pen);
    line->setZValue(dZ_XLINK);

    arrowSize = 4;
    useFixedLength = false;
    setStyleBegin(None);
    setStyleEnd(HeadFull);
}

void ArrowObj::setPen(QPen p)
{
    pen = p;
    line->setPen(pen);

    // end shall have same style as xlink
    QPen pen_solid = pen;
    pen_solid.setStyle(Qt::SolidLine);
    arrowBegin->setPen(pen_solid);
    arrowEnd->setPen(pen_solid);

    setStyleBegin(styleBegin);
    setStyleEnd(styleEnd);
}

QPen ArrowObj::getPen() { return pen; }

void ArrowObj::setArrowSize(qreal r) { arrowSize = r; }

qreal ArrowObj::getArrowSize() { return arrowSize; }

void ArrowObj::setUseFixedLength(bool b) { useFixedLength = b; }

bool ArrowObj::getUseFixedLength() { return useFixedLength; }

void ArrowObj::setFixedLength(int i) { fixedLength = i; }

int ArrowObj::getFixedLength() { return fixedLength; }

void ArrowObj::show() { setVisibility(true); }

void ArrowObj::hide() { setVisibility(false); }

void ArrowObj::setVisibility(bool b)
{
    MapObj::setVisibility(b);
    if (b) {
        if (styleEnd != None)
            arrowEnd->show();
        else
            arrowEnd->hide();
        if (useFixedLength && fixedLength == 0)
            line->hide();
        else
            line->show();
    }
    else {
        arrowEnd->hide();
        line->hide();
    }
}

void ArrowObj::setEndPoint(QPointF p)
{
    endPoint = p;

    line->setLine(absPos.x(), absPos.y(), p.x(), p.y());
    arrowEnd->setPos(absPos);

    qreal a = getAngle(endPoint - absPos);
    arrowEnd->setRotation(-a / 6.28 * 360);
    arrowEnd->setPos(endPoint);
}

QPointF ArrowObj::getEndPoint() { return endPoint; }

void ArrowObj::setStyleBegin(const QString &s)
{
    if (s == "HeadFull")
        setStyleBegin(ArrowObj::HeadFull);
    else
        setStyleBegin(ArrowObj::None);
}

void ArrowObj::setStyleBegin(OrnamentStyle os)
{
    styleBegin = os;
    switch (styleBegin) {
    case HeadFull:
        arrowEnd->setPolygon(getArrowHead());
        arrowBegin->setBrush(pen.color());
        break;
    case Foot:
        break;
    case None:
        arrowBegin->setPolygon(QPolygonF());
        break;
    }
}

ArrowObj::OrnamentStyle ArrowObj::getStyleBegin() { return styleBegin; }

void ArrowObj::setStyleEnd(const QString &s)
{
    if (s == "HeadFull")
        setStyleEnd(ArrowObj::HeadFull);
    else
        setStyleEnd(ArrowObj::None);
}

void ArrowObj::setStyleEnd(OrnamentStyle os)
{
    styleEnd = os;
    switch (styleEnd) {
    case HeadFull:
        arrowEnd->setPolygon(getArrowHead());
        arrowEnd->setBrush(pen.color());
        break;
    case Foot:
        break;
    case None:
        arrowEnd->setPolygon(QPolygonF());
        break;
    }
}

QPolygonF ArrowObj::getArrowHead()
{
    QPointF a, b, c;
    QPolygonF pa;
    b = a + QPointF(-arrowSize * 2, -arrowSize);
    c = a + QPointF(-arrowSize * 2, +arrowSize);
    pa << a << b << c;
    return pa;
}

ArrowObj::OrnamentStyle ArrowObj::getStyleEnd() { return styleEnd; }

QString ArrowObj::styleToString(const OrnamentStyle &os)
{
    switch (os) {
    case HeadFull:
        return "HeadFull";
        break;
    case None:
        return "None";
        break;
    default:
        qWarning() << "ArrowObj::styleToString unknown style " << os;
    }
    return "Unknown";
}
