#ifndef SANDBOX2D_HPP
#define SANDBOX2D_HPP

#include <open_engine.hpp>
#include <view_layer.hpp>

#include <glm/ext/matrix_transform.hpp>
#include <glm/glm.hpp>

class Sandbox2DLayer : public ViewLayer
{
    public:
        Sandbox2DLayer()
            : ViewLayer("sandbox_2d", (float)OpenEngine::Application::Get().GetWindow().GetWidth() /
                    OpenEngine::Application::Get().GetWindow().GetHeight(), 1.0f)
        {
        }
        ~Sandbox2DLayer() {};

        void OnAttach() override
        {
            OE_PROFILE_FUNCTION();
            {
                OE_PROFILE_SCOPE("Texture2D Creation");
                face = OpenEngine::Texture2D::Create("assets/textures/awesomeface.png");
            }

            OpenEngine::FramebufferSpecification specs;
            specs.width = 1280;
            specs.height = 720;

            GetFramebuffer() = OpenEngine::FrameBuffer::Create(specs);

            atlas = OpenEngine::Texture2D::Create("assets/textures/rpg-spritesheet.png");
            stairs = OpenEngine::Subtexture2D::CreateFromCoords(atlas, {7, 6}, {64, 64}, { 1, 1 });
            tree = OpenEngine::Subtexture2D::CreateFromCoords(atlas, {2, 1}, {64, 64}, { 1, 2 });

            grid_camera = OpenEngine::CreateRef<OpenEngine::OrthographicCamera>(-1, 1, -1, 1);

            grid_shader = OpenEngine::Shader::Create("assets/shaders/grid.glsl");
        }

        void OnDetach() override
        {
        }

        void OnUpdate() override
        {
            {
                OE_PROFILE_SCOPE("Setting up Rendering");
                GetCamera().OnUpdate();
                GetFramebuffer()->Bind();

                OpenEngine::RenderCommand::SetClearColor({0.11f, 0.11f, 0.15f, 1.0f});
                OpenEngine::RenderCommand::Clear();
            }

            {
                OpenEngine::Renderer2D::BeginScene(*grid_camera);

                grid_shader->Bind();
                grid_shader->SetMat4("u_ViewProjection", grid_camera->GetViewProjectionMatrix());
                glm::mat4 inverseVP = glm::inverse(GetCamera().GetCamera().GetViewProjectionMatrix());
                grid_shader->SetMat4("u_InverseViewProjection", inverseVP);

                OpenEngine::Transform screen = {glm::vec3(0.0f, 0.0f, -0.9f), glm::vec3(2.0f, 2.0f, 0.0f), 0.0f};
                //OpenEngine::Renderer2D::DrawQuad(screen, glm::vec4(0.8f, 0.4f, 0.3f, 1.0f));

                OpenEngine::Renderer2D::EndScene();

                grid_shader->Unbind();
            }

            OpenEngine::Renderer2D::BeginScene(GetCamera().GetCamera());
            {
                OE_PROFILE_SCOPE("Drawing Quads");
                OpenEngine::Transform tr1 = {glm::vec3(0.0f, 0.0f, -0.1f), glm::vec3(1.0f, 1.0f, 0.0f), angle};
                OpenEngine::Transform tr3 = {glm::vec3(-0.5f, -0.5f, 0.0f), glm::vec3(1.0f, 0.5f, 0.0f), angle * 0.5f};
                //OpenEngine::Renderer2D::DrawQuad(tr1, face);
                //OpenEngine::Renderer2D::DrawQuad(tr3, rectangle_color);
            }

            OpenEngine::Renderer2D::EndScene();

            OpenEngine::Renderer2D::BeginScene(GetCamera().GetCamera());

            for (float y = -5.0f; y < 5.0f; y += 0.5f) {
                for (float x = -5.0f; x < 5.0f; x += 0.5f) {

                    glm::vec4 gradient_color = {(x + 5.0f) / 10.0f, 0.3f, (y + 5.0f) / 10.0f, 1.0f};
                    //OpenEngine::Renderer2D::DrawQuad({{x, y, 0.0f}, glm::vec3(0.45f, 0.45f, 0.0f)}, gradient_color);

                }
            }
            OpenEngine::Transform tr2 = {glm::vec3(0, 0, 0.2f), glm::vec3(1.0f, 1.0f, 0.0f), 0.0f};
            OpenEngine::Transform tr4 = {glm::vec3(-1.0, 0.0, 0.2f), glm::vec3(1.0f, 2.0f, 0.0f), 0.0f};
            //OpenEngine::Renderer2D::DrawQuad(tr2, stairs);
            //OpenEngine::Renderer2D::DrawQuad(tr4, tree);

            auto& cursor = GetCursorPos();
            OpenEngine::Transform tr5 = {glm::vec3(cursor.x, cursor.y, 0.9f), glm::vec3(0.1f, 0.1f, 0.0f), 0.0f};
            //OpenEngine::Renderer2D::DrawQuad(tr5, {1, 1, 1, 1});

            OpenEngine::Renderer2D::EndScene();

            GetFramebuffer()->Unbind();
        }

        void OnEvent(OpenEngine::Event& event) override
        {
            OE_PROFILE_FUNCTION();
            OpenEngine::EventDispatcher dispatcher(event);

            //dispatcher.Dispatch<OpenEngine::KeyPressedEvent>(BIND_EVENT_FN(Sandbox2DLayer::StopRunning));
            {
                OE_PROFILE_SCOPE("Camera OnEvent");
                GetCamera().OnEvent(event);
            }
        }

    private:
        OpenEngine::Ref<OpenEngine::Texture2D> face;
        OpenEngine::Ref<OpenEngine::Texture2D> atlas;
        OpenEngine::Ref<OpenEngine::Subtexture2D> stairs, tree;

        OpenEngine::Ref<OpenEngine::Shader> grid_shader;

        OpenEngine::Ref<OpenEngine::OrthographicCamera> grid_camera;

        float angle;

        glm::vec4 rectangle_color = {0.8f, 0.2f, 0.7f, 1.0f};
};

#endif // SANDBOX2D_HPP
