/**
 * Author:  David Thompson
 * Date:    28 June, 2019
 * Purpose: To build a curve represenation of a transition line
 */

#pragma once

#include <QList>
#include <QGraphicsPathItem>

namespace DESpot {

enum class CurveType {
	// Connect the points with lines
	LINE,
	// Connect the points with a smooth curve that goes through
	CATMULL_ROM,
	// Use every other point as a control point for a quadratic bezier
	// (does not go through all points and isn't guarenteed to be smooth)
	BEZIER
};

class GedDesTransCurve {

private:
    QList<QPointF> points;
	CurveType type;

    /**
     * Get all the params for making an arc from a given set of three points
     */
    void arcParams(QPointF start, QPointF mid, QPointF end,
        QRectF & size, double & startAngle, double & sweepAngle) const;

    /**
     * Given three ordered points forming an arc, find the center of the
     * corresponding circle
     */
    QPointF centerOfArc(QPointF start, QPointF mid, QPointF end) const;

    /**
     * Given a line, find its midpoint
     */
    QPointF centerOfLine(QLineF line) const;

    /**
     * Different strategies for drawing the curve
     */

    /**
     * Just draw a sequence of lines
     */
    void draw_lines(QPainterPath & curve) const;

    /**
     * Draw sets of quadratic beziers until zero or one segment remains, and
     * use a line if there is one more segment.
     */
    void draw_quadraticAndLine(QPainterPath & curve) const;

    /**
     * Draw sets of quadratic beziers until zero or three segments remain.
     * Finish with a cubic if three segments remain
     */
    void draw_quadraticAndCubic(QPainterPath & curve) const;
    
    /**
     * Use a uniform Catmull-Rom spline. Approximate it by drawing it with line
     * segments.
     */
    void draw_uniformCatmullRom(QPainterPath & curve) const;

    /**
     * Use a centripetal Catmull-Rom spline. Approximate it using line
     * segments.
     * 
     * These splines are defined with four control points and generate a spline
     * that connects the two middle points. If used in a sequence, the
     * direction does not change between segments
     * 
     * Centripetal Catmull-Rom splines use an alpha (sometimes called tension)
     * value of 0.5. This means loops and cusps are generally avoided in the
     * curve.
     * 
     * For more information on these curves, look here;
     * https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline
     */
    void draw_centripetalCatmullRom(QPainterPath & curve) const;

public:
    /**
     * Make a transition curve given a set of points to put the curve through.
     */
	GedDesTransCurve(QList<QPointF> points, CurveType type) :
		points(points),
		type(type) {}

    /**
     * Gets the curve that this GedDesTransCurve represents as a QPainterPath
     */
    QPainterPath getCurve() const;

    /**
     * Gets the arrow associated with this transition curve
     */
    QPainterPath getArrow() const;

};

}
