/*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_ATTACK
#define DEF_ATTACK

#include "Animation/CallbackAnimation.hpp"
#include "Structs/Box.hpp"
#include <vector>
#include <string>

class Player;

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

struct HitBox
{
    HitBox() : time(0.f), factor(1.f) {}

    HitBox(const Box &hitBox, float hitTime, float hitFactor) :
    box(hitBox), time(hitTime), factor(hitFactor)
    {

    }

    Box box;
    float time;
    float factor; ///< Strength factor
};

/// Association of an animation with timed hitboxes and sound effects
class Attack
{
    public:
        Attack();

        /// Advances the attack by \p frameTime ms and applies any hits
        void update(float frameTime);

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

        /// Resets the attack time to 0, does not apply hits
        /// Useful to stop the attack suddenly, e.g, in case of KO
        void reset();

        bool ready();
        void setPlayer(Player &player);

        void addHitBox(const HitBox &hitBox);
        void scaleHitBoxes(float scale);

        void addSoundEffect(float time, const std::string &soundEffect);

        void setAnimation(const CallbackAnimation &animation);
        const CallbackAnimation &getAnimation() const;

        float getCurrentTime() const;
        std::vector<HitBox> getHitBoxes() const;

    private:
        /// Trigger callbacks to play any sound effects whose time
        /// is located between \p timeBegin and \p timeUpdated
        void playSoundEffects(float timeBegin, float timeUpdated);

        CallbackAnimation m_animation;
        std::vector<HitBox> m_hitBoxes;
        std::vector< std::pair<float, std::string> > m_soundEffects;

        Player *m_player;

        /// Furthest time point reached since the attack was reset.
        /// 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)
        float m_furthestTime;
};

#endif
