// qeasingcurve.sip generated by MetaSIP
//
// This file is part of the QtCore Python extension module.
//
// Copyright (c) 2024 Riverbank Computing Limited <info@riverbankcomputing.com>
// 
// This file is part of PyQt5.
// 
// This file may be used under the terms of the GNU General Public License
// version 3.0 as published by the Free Software Foundation and appearing in
// the file LICENSE included in the packaging of this file.  Please review the
// following information to ensure the GNU General Public License version 3.0
// requirements will be met: http://www.gnu.org/copyleft/gpl.html.
// 
// If you do not wish to use this file under the terms of the GPL version 3.0
// then you may purchase a commercial license.  For more information contact
// info@riverbankcomputing.com.
// 
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.


class QEasingCurve /TypeHintIn="Union[QEasingCurve, QEasingCurve.Type]"/
{
%TypeHeaderCode
#include <qeasingcurve.h>
%End

%TypeCode
// The EasingFunction callback doesn't provide a context so we support a fixed
// number of different functions.

const int ec_nr_custom_types = 10;

struct ec_custom_type {
    PyObject *py_func;
    QEasingCurve::EasingFunction func;
};

static qreal ec_call(int ec, qreal v);

static qreal ec_func_0(qreal v)
{
    return ec_call(0, v);
}

static qreal ec_func_1(qreal v)
{
    return ec_call(1, v);
}

static qreal ec_func_2(qreal v)
{
    return ec_call(2, v);
}

static qreal ec_func_3(qreal v)
{
    return ec_call(3, v);
}

static qreal ec_func_4(qreal v)
{
    return ec_call(4, v);
}

static qreal ec_func_5(qreal v)
{
    return ec_call(5, v);
}

static qreal ec_func_6(qreal v)
{
    return ec_call(6, v);
}

static qreal ec_func_7(qreal v)
{
    return ec_call(7, v);
}

static qreal ec_func_8(qreal v)
{
    return ec_call(8, v);
}

static qreal ec_func_9(qreal v)
{
    return ec_call(9, v);
}

static ec_custom_type ec_custom_types[ec_nr_custom_types] = {
    {0, ec_func_0},
    {0, ec_func_1},
    {0, ec_func_2},
    {0, ec_func_3},
    {0, ec_func_4},
    {0, ec_func_5},
    {0, ec_func_6},
    {0, ec_func_7},
    {0, ec_func_8},
    {0, ec_func_9},
};

static qreal ec_call(int ec, qreal v)
{
    PyObject *res_obj;
    qreal res = 0.0;

    SIP_BLOCK_THREADS

    res_obj = PyObject_CallFunction(ec_custom_types[ec].py_func, (char *)"(d)", (double)v);

    if (res_obj)
    {
        PyErr_Clear();

        res = PyFloat_AsDouble(res_obj);
        Py_DECREF(res_obj);

        if (PyErr_Occurred())
            res_obj = 0;
    }

    if (!res_obj)
        pyqt5_err_print();

    SIP_UNBLOCK_THREADS

    return res;
}
%End

%ConvertToTypeCode
// Allow a QEasingCurve::Type whenever a QEasingCurve is expected.

if (sipIsErr == NULL)
{
    if (sipCanConvertToType(sipPy, sipType_QEasingCurve, SIP_NO_CONVERTORS))
        return 1;

    if (PyObject_TypeCheck(sipPy, sipTypeAsPyTypeObject(sipType_QEasingCurve_Type)))
        return 1;

    return 0;
}

if (sipCanConvertToType(sipPy, sipType_QEasingCurve, SIP_NO_CONVERTORS))
{
    *sipCppPtr = reinterpret_cast<QEasingCurve *>(sipConvertToType(sipPy, sipType_QEasingCurve, sipTransferObj, SIP_NO_CONVERTORS, 0, sipIsErr));

    return 0;
}

*sipCppPtr = new QEasingCurve((QEasingCurve::Type)SIPLong_AsLong(sipPy));

return sipGetState(sipTransferObj);
%End

public:
    enum Type
    {
        Linear,
        InQuad,
        OutQuad,
        InOutQuad,
        OutInQuad,
        InCubic,
        OutCubic,
        InOutCubic,
        OutInCubic,
        InQuart,
        OutQuart,
        InOutQuart,
        OutInQuart,
        InQuint,
        OutQuint,
        InOutQuint,
        OutInQuint,
        InSine,
        OutSine,
        InOutSine,
        OutInSine,
        InExpo,
        OutExpo,
        InOutExpo,
        OutInExpo,
        InCirc,
        OutCirc,
        InOutCirc,
        OutInCirc,
        InElastic,
        OutElastic,
        InOutElastic,
        OutInElastic,
        InBack,
        OutBack,
        InOutBack,
        OutInBack,
        InBounce,
        OutBounce,
        InOutBounce,
        OutInBounce,
        InCurve,
        OutCurve,
        SineCurve,
        CosineCurve,
        BezierSpline,
        TCBSpline,
        Custom,
    };

    QEasingCurve(QEasingCurve::Type type = QEasingCurve::Linear);
    QEasingCurve(const QEasingCurve &other);
    ~QEasingCurve();
    bool operator==(const QEasingCurve &other) const;
    bool operator!=(const QEasingCurve &other) const;
    qreal amplitude() const;
    void setAmplitude(qreal amplitude);
    qreal period() const;
    void setPeriod(qreal period);
    qreal overshoot() const;
    void setOvershoot(qreal overshoot);
    QEasingCurve::Type type() const;
    void setType(QEasingCurve::Type type);
    void setCustomType(SIP_PYCALLABLE func /TypeHint="Callable[[float], float]"/);
%MethodCode
        int i;
        ec_custom_type *ct;
        
        for (i = 0; i < ec_nr_custom_types; ++i)
        {
            ct = &ec_custom_types[i];
        
            if (!ct->py_func || ct->py_func == a0)
                break;
        }
        
        if (i == ec_nr_custom_types)
        {
            PyErr_Format(PyExc_ValueError, "a maximum of %d different easing functions are supported", ec_nr_custom_types);
            sipError = sipErrorFail;
        }
        else
        {
            if (!ct->py_func)
            {
                ct->py_func = a0;
                Py_INCREF(a0);
            }
        
            sipCpp->setCustomType(ct->func);
        }
%End

    SIP_PYCALLABLE customType() const /TypeHint="Callable[[float], float]"/;
%MethodCode
        QEasingCurve::EasingFunction func = sipCpp->customType();
        
        sipRes = Py_None;
        
        if (func)
        {
            for (int i = 0; i < ec_nr_custom_types; ++i)
            {
                if (ec_custom_types[i].func == func)
                {
                    sipRes = ec_custom_types[i].py_func;
                    break;
                }
            }
        }
        
        Py_INCREF(sipRes);
%End

    qreal valueForProgress(qreal progress) const;
    void swap(QEasingCurve &other /Constrained/);
    void addCubicBezierSegment(const QPointF &c1, const QPointF &c2, const QPointF &endPoint);
    void addTCBSegment(const QPointF &nextPoint, qreal t, qreal c, qreal b);
    QVector<QPointF> toCubicSpline() const;
};

QDataStream &operator<<(QDataStream &, const QEasingCurve & /Constrained/) /ReleaseGIL/;
QDataStream &operator>>(QDataStream &, QEasingCurve & /Constrained/) /ReleaseGIL/;
