#include "labeltrajectory.h"
#include "assertions.h"
#include <iostream>

LabelTrajectory::LabelTrajectory(std::vector<QPointF>&& vertices, TrajectoryType type)
    : _vertices(std::move(vertices)), _type(type)
{
}

qreal LabelTrajectory::parameterValueAtTime(qreal time) const
{
    assert (_vertices.size() >= 2);
    qreal time1 = _vertices.front().x();
    qreal time2 = _vertices.back().x();
    assert (time1 <= time && time <= time2);
    Q_UNUSED(time1); Q_UNUSED(time2);

    // TODO: binary search?
    qreal timeBefore  = _vertices[0].x();
    qreal labelBefore = _vertices[0].y();
    qreal timeAfter   = _vertices[1].x();
    qreal labelAfter  = _vertices[1].y();
    for (std::size_t i = 2; i < _vertices.size(); ++i) {
        if (time <= timeAfter)
            break;
        timeBefore  = timeAfter;
        labelBefore = labelAfter;
        timeAfter  = _vertices[i].x();
        labelAfter = _vertices[i].y();
    }
    qreal alpha = (time - timeBefore) / (timeAfter - timeBefore);
    qreal result = (1-alpha)*labelBefore + alpha*labelAfter;
    assert(!std::isnan(result));
    return result;
}

void LabelTrajectory::printForIpe() const
{
    std::cout << "<path stroke=\"blue\">\n";
    char op = 'm';
    for (auto&& p : _vertices) {
        std::cout << 10*p.x() << " " << p.y() << " " << op << "\n";
        op = 'l';
    }
    std::cout << "</path>\n";

    std::vector<QPointF> dots;
    switch (_type) {
    case PointToPoint:
        dots.emplace_back(_vertices.front());
        dots.emplace_back(_vertices.back());
        break;
    case PointToEdge:
        dots.emplace_back(_vertices.front());
        break;
    case EdgeToPoint:
        dots.emplace_back(_vertices.back());
        break;
    case EdgeToEdge:
        break;
    }
    for (auto&& dot : dots) {
        std::cout << "<use name=\"mark/disk(sx)\" pos=\"" << 10*dot.x() << " " << dot.y()
                  << "\" size=\"normal\" stroke=\"black\"/>" << std::endl;
    }
}
