#pragma once

#include "kernel/texture.hpp"
#include "render.h"
#include <vector>

namespace render::sprite
{

struct TextureAtlasNode {
    float angle, _angle;
    vec2f scale;
    vec2f center, _center;
    vec2f rotMatrix[4];
    vec2f pos, size;
    std::string name;

    inline bool operator!=(const TextureAtlasNode &a) const noexcept
    {
        return a.angle != angle ||
               a.scale != scale ||
               a.center != center ||
               a.pos != pos ||
               a.size != size;
    }
};

class TextureAtlas;

class Icon
{
    friend class TextureAtlas;

public:
    const TextureAtlas *parent() const;

    vec4f color;
    vec2f size;
    vec2f scale;
    vec2f center;
    float angle;

    Icon();
    void draw(const vec2f &) noexcept;
    void draw(const vec2f &) const noexcept;
    const vec2f *getVertices() const noexcept;

    Icon &operator=(const TextureAtlasNode &);

private:
    const TextureAtlas *_parent;

    float _angle;
    vec2f _center;
    vec2f _rotMatrix[6];
    vec2f _pos, _isize, _size;
};

class TextureAtlas
{
private:
    kernel::Texture *texture;
    vec2<int> _size;
public:
    TextureAtlas(const std::string &path);
    ~TextureAtlas();

    void draw(const vec2f &, Icon &) const noexcept;
    void draw(const vec2f &, const Icon &) const noexcept;

    void getIcon(const std::string &, Icon &) const noexcept;

    int getNodeId(const std::string &) const noexcept;
    uint32_t getNodesCount() const noexcept;

    vec4f getTexCoord(uint32_t) const;
    inline TextureAtlasNode &operator[](uint32_t a) { return elements.at(a); }

private:
    std::vector<TextureAtlasNode> elements;
    void mathRotate(TextureAtlasNode &) noexcept;
    void mathRotate(Icon &) const noexcept;
};

} // namespace render::sprite

