#pragma once

#include "imgui/imgui.h"
#include "Types.hpp"
#include "elements/Transformable.hpp"
#include "elements/Scene.hpp"
#include "elements/Layer.hpp"
#include "Debug.hpp"
#include "BehaviourScripts/Renderable.hpp"
#include "BehaviourScripts/MeshContainer.hpp"
#include "BehaviourScripts/ImageAnimation.hpp"
#include "BehaviourScripts/RectBase.hpp"
#include "BehaviourScripts/ParticleSystem.hpp"
#include "BehaviourScripts/AudioListener.hpp"
#include "BehaviourScripts/AudioSource.hpp"
#include "BehaviourScripts/TileMap.hpp"

namespace TSE::EDITOR
{
    enum class InspectableType 
    {
        None,
        Transformable,
        Scene,
        Layer
    };

    struct Inspectable 
    {
        InspectableType type = InspectableType::None;
        void* ptr = nullptr;

        Inspectable() = default;
        Inspectable(InspectableType t, void* p) : type(t), ptr(p) {}
    };

    class ElementDrawer 
    {
    private:
        inline static bool addDropdownOpen = false;
        inline static char searchBuffer[128] = "";
        inline static ImGuiTextFilter filter;

    public:
        static void Draw(const Inspectable& element,const bool& debug) {
            switch (element.type) {
                case InspectableType::Transformable:
                    Draw(static_cast<Transformable*>(element.ptr), debug);
                    break;
                case InspectableType::Scene:
                    Draw(static_cast<Scene*>(element.ptr), debug);
                    break;
                case InspectableType::Layer:
                    Draw(static_cast<Layer*>(element.ptr), debug);
                    break;
                default:
                    TSE_WARNING("Draw not implemented for this type.");
                    break;
            }
        }

    private:
        
        static void DrawAddDropdown(const std::vector<std::string>& options, std::string& selectedOption);
        static void Draw(Transformable* element,const bool& debug);
        static void Draw(Scene* element,const bool& debug);
        static void Draw(Layer* element,const bool& debug);
        static void Draw(BehaviourScript* element,const bool& debug, const int& id = 0);
        static void Draw(Renderable* element, const bool& debug);
        static void Draw(MeshContainer* element, const bool& debug);
        static void Draw(Image* element, const bool& debug);
        static void Draw(ImageAnimation* element, const bool& debug);
        static void Draw(RectBase* element, const bool& debug);
        static void Draw(Material* element, const bool& debug);
        static void Draw(Texture* element, const bool& debug, const std::string& label = "", const bool small = false);
        static void Draw(Sprite* element, const bool& debug, const std::string& label = "", const bool small = false);
        static void Draw(Mesh* element, const bool& debug, const std::string& label = "", const bool small = false);
        static void Draw(ImageAnimationSet* element, const bool& debug, const std::string& label = "", const bool small = false);
        static void Draw(AudioSource* element, const bool& debug);
        static void Draw(AudioClip* element, const bool& debug, const std::string& label = "", const bool small = false);
        static void Draw(Camera* element, const bool& debug);
        static void Draw(ParticleSystem* element, const bool& debug);
        static void Draw(TileMap* element, const bool& debug);

        static void DrawAudioClipCompact(AudioClip* element, const bool& debug, const std::string& label);
        static void DrawAudioClipNormal(AudioClip* element, const bool& debug, const std::string& label);
        static void DrawImageAnimationSetCompact(ImageAnimationSet* element, const bool& debug, const std::string& label);
        static void DrawImageAnimationSetNormal(ImageAnimationSet* element, const bool& debug, const std::string& label);
        static void DrawMeshCompact(Mesh* element, const bool& debug, const std::string& label);
        static void DrawMeshNormal(Mesh* element, const bool& debug, const std::string& label);
        static void DrawSpriteCompact(Sprite* element, const bool& debug, const std::string& label);
        static void DrawSpriteNormal(Sprite* element, const bool& debug, const std::string& label);
        static void DrawTextureCompact(Texture* element, const bool& debug, const std::string& label);
        static void DrawTextureNormal(Texture* element, const bool& debug, const std::string& label);
    };
} // namespace TSE::EDITOR
