/*Copyright (C) 2010-2023 Duncan Deveaux

This file is part of Hikou no mizu.

Hikou no mizu is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Hikou no mizu is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Hikou no mizu.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef DEF_CALLBACK_ANIMATION
#define DEF_CALLBACK_ANIMATION

#include "Animation.hpp"

/// Tools to enable/disable lag mitigation for all animation callbacks
/// Typically enabled for networked game and disabled for local games
namespace AnimationLag
{
    void enableLagMitigation();
    void disableLagMitigation();
}

/// Abstract class to extend in order to catch animation-related callbacks
class AnimationCallbackReceiver
{
    public:
        virtual ~AnimationCallbackReceiver() {}
        virtual void stepImpactCallback() = 0;
};

/// An animation which produces callback at pre-defined times
class CallbackAnimation : public Animation
{
    public:
        CallbackAnimation();

        void setReceiver(AnimationCallbackReceiver *receiver);
        void addStepImpactCallback(std::size_t frameIx);

        void reset() override;
        void goToTime(float time) override;

        /// Resets the animation time to \p time ms, does not apply callbacks
        /// Useful to apply a networked server update to a client animation
        void forceTime(float time);

    private:
        AnimationCallbackReceiver *m_receiver;
        std::vector<std::size_t> m_stepImpactCallbacks;

        /// Furthest frame index reached since the animation was started
        /// Used to avoid triggering the same callback multiple times for the
        /// same animation playback (as the animation will be pushed slightly
        /// back in time at each incoming server update)
        std::size_t m_furthestFrame;
};

#endif
