/********************\
|  Copyright 2024,   |
|       Ulysse Cura  |
\********************/

///////////////////////////////////////////////////////
//                                                   //
//   Système d'animation pour l'ECS, peut controller //
// tout ce qui est en rapport avec des animations.   //
//                                                   //
///////////////////////////////////////////////////////

#ifndef ANIMATION_HPP
#define ANIMATION_HPP

#include <algorithm>
#include <vector>
#include "ECS.hpp"
#include "../Game.hpp"
#include "SpriteComponent.hpp"

using std::string, std::reverse, std::vector;

class AnimationSystem : public Component {
  public:
    AnimationSystem() = default;
    AnimationSystem(int nbF, int currentF, int frameD, bool playAnim) : playAnimation(playAnim), frameDelay(frameD), currentFrame(currentF), m_nbFrames(nbF)
    {}

    void init() override
    {
        m_sprite = &entity->getComponent<SpriteComponent>();

        m_createFramesClips();
    }

    void update() override
    {
        if(playAnimation)
        {
            m_frameTimer++;

            if(m_frameTimer >= frameDelay)
            {
                m_frameTimer = 0;

                if(reverse)
                {
                    currentFrame = m_nbFrames - 1 - (m_nbFrames - 1 - currentFrame + 1) % m_nbFrames;
                    if(!loop && !currentFrame) playAnimation = false;
                }
                else
                {
                    currentFrame = (currentFrame + 1) % m_nbFrames;
                    if(!loop && currentFrame == m_nbFrames - 1) playAnimation = false;
                }
            }

            m_sprite->setSrcRect(m_frames[currentFrame]);
        }
    }

    void changeAnimation(const string &path, int nbF)
    {
        currentFrame = 0;

        m_sprite->setTexture(path);
        m_nbFrames = nbF;
        m_createFramesClips();

        update();
    }

    void changeAnimation(const string &path, int nbF, int frameD)
    {
        changeAnimation(path, nbF);

        frameDelay = frameD;
    }

    bool playAnimation {true};
    bool loop {true};
    bool reverse {false};

    int frameDelay {0};
    int currentFrame {0};

  private:
    void m_createFramesClips()
    {
        m_frames.clear();

        for (int framePos {0}; framePos < m_nbFrames; framePos++) {
            SDL_Rect frame;

            frame.x = framePos * m_sprite->getSrcRect().w;
            frame.y = 0;
            frame.w = m_sprite->getSrcRect().w;
            frame.h = m_sprite->getSrcRect().h;

            m_frames.push_back(frame);
        }
    }

    SpriteComponent *m_sprite;
    vector<SDL_Rect> m_frames;

    int m_nbFrames {1};
    int m_frameTimer {0};
};

#endif