#include <QDebug>

#include "xlink.h"

#include "branchitem.h"
#include "misc.h"
#include "vymmodel.h"
#include "xlinkitem.h"
#include "xlinkobj.h"

class VymModel;

/////////////////////////////////////////////////////////////////
// Link
/////////////////////////////////////////////////////////////////

Link::Link(VymModel *m)
{
    // qDebug() << "Const Link () this="<<this;
    model = m;
    init();
}

Link::~Link()
{
    //    qDebug()<<"* Destr Link begin this="<<this<<"  bLI="<<beginLinkItem<<"
    //    eLI="<<endLinkItem;
    deactivate();
    //    qDebug()<<"* Destr Link end   this="<<this;
}

void Link::init()
{
    xlo = NULL;
    beginBranch = NULL;
    endBranch = NULL;
    beginLinkItem = NULL;
    endLinkItem = NULL;
    xLinkState = Link::undefinedXLink;

    type = Bezier;
    pen = model->getMapDefXLinkPen();
}

VymModel *Link::getModel() { return model; }

void Link::setBeginBranch(BranchItem *bi)
{
    if (bi) {
        xLinkState = initXLink;
        beginBranch = bi;
    }
}

BranchItem *Link::getBeginBranch() { return beginBranch; }

void Link::setEndBranch(BranchItem *bi)
{
    if (bi) {
        endBranch = bi;
        if (xlo)
            xlo->initC1();
    }
}

BranchItem *Link::getEndBranch() { return endBranch; }

void Link::setEndPoint(QPointF p)
{
    // Used only while creating the link, without endBranch
    if (xlo)
        xlo->setEnd(p);
}

void Link::setBeginLinkItem(XLinkItem *li)
{
    if (li) {
        xLinkState = initXLink;
        beginLinkItem = li;
    }
}

XLinkItem *Link::getBeginLinkItem() { return beginLinkItem; }

void Link::setEndLinkItem(XLinkItem *li)
{
    if (li) {
        xLinkState = initXLink;
        endLinkItem = li;
    }
}

XLinkItem *Link::getEndLinkItem() { return endLinkItem; }

XLinkItem *Link::getOtherEnd(XLinkItem *xli)
{
    if (xli == beginLinkItem)
        return endLinkItem;
    if (xli == endLinkItem)
        return beginLinkItem;
    return NULL;
}

void Link::setPen(const QPen &p)
{
    pen = p;
    if (xlo)
        xlo->updateXLink();
}

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

void Link::setLinkType(const QString &s)
{
    if (s == "Linear")
        type = Linear;
    else if (s == "Bezier")
        type = Bezier;
    else
        qWarning() << "Link::setLinkType  Unknown type: " << s;
}

void Link::setStyleBegin(const QString &s)
{
    if (xlo) {
        xlo->setStyleBegin(s);
        xlo->updateXLink();
    }
}

QString Link::getStyleBeginString()
{
    if (xlo)
        return ArrowObj::styleToString(xlo->getStyleBegin());
    else
        return QString();
}

void Link::setStyleEnd(const QString &s)
{
    if (xlo) {
        xlo->setStyleEnd(s);
        xlo->updateXLink();
    }
}

QString Link::getStyleEndString()
{
    if (xlo)
        return ArrowObj::styleToString(xlo->getStyleEnd());
    else
        return QString();
}

bool Link::activate()
{
    if (beginBranch && endBranch) {
        if (beginBranch == endBranch)
            return false;
        xLinkState = activeXLink;
        model->updateActions();
        return true;
    }
    else
        return false;
}

void Link::deactivate()
{
    // Remove pointers from XLinkItem to Link and
    // delete XLinkObj

    //    qDebug()<<"Link::deactivate ******************************";
    xLinkState = deleteXLink;
    if (beginLinkItem)
        beginLinkItem->setLink(NULL);
    if (endLinkItem)
        endLinkItem->setLink(NULL);
    if (xlo) {
        delete (xlo);
        xlo = NULL;
    }
}

Link::XLinkState Link::getState() { return xLinkState; }

void Link::removeXLinkItem(XLinkItem *xli)
{
    // Only mark _one_ end for removal here!
    if (xli == beginLinkItem)
        beginLinkItem = NULL;
    if (xli == endLinkItem)
        endLinkItem = NULL;
    xLinkState = deleteXLink;
}

void Link::updateLink()
{
    if (xlo)
        xlo->updateXLink();
}

QString Link::saveToDir()
{
    //    qDebug()<<"Link::saveToDir  this="<<this<<"
    //    beginBranch="<<beginBranch<<"  endBranch="<<endBranch<<"
    //    state="<<xLinkState;
    QString s = "";
    if (beginBranch && endBranch && xLinkState == activeXLink) {
        if (beginBranch == endBranch)
            qWarning(
                "Link::saveToDir  ignored, because beginBranch==endBranch, ");
        else {
            QString colAttr = attribut("color", pen.color().name());
            QString widAttr =
                attribut("width", QString().setNum(pen.width(), 10));
            QString styAttr =
                attribut("penstyle", penStyleToString(pen.style()));
            QString ctrlAttr;
            QString typeAttr;
            switch (type) {
            case Linear:
                typeAttr = attribut("type", "Linear");
                break;
            case Bezier:
                typeAttr = attribut("type", "Bezier");
                if (xlo) {
                    ctrlAttr += attribut("c0", pointToString(xlo->getC0()));
                    ctrlAttr += attribut("c1", pointToString(xlo->getC1()));
                }
                break;
            }
            QString begSelAttr =
                attribut("beginID", model->getSelectString(beginBranch));
            QString endSelAttr =
                attribut("endID", model->getSelectString(endBranch));
            QString styleAttr;
            if (xlo) {
                styleAttr =
                    QString(" styleBegin=\"%1\"")
                        .arg(ArrowObj::styleToString(xlo->getStyleBegin()));
                styleAttr +=
                    QString(" styleEnd=\"%1\"")
                        .arg(ArrowObj::styleToString(xlo->getStyleEnd()));
            }
            s = singleElement("xlink", colAttr + widAttr + styAttr + typeAttr +
                                           ctrlAttr + begSelAttr + endSelAttr +
                                           styleAttr);
        }
    }
    return s;
}

XLinkObj *Link::getXLinkObj() { return xlo; }

XLinkObj *Link::createMapObj()
{
    if (!xlo)
        xlo = new XLinkObj(beginBranch->getLMO(), this);
    xlo->setVisibility();
    return xlo;
}

MapObj *Link::getMO() { return xlo; }
