/******************************************************************************
 *	File		-	worldTree.cpp
 *	Author		-	Joey Pollack
 *	Date		-	2021/11/04 (y/m/d)
 *	Mod Date	-	2021/11/04 (y/m/d)
 *	Description	-	The tree view listing all objects in the world
 ******************************************************************************/

#include "world_tree.h"
#include <editor/editor.h>
#include <core/core.h>
#include <world/world.h>
#include <world/entity.h>
#include <world/components.h>
#include <dearimgui/imgui.h>
#include <editor/editor.h>
#include <utils/logger.h>

namespace lunarium
{
    namespace editor
    {
        WorldTree::WorldTree(Editor *editor)
            : Panel("World Tree", PanelDockZone::DDZ_LEFT, true, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar),
              mpEditor(editor),
              // TODO: Temp world created here
              mpWorld(nullptr),
              mpSelectedEntity(nullptr)
        {
            AddPopup(PopUp::NEW_ENTITY, "New Entity", [](Panel *p)
                {
                    WorldTree* pWT = (WorldTree*)p;
                    if (!pWT->mpWorld)
                    {
                        return false;
                    }

                    char name_buf[64] = "NewEntity";
                    ImGui::TextUnformatted("Entity Name: ");
                    ImGui::SameLine();
                    if (ImGui::InputText("##Entity Name", name_buf, 64, ImGuiInputTextFlags_AutoSelectAll | ImGuiInputTextFlags_EnterReturnsTrue))
                    {
                        LUUID id = pWT->mpWorld->CreateEntity();
                        pWT->mpWorld->GetEntity(id)->AddComponent<TagComponent>();
                        TagComponent& tc = pWT->mpWorld->GetEntity(id)->GetComponent<TagComponent>();
                        tc.Info = name_buf;
                        return false;
                    }

                    if (Core::Input().IsKeyDown(KeyCode::ESCAPE, true))
                    {
                        return false;
                    } 

                    return true;
            }).LogIfFailed(Editor::LogCat);
        }

        void WorldTree::SetWorld(lunarium::World *pWorld)
        {
            mpWorld = pWorld;
            mpSelectedEntity = nullptr;
        }

        lunarium::World *WorldTree::GetWorld()
        {
            return mpWorld;
        }

        void WorldTree::DoFrame()
        {
            Entity *pSelection = nullptr;
            if (!mpWorld)
            {
                ImGui::Text("No World Loaded");
                return;
            }

            ImGui::SetNextItemOpen(true);

            if (ImGui::TreeNode("World Root"))
            {
                // List all world entities
                // This will fail if we end up implementing child entities
                // In that case this needs to become recursive
                int idx = 0;
                for (auto iter = mpWorld->EntitiesBegin(); !mpWorld->EntitiesIsEnd(iter); iter++, idx++)
                {
                    std::string name = "Entity";
                    name += std::to_string(idx);
                    if ((*iter)->HasComponent<TagComponent>())
                    {
                        name = (*iter)->GetComponent<TagComponent>().Info;
                    }

                    if ((*iter)->HasChildren())
                    {
                        // TODO: Recurse through children
                        if (ImGui::TreeNode(name.c_str()))
                        {
                            ImGui::TreePop();
                        }
                    }
                    else
                    {
                        bool is_selected = false;
                        if ((*iter) == mpSelectedEntity)
                        {
                            is_selected = true;
                        }
                        if (ImGui::Selectable(name.c_str(), &is_selected))
                        {
                            mpSelectedEntity = (*iter);
                            if (is_selected)
                            {
                                mpEditor->OnEntitySelect(mpSelectedEntity);
                            }
                            else
                            {
                                mpEditor->OnEntitySelect(nullptr);
                                mpSelectedEntity = nullptr;
                            }
                        }
                    }
                }

                ImGui::TreePop();
            }

            if (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && ImGui::IsWindowHovered())
            {
                mpSelectedEntity = nullptr;
                mpEditor->OnEntitySelect(nullptr);
            }

            DoContextMenu();
        }

        void WorldTree::DoContextMenu()
        {
            if (ImGui::BeginPopupContextWindow(0, ImGuiPopupFlags_MouseButtonRight))
            {
                if (ImGui::Button("Create New Entity"))
                {
                    if (!mpWorld)
                    {
                        Logger::Warn(Editor::LogCat, "Can not create new entity - World pointer is null");
                    }
                    else
                    {
                        OpenPopup(PopUp::NEW_ENTITY).LogIfFailed(Editor::LogCat);
                    }
                }
                ImGui::EndPopup();
            }
        }

    }
}