/******************************************************************************
*	File		-	simple_render_scene.cpp
*	Author		-	Joey Pollack
*	Date		-	2021/10/27 (y/m/d)
*	Mod Date	-	2021/10/27 (y/m/d)
*	Description	-	Displays a simple scene that tests basic render features.
******************************************************************************/

#include "simple_render_scene.h"
#include <core/core.h>
#include <gui/gui.h>
#include <utils/helpers.h>
#include <utils/logger.h>
#include <renderer/texture.h>
#include <renderer/frame_buffer.h>
#include <renderer/orthographic_camera.h>
#include <input/input_manager.h>
#include <utils/stb/std_image_write.h>
#include <utils/stb/stb_image.h>

#include <glm/gtc/matrix_transform.hpp>

#include <thread>        
#include <chrono> 

#include <cstdlib>
#include <ctime>

namespace lunarium
{
    SimpleRenderScene::SimpleRenderScene(uint32_t logCat)
        : BaseScene(logCat), mTestMode(TestMode::Basic), mShapeMode(ShapeMode::Lines), mFrameTime(0.0), mNumFrames(0), mpTestImageLoad3(nullptr),
        mEllipseResolution(50), mEllipseRadii{ 100.0f, 100.0f }, mTestMap({ 16, 16 })
    {
        srand((u32)time(0));
    }

    SimpleRenderScene::~SimpleRenderScene()
    {
        delete mpTestImageLoad;
    }

    void SimpleRenderScene::OnLoad()
    {
        Logger::Info(mLogCat, "Running Simple Render Test Scene");
        mTextBoxWidth = 500;


        // Currently the full default window size
        mImageSize.Width = 1280;
        mImageSize.Height = 720;

        // Create the render textures
        mFrameBufferOne = FrameBuffer::Create(mImageSize.Width, mImageSize.Height); //Core::Graphics().CreateRenderTexture(mImageSize.Width, mImageSize.Height, 4);
        mFrameBufferTwo = FrameBuffer::Create(1024, 1024); //Core::Graphics().CreateRenderTexture(1024, 1024, 4);

        // Load test image
        LoadImages();

        GenerateQuads();
        GenerateLines();

        mParentPos = glm::vec3(300.0f, 300.0f, 0.0f);
        mChildPos = glm::vec3(250.0f, 0.0f, 0.0f);
        mChild2Pos = glm::vec3(100.f, 100.0f, 0.0f);
        mParentAngle = 0.0f;
        mChildAngle = 0.0f;
        mChild2Angle = 0.0f;


        mParentPos2 = glm::vec3(700.0f, 200.0f, 0.0f);
        mChildPos2 = glm::vec3(-300.0f, 50.0f, 0.0f);

        mParentPos3 = glm::vec3(200.0f, 600.0f, 0.0f);
        mChildPos3 = glm::vec3(150.0f, 100.0f, 0.0f);
        mChildPos3_2 = glm::vec3(150.0f, 0.0f, 0.0f);

        angle = 0.0f;
        box_angle = 0.0f;
        mTextDebugPosX = 200;
        mSubTex = Rectangle::MakeFromTopLeft(0, 0, 256, 256);
    }

    void SimpleRenderScene::OnTick(double delta)
    {
        if (Core::Input().IsKeyDown(KeyCode::ESCAPE))
        {
            Core::GetInstance().SignalShutdown();
        }

        // Textbox size adjustment
        if (Core::Input().IsKeyDown(KeyCode::LEFT))
        {
            if (mTestMode == TestMode::Basic)
                mTextBoxWidth -= 10;

            if (mTestMode == TestMode::String)
                mTextDebugPosX -= 10;
        }

        if (Core::Input().IsKeyDown(KeyCode::RIGHT))
        {
            mTextBoxWidth += 10;
            if (mTestMode == TestMode::Basic)
                mTextBoxWidth += 10;

            if (mTestMode == TestMode::String)
                mTextDebugPosX += 10;
        }

        if (Core::Input().IsKeyDown(KeyCode::R))
        {
            mSrcWidth -= 10.0f;
            mSrcHeight -= 10.0f;
        }

        if (Core::Input().IsKeyDown(KeyCode::F))
        {
            mSrcWidth += 10.0f;
            mSrcHeight += 10.0f;
        }

        mTextBoxWidth = Math::ClampI(mTextBoxWidth, 20, 500);

        // Image Size adjustment
        if (Core::Input().IsKeyDown(KeyCode::DOWN))
        {
            mImageSize.Width -= 10;
            mImageSize.Height -= 10;
        }

        if (Core::Input().IsKeyDown(KeyCode::UP))
        {
            mImageSize.Width += 10;
            mImageSize.Height += 10;
        }

        if (Core::Input().IsKeyDown(KeyCode::PAGE_UP))
        {
            angle += 0.1f;
        }

        if (Core::Input().IsKeyDown(KeyCode::PAGE_DOWN))
        {
            angle -= 0.1f;
        }

        if (Core::Input().IsKeyPressed(KeyCode::Q))
        {
           DoFrameBufferSaveTest();
        }

        if (Core::Input().IsKeyPressed(KeyCode::T))
        {
            Texture* dt = Core::Graphics().GetTextDebugTexture();
            stbi_flip_vertically_on_write(0);
            stbi_write_png("lunarium_text_test.png", dt->GetWidth(), dt->GetHeight(), 1, 
                            dt->GetPixels(), dt->GetWidth() * 1);
            Logger::Info(mLogCat, "Saved Text test image");

        }

        if (Core::Input().IsKeyPressed(KeyCode::F))
        {
            flip_image = !flip_image;
        }

        mImageSize.Width = Math::ClampI(mImageSize.Width, 320, 1280);
        mImageSize.Height = Math::ClampI(mImageSize.Height, 180, 720);

        // Render to texture testing
        mFrameBufferOne->Bind();
        OrthographicCamera cam(Vec2f{0.0f, 0.0f}, Sizef{(float)mFrameBufferOne->GetTexture()->GetWidth(), (float)mFrameBufferOne->GetTexture()->GetHeight()});
        Renderer2D& g = Core::Graphics();
        g.BeginDraw(&cam);

        g.DrawQuad(Rectangle(300, 300, 150, 150), Color::Red());
        g.DrawQuad(Rectangle(200, 300, 100, 100), Color(0.2f, 0.5f, 0.4f, 1.0f), nullptr, 45.0f);
        //g.DrawFilledEllipse(glm::vec2(600, 300), glm::vec2(100, 150), Color(1.0f, 0.0f, 1.0f, 1.0f), 100);
        g.DrawString("This is a test of the text renderer!", Rectangle::MakeFromTopLeft(100, 200, mTextBoxWidth, 300), 
                                Color(0.0f, 1.0f, 1.0f, 1.0f), 0.5f);
        g.EndDraw();
        mpRenderedImage = mFrameBufferOne->GetTexture();
        if (flip_image) mpRenderedImage->FlipVertically();
        mFrameBufferOne->Unbind();

        box_angle += 0.01f;
        int w, h;
        Core::MainWindow().GetFramebufferSize(&w, &h);
        OrthographicCamera main_cam(Vec2f { 0.0f, 0.0f }, Sizef { (float)w, (float)h });
        Core::GUI().NewFrame();
        mTimer.Reset();
        Core::Graphics().ResetFrameStats();
        Core::Graphics().BeginDraw(&main_cam);

        switch (mTestMode)
        {
            case TestMode::Basic: RenderScene(Core::Graphics()); break;
            case TestMode::Stress: RenderBatchStressTest(Core::Graphics()); break;
            case TestMode::String: RenderStringTest(Core::Graphics()); break;
            case TestMode::Shapes: RenderShapesTest(Core::Graphics()); break;
            case TestMode::TileMap: RenderTileMapTest(Core::Graphics()); break;
            case TestMode::Parent: RenderParentTest(Core::Graphics()); break;
        }
        


        Core::Graphics().EndDraw(); // Graphics end draw must happen before GUI end frame
        DrawStatsGUI();
        Core::GUI().EndFrame();
        Core::MainWindow().SwapBuffers();
        mFrameTime += mTimer.GetElapsedSeconds();
        mNumFrames++;
        mRenderStats = Core::Graphics().GetFrameStats();
        //std::this_thread::sleep_for (std::chrono::seconds(2));
    }

    /////////////////////////////////////////////////////////////////////
    //				RENDER METHODS      RENDER METHODS
    /////////////////////////////////////////////////////////////////////
    void SimpleRenderScene::RenderScene(Renderer2D& g)
    {
        
        Rectangle image_rect = Rectangle::MakeFromTopLeft(0.0f, 0.0f, (float)mpRenderedImage->GetWidth(), (float)mpRenderedImage->GetHeight());
        g.DrawQuad(image_rect, Color::White(), mpRenderedImage, angle);

        //g.DrawQuad(Rectangle::MakeFromTopLeft(0.0f, 0.0f, (float)mImageSize.Width, (float)mImageSize.Height), Color(1.0f, 1.0f, 0.0f, 1.0f), nullptr, angle);

        g.DrawQuad(Rectangle(100, 100, 16, 16), Color::White(), mpTestImageLoad2, 0.0f, mSubTex);
        g.DrawSprite(mpTestImageLoad2, glm::vec2(600, 200), Rectangle::MakeFromTopLeft(255, 255, 255, 255));

        //g->DrawImage(*mpTestImageLoad, glm::vec2(0.0f, 0.0f), Color::White());
        //Rectangle src = Rectangle::MakeFromTopLeft(0.0f, 0.0f, (float)mpTestImageLoad->GetWidth(), (float)mpTestImageLoad->GetHeight());
        //Rectangle src = Rectangle::MakeFromTopLeft(0.0f, 0.0f, mSrcWidth, mSrcHeight);
        Rectangle src = Rectangle::MakeFromTopLeft(0.0f, 0.0f, 16, 16);
        Rectangle dest = Rectangle::MakeFromTopLeft(900.0f, 350.0f, 256.0f, 256.0f);
        g.DrawQuad(dest, Color::White(), mpTestImageLoad, 0.0f, src);
        
        // g->DrawImage(*mpTestImageLoad, src,
        //             dest, Color(1.0f, 1.0f, 1.0f, 0.8f));
    }
    
    void SimpleRenderScene::RenderBatchStressTest(Renderer2D& g)
    {
        for (int i = 0; i < mNumQuadsToRender; i++)
        {   
            Texture* t = mUseTextures ? mQuadTexures[i] : nullptr;
            g.DrawQuad(mQuads[i], mQuadColors[i], t, box_angle + (i / 10.0f));
        }

    }

    
    void SimpleRenderScene::RenderStringTest(Renderer2D& g)
    {
        Texture* dt = g.GetTextDebugTexture();
        g.DrawQuad(Rectangle(mTextDebugPosX, 300, dt->GetWidth() , dt->GetHeight() ), Color::Blue(), dt);
        g.DrawQuad(Rectangle(200, 100, 32, 32), Color(0.25f, 0.75f, 0.6f, 1.0f), mpTestImageLoad3, 0.0f, mSubTex);

        g.DrawString("A", Rectangle(200, 170, 32, 32), Color(0.25f, 0.75f, 0.6f, 1.0f));

        g.DrawString("This is a test string!", Rectangle::MakeFromTopLeft(100, 500, 500, 50), Color::Green());
        g.DrawString("This is a very long string that should end up on more than one line when printed out test string!", Rectangle::MakeFromTopLeft(300, 50, 400, 500), Color::Red());
    }

    
    void SimpleRenderScene::RenderShapesTest(Renderer2D& g)
    {

        switch (mShapeMode)
        {
            case ShapeMode::Boxes: 
            { 
                g.DrawBox(Rectangle(300, 300, 50, 50), Color::Green());

            } break;

            case ShapeMode::Lines: 
            { 
                g.DrawLine(glm::vec2(30.0f, 200.0f), glm::vec2(400.0f, 400.0f), Color::Green(), 3.0f, box_angle * 3.0f);

                for (auto iter = mLines.begin(); iter != mLines.end(); iter++)
                {
                    g.DrawLine(iter->Position1, iter->Position2, iter->Color, iter->Thickness, iter->Angle);
                    iter->Angle += iter->RotSpeed;
                }
            } break;

            case ShapeMode::Ellipses: 
            { 
                g.DrawEllipseFilled(glm::vec2(350.0f, 300.0f), glm::vec2(mEllipseRadii[0], mEllipseRadii[1]), Color::Blue(), mEllipseResolution);
                g.DrawEllipse(glm::vec2(800.0f, 300.0f), glm::vec2(mEllipseRadii[0], mEllipseRadii[1]), Color::Red(), mEllipseResolution);

            } break;
        }
        
    }

    
    void SimpleRenderScene::RenderTileMapTest(Renderer2D& g)
    {
        mTestMap.Render(&g);
    }

    void SimpleRenderScene::RenderParentTest(Renderer2D& g)
    {
        g.DrawQuad(Rectangle(mParentPos.x, mParentPos.y, 50.0f, 50.0f), Color::Blue(), nullptr, mParentAngle);
        glm::mat4 parent = glm::mat4(1.0f);
        parent = glm::translate(parent, mParentPos);
        parent = glm::rotate(parent, mParentAngle * -1.0f, glm::vec3(0.0f, 0.0f, 1.0f));
        g.DrawQuad(Rectangle(mChildPos.x, mChildPos.y, 50.0f, 50.0f), Color::Green(), nullptr, mChildAngle, Rectangle(-1, -1, -1, -1), parent);
        g.DrawLine(glm::vec2(mParentPos.x, mParentPos.y), glm::vec2(mParentPos.x + mChildPos.x, mParentPos.y + mChildPos.y), Color::Blue(), 1.5f);
        parent = glm::translate(parent, mChildPos);
        parent = glm::rotate(parent, mChildAngle * -1.0f, glm::vec3(0.0f, 0.0f, 1.0f));
        g.DrawQuad(Rectangle(mChild2Pos.x, mChild2Pos.y, 50.0f, 50.0f), Color::Green(), nullptr, mChild2Angle, Rectangle(-1, -1, -1, -1), parent);
        g.DrawLine(glm::vec2(mParentPos.x + mChildPos.x, mParentPos.y + mChildPos.y), glm::vec2(mParentPos.x + mChildPos.x + mChild2Pos.x, mParentPos.y + mChildPos.y + mChild2Pos.y), Color::Blue(), 1.5f);


        // g.DrawQuad(Rectangle(mParentPos2.x, mParentPos2.y, 50.0f, 50.0f), Color::Red());
        // parent = glm::mat4(1.0f);
        // parent = glm::translate(parent, mParentPos2);
        // g.DrawQuad(Rectangle(mChildPos2.x, mChildPos2.y, 50.0f, 50.0f), Color::White(), nullptr, mChildAngle, Rectangle(-1, -1, -1, -1), parent);
        // g.DrawLine(glm::vec2(mParentPos2.x, mParentPos2.y), glm::vec2(mParentPos2.x + mChildPos2.x, mParentPos2.y + mChildPos2.y), Color::Red(), 1.5f);

        // g.DrawQuad(Rectangle(mParentPos3.x, mParentPos3.y, 50.0f, 50.0f), Color::Black());
        // parent = glm::mat4(1.0f);
        // parent = glm::translate(parent, mParentPos3);
        // g.DrawQuad(Rectangle(mChildPos3.x, mChildPos3.y, 50.0f, 50.0f), Color(0.75f, 0.15f, 0.5f, 1.0f), nullptr, mChildAngle, Rectangle(-1, -1, -1, -1), parent);
        // g.DrawLine(glm::vec2(mParentPos3.x, mParentPos3.y), glm::vec2(mParentPos3.x + mChildPos3.x, mParentPos3.y + mChildPos3.y), Color::Black(), 1.5f);

        // parent = glm::translate(parent, mChildPos3);
        // g.DrawQuad(Rectangle(mChildPos3_2.x, mChildPos3_2.y, 50.0f, 50.0f), Color(0.75f, 0.15f, 0.5f, 1.0f), nullptr, mChildAngle, Rectangle(-1, -1, -1, -1), parent);
        // g.DrawLine(glm::vec2(mParentPos3.x + mChildPos3.x, mParentPos3.y + mChildPos3.y), glm::vec2(mParentPos3.x + mChildPos3.x + mChildPos3_2.x, mParentPos3.y + mChildPos3.y + mChildPos3_2.y), Color::Black(), 1.5f);
    }

    /////////////////////////////////////////////////////////////////////
    //				GUI DRAWING     GUI DRAWING
    /////////////////////////////////////////////////////////////////////
    void SimpleRenderScene::DrawStatsGUI()
    {
        const char* mode_names[6] = { "Basic", "Stress", "String", "Shapes", "TileMap", "Parent/Child"};
        ImGui::SetNextWindowPos(ImVec2(0, 0), ImGuiCond_FirstUseEver);
        ImGui::SetNextWindowSize(ImVec2(400, 800));
        ImGui::Begin("RENDER INFO"); 
        ImGui::BeginChild("Scene Info", ImVec2(ImGui::GetWindowSize().x - 15, ImGui::GetFrameHeightWithSpacing() * 3.5f), true);
        ImGui::Text("Scene Info");
        ImGui::Separator();
        ImGui::Combo("Scene Mode", (int*)&mTestMode, mode_names, 6);
        ImGui::EndChild();
        ImGui::BeginChild("Per Frame", ImVec2(ImGui::GetWindowSize().x - 15, ImGui::GetFrameHeightWithSpacing() * 3.5f), true);
        ImGui::Text("Per Frame");
        ImGui::Separator();
        ImGui::Text("Number of triangles: %d", mRenderStats.NumTris);
        ImGui::Text("Draw calls: %d", mRenderStats.DrawCalls);
        ImGui::EndChild();
        ImGui::BeginChild("General", ImVec2(ImGui::GetWindowSize().x - 15, ImGui::GetFrameHeightWithSpacing() * 4.5f), true);
        ImGui::Text("General Info");
        ImGui::Separator();
        ImGui::Text("Average Render time: %f", Core::GetInstance().GetFrameData().AverageFrameTime);
        ImGui::Text("FPS: %d", Core::GetInstance().GetFrameData().CurrentFPS);
        ImGui::Text("Frame Number: %d", mNumFrames);
        ImGui::EndChild();
        ImGui::BeginChild("Settings", ImVec2(ImGui::GetWindowSize().x - 15, ImGui::GetFrameHeightWithSpacing() * 10.5f), true);
        ImGui::Text("Settings");
        ImGui::Separator();
        if (mTestMode == TestMode::Stress)
        {
            ImGui::InputInt("Number of Quads to draw", &mNumQuadsToRender);
            ImGui::Checkbox("Draw Textures", &mUseTextures);
        }

        else if (mTestMode == TestMode::Basic)
        {
            float vals[4] = {mSubTex.left(), mSubTex.top(), mSubTex.HalfWidth * 2, mSubTex.HalfHeight * 2 };
            if (ImGui::DragFloat4("Sub Texture Rect", vals))
            {
                mSubTex = Rectangle::MakeFromTopLeft(vals[0], vals[1], vals[2], vals[3]);
            }

            if (ImGui::Button("Reset"))
            {
                mSubTex = Rectangle::MakeFromTopLeft(0.0f, 0.0f, 256.0f, 256.0f);
            }
        }
        else if (mTestMode == TestMode::Shapes)
        {
            const char* shape_types[3] = { "Lines", "Boxes", "Ellipses" };
            ImGui::Combo("Shape Type", (int*)&mShapeMode, shape_types, 3);
            ImGui::Separator();
            if (mShapeMode == ShapeMode::Lines)
            {
                ImGui::DragInt("Number of Lines", &mNumLines);
            }
            else if (mShapeMode == ShapeMode::Ellipses)
            {
                ImGui::DragInt("Ellipse Resolution", &mEllipseResolution, 0.5f, 4);
                ImGui::DragFloat2("Ellipse Radii", mEllipseRadii);
            }
            if (ImGui::Button("Regenerate Shapes"))
            {
                GenerateLines();
                GenerateEllipses();
            }
        }
        else if (mTestMode == TestMode::TileMap)
        {
            ImGui::Begin("TileSet View");
            ImGui::Image((ImTextureID)mpTestImageLoad->GetGLID64(), ImVec2(mpTestImageLoad->GetWidth(), mpTestImageLoad->GetHeight()));
            ImGui::End(); 
            
            ImGui::BeginChild("TileMap Editor", ImVec2(ImGui::GetWindowSize().x - 15, ImGui::GetFrameHeightWithSpacing() * 6.5f), true, ImGuiWindowFlags_HorizontalScrollbar);
            for (int i = 0; i < mTestMap.GetSizeInTiles().Width; i++)
            {
                for (int j = 0; j < mTestMap.GetSizeInTiles().Height; j++)
                {   
                    std::string id = "##idx";
                    id += std::to_string(i);
                    id += ", ";
                    id += std::to_string(j);
                    int v[2] = { mTestMap.GetMap()[i][j].TileIndex.X, mTestMap.GetMap()[i][j].TileIndex.Y };
                    ImGui::SetNextItemWidth(65);
                    if (ImGui::InputInt2(id.c_str(), v))
                    {
                        mTestMap.SetTile(editor::TileRef {0, {v[0], v[1]} }, Vec2i { i, j });
                    }

                    if (j + 1 < mTestMap.GetSizeInTiles().Height)
                    {
                        ImGui::SameLine();
                    }
                }
            }
            ImGui::EndChild();
        }
        else if (mTestMode == TestMode::Parent)
        {
            // GROUP ONE
            ImGui::Text("Group One:");
            float parent_pos[3] = { mParentPos.x, mParentPos.y, mParentPos.z };
            float child_pos[3] = { mChildPos.x, mChildPos.y, mChildPos.z };
            float child2_pos[3] = { mChild2Pos.x, mChild2Pos.y, mChild2Pos.z };

            ImGui::Text("Parent Position:");
            ImGui::SameLine();
            if (ImGui::DragFloat3("##ParentPos", parent_pos))
            {
                mParentPos = { parent_pos[0], parent_pos[1], parent_pos[2] };
            }

            ImGui::Text("Parent Angle:");
            ImGui::SameLine();
            ImGui::DragFloat("##ParentAngle", &mParentAngle, 0.1f);

            ImGui::Text("Child Position:");
            ImGui::SameLine();
            if (ImGui::DragFloat3("##ChildPos", child_pos))
            {
                mChildPos = { child_pos[0], child_pos[1], child_pos[2] };
            }

            ImGui::Text("Child Angle:");
            ImGui::SameLine();
            ImGui::DragFloat("##ChildAngle", &mChildAngle, 0.1f);

            ImGui::Text("Child 2 Position:");
            ImGui::SameLine();
            if (ImGui::DragFloat3("##Child2Pos", child2_pos))
            {
                mChild2Pos = { child2_pos[0], child2_pos[1], child2_pos[2] };
            }

            ImGui::Text("Child 2 Angle:");
            ImGui::SameLine();
            ImGui::DragFloat("##Child2Angle", &mChild2Angle, 0.1f);


            // GROUP TWO
            // ImGui::Text("Group two:");
            // float parent_pos2[3] = { mParentPos2.x, mParentPos2.y, mParentPos2.z };
            // float child_pos2[3] = { mChildPos2.x, mChildPos2.y, mChildPos2.z };

            // ImGui::Text("Parent Position:");
            // ImGui::SameLine();
            // if (ImGui::DragFloat3("##ParentPos2", parent_pos2))
            // {
            //     mParentPos2 = { parent_pos2[0], parent_pos2[1], parent_pos2[2] };
            // }

            // ImGui::Text("Child Position:");
            // ImGui::SameLine();
            // if (ImGui::DragFloat3("##ChildPos2", child_pos2))
            // {
            //     mChildPos2 = { child_pos2[0], child_pos2[1], child_pos2[2] };
            // }

            // // GROUP THREE
            // ImGui::Text("Group three:");
            // float parent_pos3[3] = { mParentPos3.x, mParentPos3.y, mParentPos3.z };
            // float child_pos3[3] = { mChildPos3.x, mChildPos3.y, mChildPos3.z };
            // float child_pos3_2[3] = { mChildPos3_2.x, mChildPos3_2.y, mChildPos3_2.z };

            // ImGui::Text("Parent Position:");
            // ImGui::SameLine();
            // if (ImGui::DragFloat3("##ParentPos3", parent_pos3))
            // {
            //     mParentPos3 = { parent_pos3[0], parent_pos3[1], parent_pos3[2] };
            // }

            // ImGui::Text("Child Position:");
            // ImGui::SameLine();
            // if (ImGui::DragFloat3("##ChildPos3", child_pos3))
            // {
            //     mChildPos3 = { child_pos3[0], child_pos3[1], child_pos3[2] };
            // }

            // ImGui::Text("Child Position:");
            // ImGui::SameLine();
            // if (ImGui::DragFloat3("##ChildPos3_2", child_pos3_2))
            // {
            //     mChildPos3_2 = { child_pos3_2[0], child_pos3_2[1], child_pos3_2[2] };
            // }
        }
       
        ImGui::EndChild();
        ImGui::End();

        mNumQuadsToRender = Math::ClampI(mNumQuadsToRender, 0, NUM_QUADS);
    }


    /////////////////////////////////////////////////////////////////////
    //				HELPERS         HELPERS
    /////////////////////////////////////////////////////////////////////    
    
    void SimpleRenderScene::LoadImages()
    {
        // Test Image 1
        int w, h, n;
        stbi_set_flip_vertically_on_load(0);
        unsigned char* buffer = stbi_load("LinkToThePast1_sized.png", &w, &h, &n, 0);

        TextureFormat format = TextureFormat::RGBA;
        if (n == 3)
        {
            format = TextureFormat::RGB;
        }
        mpTestImageLoad = Texture::Create(buffer, w, h, format, true);
        mSrcWidth = w;
        mSrcHeight = h;

        delete[] buffer;

        // Debug texture
        stbi_set_flip_vertically_on_load(0);
        buffer = stbi_load("debug_texture.jpeg", &w, &h, &n, 0);

        format = TextureFormat::RGBA;
        if (n == 3)
        {
            format = TextureFormat::RGB;
        }
        else if (n == 1)
        {
            format = TextureFormat::RED;
        }

        mpTestImageLoad2 = Texture::Create(buffer, w, h, format);
        delete[] buffer;

        // Text testing texture
        stbi_set_flip_vertically_on_load(0);
        buffer = stbi_load("lunarium_text_test.png", &w, &h, &n, 0);

        format = TextureFormat::RGBA;
        if (n == 3)
        {
            format = TextureFormat::RGB;
        }
        else if (n == 1)
        {
            format = TextureFormat::RED;
        }

        mpTestImageLoad3 = Texture::Create(buffer, w, h, format);
        delete[] buffer;

        mTestSet.SetImage(mpTestImageLoad);
        mTestSet.SetTileSize({16, 16});
        mTestMap.AddTileSet(0, &mTestSet).LogIfFailed(mLogCat);
        mTestMap.ResizeMap({4, 4});
        mTestMap.ClearMap();
    }

    void SimpleRenderScene::GenerateLines()
    {
        mLines.clear();
        int window_width = 0;
        int window_height = 0;
        Core::MainWindow().GetFramebufferSize(&window_width, &window_height);
        for (int i = 0; i < mNumLines; i++)
        {
            mLines.push_back(LineData
            {
                glm::vec2(rand() % window_width, rand() % window_height),
                glm::vec2(rand() % window_width, rand() % window_height),
                Color(((float)(rand() % 10000)) / 10000.0f,
                        ((float)(rand() % 10000)) / 10000.0f,
                        ((float)(rand() % 10000)) / 10000.0f,
                        1.0f),
                ((float)(rand() % 180)),
                ((float)(rand() % 100)) / 100.0f + 0.01f,
                ((float)(rand() % 100)) / 10.0f + 0.5f
            });
        }
    }

    void SimpleRenderScene::GenerateEllipses()
    {
        
    }

    void SimpleRenderScene::GenerateQuads()
    {
        mQuads = new Rectangle[NUM_QUADS];
        for (int i = 0; i < NUM_QUADS; i++)
        {
            float x = (rand() % 1000);
            float y = (rand() % 600);
            float w = (rand() % 200) + 10;
            float h = (rand() % 200) + 10;

            mQuads[i] = Rectangle(x, y, w, h);
        }

        mQuadColors = new Color[NUM_QUADS];
        mQuadTexures = new Texture*[NUM_QUADS];
        
        for (int i = 0; i < NUM_QUADS; i++)
        {
            mQuadTexures[i] =  (i % 2 == 0) ? mpTestImageLoad : mpTestImageLoad2;
            mQuadColors[i].R = ((float)(rand() % 10000)) / 10000.0f;
            mQuadColors[i].G = ((float)(rand() % 10000)) / 10000.0f;
            mQuadColors[i].B = ((float)(rand() % 10000)) / 10000.0f;
            mQuadColors[i].A = 1.0f;
        }
    }
    
    void SimpleRenderScene::DoFrameBufferSaveTest()
    {
         // Test writing out a rendered image with transparency
            Renderer2D& g = Core::Graphics();
            Color prev = g.GetClearColor();
            g.SetClearColor(Color(0.0f, 0.0f, 0.0f, 0.0f));
            mFrameBufferTwo->Bind();
            OrthographicCamera cam(Vec2f{0.0f, 0.0f}, Sizef{(float)mFrameBufferTwo->GetTexture()->GetWidth(), (float)mFrameBufferTwo->GetTexture()->GetHeight()});
            g.BeginDraw(&cam);
            // if (Failed(result))
            // {
            //     Logger::Warn(mLogCat, "Unable to render to texture: %s", result.Description.c_str());
            //     return;
            // }

            Logger::Info(mLogCat, "Running transparent image test");

            g.DrawQuad(Rectangle(500, 400, 300, 300), Color(0.5f, 0.0f, 0.75f, 1.0f));
            g.DrawQuad(Rectangle(200, 300, 100, 100), Color(0.2f, 0.5f, 0.4f, 1.0f), nullptr, 45.0f);
            g.DrawString("This is a test of rendering an image with transparency", 
                            Rectangle::MakeFromTopLeft(50, 50, 600, 200), Color(0.0f, 1.0f, 0.2f, 1.0f), 0.5f);
            
            g.EndDraw();
            mpRenderedImage = mFrameBufferTwo->GetTexture();
            mFrameBufferTwo->Unbind();
            //mpRenderedImage = Core::GetInstance().EndRenderToTexture();
            g.SetClearColor(prev);

            stbi_flip_vertically_on_write(1);
            stbi_write_png("lunarium_test_image.png", mpRenderedImage->GetWidth(), mpRenderedImage->GetHeight(), 4, 
                            mpRenderedImage->GetPixels(), mpRenderedImage->GetWidth() * 4);
            //Logger::Info(mLogCat, "")
    }
}