#include "sprite.h"

Sprite::Sprite(SDL_Renderer *renderer, SDL_Surface *surface)
{
    Texture = SDL_CreateTextureFromSurface(renderer, surface);
    dstrect = { 0, 0, surface->w, surface->h };
}

Sprite::~Sprite()
{
    SDL_DestroyTexture(Texture);
}

void Sprite::draw(SDL_Renderer* renderer, std::string frame, bool autoRect, bool flip)
    {
    if (frames.find(frame) == frames.end())
    {
        printf("Frame not found\n");
        return;
    }
    if (autoRect)
    {
        dstrect = { dstrect.x, dstrect.y, frames[frame].w, frames[frame].h };
    }
    SDL_SetTextureAlphaMod(Texture, 255);
    dstrect.w *= scale.x;
    dstrect.h *= scale.y;
    SDL_RenderCopyEx(renderer, Texture, &frames[frame], &dstrect, angle, NULL, flip ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE);
}

void Sprite::addFrame(std::string name, SDL_Rect rect)
{
    frames[name] = rect;
}

void Sprite::setPos(int_vec2 position)
{
    dstrect.x = position.x;
    dstrect.y = position.y;
}

void Sprite::move(int_vec2 position)
{
    dstrect.x += position.x;
    dstrect.y += position.y;
}

int_vec2 Sprite::getSize(std::string frame)
{
    size = { frames[frame].w, frames[frame].h };
    return size;
}

void Sprite::autorect(std::string frame)
{
    dstrect = { dstrect.x, dstrect.y, frames[frame].w, frames[frame].h };
}


Animation::Animation(std::map<std::string, SDL_Rect> frames, Sprite* sprite, int frameDuration)
{
    this->sprite = sprite;
    this->frameDuration = frameDuration;

    for (auto const& x : frames)
    {
        this->frames.push_back(x.first);
        this->sprite->addFrame(x.first, x.second);
    }
    currentFrameName = this->frames[0];
}

void Animation::reset()
{
    frameIndex = 0;
    frameDirection = 1;
    currentFrameName = frames[0];
    end = false;
}

void Animation::update()
{
    frameCounter++;
    end = false;
    if (frameCounter >= frameDuration)
    {
        frameCounter = 0;
        if (pingpong)
        {
            frameIndex += frameDirection;
            if (frameIndex >= frames.size() - 1 || frameIndex <= 0)
            {
                if (!loop)
                {
                    frameDirection = 0;
                    end = true;
                } else { 
                    frameDirection *= -1;
                }
            }
        }
        else
        {
            frameIndex++;
            if (frameIndex >= frames.size())
            {
                if (!loop)
                {
                    frameIndex = frames.size() - 1;
                    end = true;
                } else {
                    frameIndex = 0;
                }
            }
        }
        

        currentFrameName = frames[frameIndex];
    }
}

void Animation::draw(SDL_Renderer* renderer, bool autoRect, bool flip)
{
    sprite->draw(renderer, currentFrameName, autoRect, flip);
}

AnimationManager::AnimationManager(Sprite* sprite)
{
    this->sprite = sprite;
}

void AnimationManager::addAnimation(std::string name, std::map<std::string, SDL_Rect> frames, int frameDuration, bool flip, bool autoRect, bool loop, bool pingpong)
{
    animations[name] = new Animation(frames, sprite, frameDuration);
    this->flip[name] = flip;
    this->autoRect[name] = autoRect;
    animations[name]->loop = loop;
    animations[name]->pingpong = pingpong;
}

void AnimationManager::setAnimation(std::string name)
{
    if (!playing) {
        currentAnimation = name;
    }
}

void AnimationManager::update()
{
    animations[currentAnimation]->update();
    if (playing && animations[currentAnimation]->end)
    {
        playing = false;
    }
}

void AnimationManager::draw(SDL_Renderer* renderer)
{
    animations[currentAnimation]->draw(renderer, autoRect[currentAnimation], flip[currentAnimation]);
}

void AnimationManager::playAnimation(std::string name)
{
    if (!playing) {
        animations[name]->loop = false;
        animations[name]->reset();
        setAnimation(name);
        playing = true;
    }
}