/******************************************************************************
*	File		-	properties_view.h
*	Author		-	Joey Pollack
*	Date		-	2022/01/26 (y/m/d)
*	Mod Date	-	2022/01/26 (y/m/d)
*	Description	-	Displayes the properties and components(?) of the selected
*                   object.
******************************************************************************/

#include "properties_view.h"
#include "editor/editor.h"
#include <dearimgui/imgui.h>
#include <gui/imgui_ext.h>
#include <editor/editor.h>
#include <world/entity.h>
#include <world/components.h>
#include <editor/contents/editor_asset.h>
#include <editor/component_guis.h>

/////////////////////////////////////////////////////////////////////
//				MACROS      MACROS
/////////////////////////////////////////////////////////////////////
#define PRESENT_COMP_CHOICE(str_name, type_name, pv) \
if (ImGui::Selectable(str_name)){\
    if (pv->mpSelectedEntity->HasComponent<type_name>()) {\
        pv->OpenPopup(Popup::ADD_COMP_FAIL).LogIfFailed(Editor::LogCat);\
        return false;\
    }\
    pv->mpSelectedEntity->AddComponent<type_name>();\
    if (!pv->mpSelectedEntity->HasComponent<type_name>()) {\
        Logger::Error(Editor::LogCat, "Component not added to entity - unknown error");\
    }\
    pv->mpEditor->OnComponentAdd(pv->mpSelectedEntity, (void*)&pv->mpSelectedEntity->GetComponent<type_name>(), lunarium::ComponentType::type_name);\
    Logger::Info(Editor::LogCat, "Component added to entity: %ll", pv->mpSelectedEntity->GetUUID());\
    return false;\
}

#define DRAW_COMP_GUI(type_name, func_name) \
if (mpSelectedEntity->HasComponent<type_name>()) \
        { \
            ImGui::PopStyleVar(); \
            if (CompGui::func_name(mpSelectedEntity->GetComponent<type_name>())) \
            {\
                mpSelectedEntity->RemoveComponent<type_name>();\
            }\
            ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, spacing_y)); \
            ImGui::Separator(); \
        }


/////////////////////////////////////////////////////////////////////
//				CLASS DEFINTION BEGIN
/////////////////////////////////////////////////////////////////////
namespace lunarium { namespace editor 
{
    PropertiesView::PropertiesView(Editor* pEditor)
        : Panel("Properties", PanelDockZone::DDZ_RIGHT, true, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar), 
            mpSelectedAsset(nullptr), mpSelectedEntity(nullptr), mIsLocked(false), mpEditor(pEditor)
    {
        // ADD COMPONENT POPUP
        AddPopup(Popup::ADD_COMP, "Add Component", [](Panel* p) 
        {
            PropertiesView* pv = (PropertiesView*)p;
            int is_hover = ImGui::IsWindowHovered();

            // List components that can be added
            PRESENT_COMP_CHOICE("Tag Component", TagComponent, pv)
            PRESENT_COMP_CHOICE("Transform Component", TransformComponent, pv)
            PRESENT_COMP_CHOICE("Velocity Component", VelocityComponent, pv)
            PRESENT_COMP_CHOICE("Camera Component", CameraComponent, pv)
            PRESENT_COMP_CHOICE("Block Out Component", BlockOutComponent, pv)
            PRESENT_COMP_CHOICE("Sprite Renderer Component", SpriteRendererComponent, pv)
            PRESENT_COMP_CHOICE("Script Component", ScriptComponent, pv)
            PRESENT_COMP_CHOICE("Rigid Body Component", RigidBodyComponent, pv)
            PRESENT_COMP_CHOICE("Collision Component", CollisionComponent, pv)
            

            if ((ImGui::IsMouseClicked(ImGuiMouseButton_Left) && is_hover < 1))
            {
                return false;
            }

           // ImGui::Text("Is Window Hovered? %d", is_hover);

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

        // ADD COMP FAILED POPUP
        AddPopup(Popup::ADD_COMP_FAIL, "Add Comp Fail", [] (Panel* p)
        {
            ImGui::Text("Can not add that component - Entity already has it");
            if (ImGui::Button("OK") || (ImGui::IsMouseClicked(ImGuiMouseButton_Left) && !ImGui::IsWindowHovered()))
            {
                return false;
            }

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

    /////////////////////////////////////////////////////////////////////
    //				RENDER METHOD
    /////////////////////////////////////////////////////////////////////

    void PropertiesView::DoFrame()
    {
        ShowToolBar();

        if (mpSelectedEntity)
        {
            ShowEntity();
        }

        if (mpSelectedAsset)
        {
            ShowAsset();
        }

    }

    /////////////////////////////////////////////////////////////////////
    //				INTERFACE METHODS
    /////////////////////////////////////////////////////////////////////

    void PropertiesView::SetSelection(Entity* pEntity)
    {
        if (mIsLocked)
        {
            return;
        }

        mpSelectedAsset = nullptr;
        mpSelectedEntity = pEntity;
    }

    void PropertiesView::SetSelection(EditorAsset* pAsset)
    {
        if (mIsLocked)
        {
            return;
        }
        
        mpSelectedEntity = nullptr;
        mpSelectedAsset = pAsset;
    }

    /////////////////////////////////////////////////////////////////////
    //			HELPER METHODS      HELPER METHODS
    /////////////////////////////////////////////////////////////////////
    void PropertiesView::ShowToolBar()
    {
        ImGui::BeginChild("##PropsToolBar", ImVec2(0, ImGui::GetFrameHeightWithSpacing()));

        ImGui::Checkbox("Locked", &mIsLocked);

        ImGui::EndChild();
        ImGui::Separator();
    }
    
    void PropertiesView::ShowEntity()
    {
        LUUID id = mpSelectedEntity->GetUUID();
        ImGui::Text("UUID: %llu", (u64)id);
        char buffer[256] = { 0 };
        strcpy(buffer, mpSelectedEntity->GetName().c_str());
        ImGui::Text("Name:");
        ImGui::SameLine();
        if (ImGui::InputText("##Entity Name", buffer, 256))
        {
            mpSelectedEntity->SetName(buffer);
        }

        ImGui::Separator();

        ImGuiExt::TextCentered("Components");
        float spacing_y = 12.0f;
        ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.0f, spacing_y));
        ImGui::Separator();

        // TODO: iterate through components
        if (mpSelectedEntity->HasComponent<TagComponent>())
        {
            if (CompGui::RenderTagComp(mpSelectedEntity->GetComponent<TagComponent>()))
            {
                mpSelectedEntity->RemoveComponent<TagComponent>();
            }

            ImGui::Separator();
        }

        DRAW_COMP_GUI(TransformComponent, RenderTransformComp)
        DRAW_COMP_GUI(VelocityComponent, RenderVelocityComp)
        DRAW_COMP_GUI(CameraComponent, RenderCameraComp)
        DRAW_COMP_GUI(BlockOutComponent, RenderBlockOutComp)
        DRAW_COMP_GUI(SpriteRendererComponent, RenderSpriteRendererComp)
        DRAW_COMP_GUI(ScriptComponent, RenderScriptComp)
        DRAW_COMP_GUI(RigidBodyComponent, RenderRigidBodyComp)
        DRAW_COMP_GUI(CollisionComponent, RenderCollisionComp)

        // After all components rendered
        if (ImGuiExt::ButtonCentered("Add Component"))
        {
            OpenPopup(Popup::ADD_COMP).LogIfFailed(Editor::LogCat);
        }

        ImGui::PopStyleVar();
    }

    void PropertiesView::ShowAsset()
    {
        if (mpSelectedAsset)
        {
            if (mpSelectedAsset->DrawProperties())
            {
                mpEditor->OnAssetUpdate(mpSelectedAsset);
            }
        }
    }

}}
