// Copyright 2024 Pixar
//
// Licensed under the terms set forth in the LICENSE.txt file available at
// https://openusd.org/license.
//
// Modified by Jeremy Retailleau.

#include "./types.h"
#include "./spline.h"
#include <pxr/tf/type.h>
#include <pxr/tf/enum.h>
#include <pxr/tf/registryManager.h>

namespace pxr {


TF_REGISTRY_FUNCTION(pxr::TfEnum)
{
    TF_ADD_ENUM_NAME(TsInterpValueBlock, "Value Block");
    TF_ADD_ENUM_NAME(TsInterpHeld, "Held");
    TF_ADD_ENUM_NAME(TsInterpLinear, "Linear");
    TF_ADD_ENUM_NAME(TsInterpCurve, "Curve");

    TF_ADD_ENUM_NAME(TsCurveTypeBezier, "Bezier");
    TF_ADD_ENUM_NAME(TsCurveTypeHermite, "Hermite");

    TF_ADD_ENUM_NAME(TsExtrapValueBlock, "Value Block");
    TF_ADD_ENUM_NAME(TsExtrapHeld, "Held");
    TF_ADD_ENUM_NAME(TsExtrapLinear, "Linear");
    TF_ADD_ENUM_NAME(TsExtrapSloped, "Sloped");
    TF_ADD_ENUM_NAME(TsExtrapLoopRepeat, "Loop Repeat");
    TF_ADD_ENUM_NAME(TsExtrapLoopReset, "Loop Reset");
    TF_ADD_ENUM_NAME(TsExtrapLoopOscillate, "Loop Oscillate");

    TF_ADD_ENUM_NAME(TsAntiRegressionNone, "None");
    TF_ADD_ENUM_NAME(TsAntiRegressionContain, "Contain");
    TF_ADD_ENUM_NAME(TsAntiRegressionKeepRatio, "Keep Ratio");
    TF_ADD_ENUM_NAME(TsAntiRegressionKeepStart, "Keep Start");

    TF_ADD_ENUM_NAME(TsSourcePreExtrap, "Pre Extrapolation");
    TF_ADD_ENUM_NAME(TsSourcePreExtrapLoop, "Pre Extrapolation Loop");
    TF_ADD_ENUM_NAME(TsSourceInnerLoopPreEcho, "Pre Inner Loop");
    TF_ADD_ENUM_NAME(TsSourceInnerLoopProto, "Inner Loop Prototype");
    TF_ADD_ENUM_NAME(TsSourceInnerLoopPostEcho, "Post Inner Loop");
    TF_ADD_ENUM_NAME(TsSourceKnotInterp, "Knot Interpolation");
    TF_ADD_ENUM_NAME(TsSourcePostExtrap, "Post Extrapolation");
    TF_ADD_ENUM_NAME(TsSourcePostExtrapLoop, "Post Extrapolation Loop");
}

bool TsLoopParams::operator==(const TsLoopParams &other) const
{
    return
        protoStart == other.protoStart
        && protoEnd == other.protoEnd
        && numPreLoops == other.numPreLoops
        && numPostLoops == other.numPostLoops
        && valueOffset == other.valueOffset;
}

bool TsLoopParams::operator!=(const TsLoopParams &other) const
{
    return !(*this == other);
}

GfInterval TsLoopParams::GetPrototypeInterval() const
{
    return GfInterval(
        protoStart, protoEnd,
        /* minClosed = */ true, /* maxClosed = */ false);
}

GfInterval TsLoopParams::GetLoopedInterval() const
{
    const TsTime protoSpan = protoEnd - protoStart;
    return GfInterval(
        protoStart - numPreLoops * protoSpan,
        protoEnd + numPostLoops * protoSpan);
}

TsExtrapolation::TsExtrapolation() = default;

TsExtrapolation::TsExtrapolation(TsExtrapMode modeIn)
    : mode(modeIn)
{
}

bool TsExtrapolation::operator==(const TsExtrapolation &other) const
{
    return
        mode == other.mode
        && (mode != TsExtrapSloped || slope == other.slope);
}

bool TsExtrapolation::operator!=(const TsExtrapolation &other) const
{
    return !(*this == other);
}

bool TsExtrapolation::IsLooping() const
{
    return (mode >= TsExtrapLoopRepeat && mode <= TsExtrapLoopOscillate);
}

////////////////////////////////////////////////////////////////////////////////
// TEMPLATE IMPLEMENTATIONS

// Instantiate the supported samples classes
#define TS_SAMPLE_EXPLICIT_INST(unused, tuple)                          \
    template class TS_API                                               \
        TsSplineSamples< TS_SPLINE_VALUE_CPP_TYPE(tuple) >;             \
    template class TS_API                                               \
        TsSplineSamplesWithSources< TS_SPLINE_VALUE_CPP_TYPE(tuple) >;

TF_PP_SEQ_FOR_EACH(TS_SAMPLE_EXPLICIT_INST, ~, TS_SPLINE_SAMPLE_VERTEX_TYPES)
#undef TS_SAMPLE_EXTERN_IMPL


}  // namespace pxr
