#pragma once

#include <cstdint>
#include <vector>

#include "Camera.h"
#include "DataTypes.h"

struct SDL_Window;
struct SDL_Surface;

namespace dae {
    class Texture;

    struct Mesh;

    class Timer;

    class Scene;

    class Renderer final {
    public:
        Renderer(SDL_Window *pWindow);

        ~Renderer();

        Renderer(const Renderer &) = delete;

        Renderer(Renderer &&) noexcept = delete;

        Renderer &operator=(const Renderer &) = delete;

        Renderer &operator=(Renderer &&) noexcept = delete;

        void Update(Timer *pTimer);

        void Render();

        bool SaveBufferToImage() const;

        void
        VertexTransformationFunction(const std::vector<Vertex> &vertices_in, std::vector<Vertex> &vertices_out) const;

    private:
        SDL_Window *m_pWindow{};

        Uint8 r{100};
        Uint8 g{100};
        Uint8 b{100};
        Uint32 m_ClearColor{ Uint32(255 << 24) + Uint32(r << 16) + Uint32(g << 8) + Uint32(b) };

        SDL_Surface* m_pFrontBuffer{ nullptr };
        SDL_Surface* m_pBackBuffer{ nullptr };
        uint32_t* m_pBackBufferPixels{};

        float m_aspectRatio{};

        std::vector<Vertex> m_verticiesWorld{
                //Triangle 0
                {{0.f,2.f,0.f}, {1,0,0}},
                {{1.5f,-1.f,0.f}, {1,0,0}},
                {{-1.5f,-1.f,0.f}, {1,0,0}},

                //Triangle 1
                {{0.f,4.f,2.f}, {1,0,0}},
                {{3.f,-2.f,2.f}, {0,1,0}},
                {{-3.f,-2.f,2.f}, {0,0,1}}
        };

        std::vector<Mesh> m_meshesWorldList
                {
                        Mesh
                                {
                                        {
                                                Vertex{ {-3,  3, -2 }, { 1, 1, 1 }, },
                                                Vertex{ { 0,  3, -2 }, { 1, 1, 1 }, },
                                                Vertex{ { 3,  3, -2 }, { 1, 1, 1 }, },
                                                Vertex{ {-3,  0, -2 }, { 1, 1, 1 }, },
                                                Vertex{ { 0,  0, -2 }, { 1, 1, 1 }, },
                                                Vertex{ { 3,  0, -2 }, { 1, 1, 1 }, },
                                                Vertex{ {-3, -3, -2 }, { 1, 1, 1 }, },
                                                Vertex{ { 0, -3, -2 }, { 1, 1, 1 }, },
                                                Vertex{ { 3, -3, -2 }, { 1, 1, 1 }, }
                                        },
                                        {
                                                3, 0, 1,	1, 4, 3,	4, 1 ,2,
                                                2, 5, 4,	6, 3, 4,	4, 7, 6,
                                                7, 4, 5,	5, 8, 7
                                        },
                                        PrimitiveTopology::TriangleList
                                }
                };

        std::vector<Mesh> m_meshesWorldStrip
                {
                        Mesh
                                {
                                        {
                                                Vertex{ {-3,  3, -2 }, { 1, 1, 1 }, },
                                                Vertex{ { 0,  3, -2 }, { 1, 1, 1 }, },
                                                Vertex{ { 3,  3, -2 }, { 1, 1, 1 }, },
                                                Vertex{ {-3,  0, -2 }, { 1, 1, 1 }, },
                                                Vertex{ { 0,  0, -2 }, { 1, 1, 1 }, },
                                                Vertex{ { 3,  0, -2 }, { 1, 1, 1 }, },
                                                Vertex{ {-3, -3, -2 }, { 1, 1, 1 }, },
                                                Vertex{ { 0, -3, -2 }, { 1, 1, 1 }, },
                                                Vertex{ { 3, -3, -2 }, { 1, 1, 1 }, }
                                        },
                                        {
                                                3, 0, 4, 1, 5, 2,
                                                2, 6,
                                                6, 3, 7, 4, 8, 5
                                        },
                                        PrimitiveTopology::TriangleStrip
                                }
                };

        std::vector<Vertex> m_verticies_screenSpace{};

        float* m_pDepthBufferPixels{};

        Camera m_Camera{};

        int m_Width{};
        int m_Height{};
    };
}
