#include "HirearchieView.hpp"
#include "PropertiesView.hpp"

TSE::EDITOR::HirearchieView::HirearchieView(Scene *s) : GuiWindow("Hirearchie", ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoCollapse)
{
    SetScene(s);
}

void TSE::EDITOR::HirearchieView::SetScene(Scene *s)
{
    currentScene = s;
}

bool selectedFound = false;

void TSE::EDITOR::HirearchieView::Define()
{
    if(currentScene == nullptr) return;
    MenuBar();

    bool collapseOpen = ImGui::CollapsingHeader(currentScene->GetName().c_str(), ImGuiTreeNodeFlags_DefaultOpen);
    if(ImGui::BeginPopupContextItem())
    {
        if(ImGui::MenuItem("Rename"))
        {
            strcpy(inputBuffer, currentScene->GetName().c_str());
            activatePopUpNamingLayer = true;
            inputPurpose = RenamingScene;
        }
        ImGui::Separator();
        AddMenu(nullptr, nullptr);
        ImGui::EndPopup();
    }
    if(collapseOpen)
    {
        int layerCount = currentScene->GetLayerCount();
        selectedFound = false;
        for (int i = 0; i < layerCount; i++)
        {
            auto layer = currentScene->GetLayerAt(i);
            //if(layer->GetName() != ".editor")
            DisplayLayer(layer);
        }

        if(!selectedFound && PropertiesView::GetCurrentInspectableType() == InspectableType::Transformable)
        {
            PropertiesView::ForceClearInspectorElement();
        }
        
    }

    if(activatePopUpNamingLayer)
    {
        activatePopUpNamingLayer = false;
        openPopUpNamingLayer = true;
        ImGui::OpenPopup("Enter Text");
    }

    if (openPopUpNamingLayer) {
        if (ImGui::BeginPopupModal("Enter Text", NULL, ImGuiWindowFlags_AlwaysAutoResize)) {
            ImGui::Text("Please enter a Name:");

            ImGui::InputText("##input", inputBuffer, IM_ARRAYSIZE(inputBuffer));

            bool inputValid = strlen(inputBuffer) > 0;

            if (!inputValid) {
                ImGui::TextColored(ImVec4(1,0,0,1), "Not Valid.");
            }

            if (ImGui::Button("OK", ImVec2(120, 0))) {
                if (inputValid) {
                    inputConfirmed = true;
                    openPopUpNamingLayer = false;
                    ImGui::CloseCurrentPopup();
                }
            }
            ImGui::SameLine();
            if (ImGui::Button("Cancel", ImVec2(120, 0))) {
                openPopUpNamingLayer = false;
                ImGui::CloseCurrentPopup();
            }

            ImGui::EndPopup();
        }
    }
    if (inputConfirmed) {
        switch (inputPurpose)
        {
        case LayerCreation:
            CreateLayer();
            break;
        case RenamingLayer:
            currentScene->RenameLayer(tmpHolder2->GetName(), inputBuffer);
            tmpHolder2 = nullptr;
            break;
        case RenamingScene:
            currentScene->SetName(inputBuffer);
            break;
        case RenamingTransformable:
            tmpHolder1->name = inputBuffer;
            tmpHolder1 = nullptr;
            break;
        
        }
        inputConfirmed = false; 
        inputPurpose = Nothing;
        strcpy(inputBuffer, ""); // Reset
    }
}

void TSE::EDITOR::HirearchieView::MenuBar()
{
    if(ImGui::BeginMenuBar())
    {
        if(ImGui::BeginMenu("Add"))
        {
            if(ImGui::MenuItem("Empty"))
            {
                CreateEmpty(currentScene->GetLayerAt(0));
            }
            ImGui::Separator();
            if(ImGui::MenuItem("Layer"))
            {
                activatePopUpNamingLayer = true;
                inputPurpose = LayerCreation;
            }
            ImGui::EndMenu();
        }
    }
    ImGui::EndMenuBar();
}


void TSE::EDITOR::HirearchieView::DisplayLayer(Layer *l)
{
    ImGui::Indent(20.0f);
    bool collapseOpen = ImGui::CollapsingHeader(l->GetName().c_str(), ImGuiTreeNodeFlags_DefaultOpen);
    if(ImGui::BeginPopupContextItem())
    {
        bool disabled = currentScene->GetLayerCount() <= 1;
        if (disabled)
        {
            ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
        }
        if(ImGui::MenuItem("Move Up") && !disabled)
        {
            MoveUpLayer(l);
        }
        if(ImGui::MenuItem("Move Down") && !disabled)
        {
            MoveDownLayer(l);
        }
        if (disabled)
        {
            ImGui::PopStyleVar();
        }
        if(ImGui::MenuItem("Rename"))
        {
            strcpy(inputBuffer, l->GetName().c_str());
            activatePopUpNamingLayer = true;
            inputPurpose = RenamingLayer;
            tmpHolder2 = l;
        }
        ImGui::Separator();
        AddMenu(nullptr, l);
        ImGui::Separator();
        if(ImGui::MenuItem("Delete"))
        {
            currentScene->RemoveLayer(l->GetName());
            //property display remove if present

            //exit early:
            ImGui::EndPopup();
            ImGui::Unindent(20.0f);
            return;
        }
        ImGui::EndPopup();
    }
    if(ImGui::BeginDragDropTarget())
    {
        auto payload = ImGui::AcceptDragDropPayload("OBJ_TRANS_PTR");
        if(payload != nullptr)
        {
            auto t2 = *(Transformable**)payload->Data;
            HandleDropping(l, t2);
        }
        ImGui::EndDragDropTarget();
    }
    if(collapseOpen)
    {
        for(int i = 0; i < l->GetAllObjects().size(); i++)
        {
            DisplayObj(l->GetAllObjects()[i], l);
        }
    }
    ImGui::Unindent(20.0f);
}

void TSE::EDITOR::HirearchieView::DisplayObj(Transformable *t, Layer *l)
{
    ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_DefaultOpen | ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_SpanFullWidth;
    if(t->GetChildren().size() == 0)
    {
        flags |= ImGuiTreeNodeFlags_Leaf;
    }
    if(selected == t->id)
    {
        flags |= ImGuiTreeNodeFlags_Selected;
        selectedFound = true;
    }
    string name = t->GetName() + "##" + to_string(t->id);
    bool open = ImGui::TreeNodeEx((name).c_str(), flags);
    if(ImGui::BeginPopupContextItem())
    {
        bool disabled = false;
        if(t->GetParent() != nullptr)
            disabled = t->GetParent()->GetChildren().size() < 1;
        else
            disabled = l->GetAllObjects().size() <= 1;
        if (disabled)
        {
            ImGui::PushStyleVar(ImGuiStyleVar_Alpha, ImGui::GetStyle().Alpha * 0.5f);
        }
        if(ImGui::MenuItem("Move Up") && !disabled)
        {
            t->MoveUp(l);
        }
        if(ImGui::MenuItem("Move Down") && !disabled)
        {
            t->MoveDown(l);
        }
        if (disabled)
        {
            ImGui::PopStyleVar();
        }
        if(ImGui::MenuItem("Rename"))
        {
            strcpy(inputBuffer, t->name.c_str());
            activatePopUpNamingLayer = true;
            inputPurpose = RenamingTransformable;
            tmpHolder1 = t;
        }
        ImGui::Separator();
        AddMenu(t, nullptr);
        ImGui::Separator();
        if(ImGui::MenuItem("Delete"))
        {
            t->SetParent(nullptr);
            int layerCount = currentScene->GetLayerCount();
            for (int i = 0; i < layerCount; i++)
            {
                auto layer = currentScene->GetLayerAt(i);
                if(layer->HasTransformable(t))
                {
                    layer->RemoveTransformable(t);
                    break;
                }
            }
            Transformable::HardDelete(t->id);
            PropertiesView::ForceClearInspectorElement();

            //exit early:
            ImGui::EndPopup();
            if(open)
            {
                ImGui::TreePop();
            }
            return;
        }
        ImGui::EndPopup();
    }
    if(ImGui::BeginDragDropSource())
    {
        auto ptr = &t;
        ImGui::SetDragDropPayload("OBJ_TRANS_PTR", ptr, sizeof(ptr));
        std::string name = t->GetName();
        ImGui::Text((std::string("Move \"") + t->GetName() + "\"").c_str());
        ImGui::EndDragDropSource();
    }
    if(ImGui::BeginDragDropTarget())
    {
        auto payload = ImGui::AcceptDragDropPayload("OBJ_TRANS_PTR");
        if(payload != nullptr)
        {
            auto t2 = *(Transformable**)payload->Data;
            HandleDropping(t, t2);
        }
        ImGui::EndDragDropTarget();
    }
    if(ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen())
    {
        selected = t->id;
        PropertiesView::SetInspectorElement(InspectableType::Transformable, t);
        selectedFound = true;
    }
    if(open)
    {
        for(int i = 0; i < t->GetChildren().size(); i++)
        {
            DisplayObj(t->GetChildren()[i], nullptr);
        }
        ImGui::TreePop();
    }
}

void TSE::EDITOR::HirearchieView::HandleDropping(Layer *target, Transformable *payload)
{
    payload->SetParent(nullptr);
    int layerCount = currentScene->GetLayerCount();
    for (int i = 0; i < layerCount; i++)
    {
        auto layer = currentScene->GetLayerAt(i);
        if(layer == target && layer->HasTransformable(payload)) return;
        if(layer->HasTransformable(payload))
        {
            layer->RemoveTransformable(payload);
            break;
        }
    }
    target->AddTransformable(payload);
}

void TSE::EDITOR::HirearchieView::HandleDropping(Transformable *target, Transformable *payload)
{
    if(target->id == payload->id) return;
    if(payload->IsMyChild(target)) return;
    int layerCount = currentScene->GetLayerCount();
    for (int i = 0; i < layerCount; i++)
    {
        auto layer = currentScene->GetLayerAt(i);
        if(layer->HasTransformable(payload))
        {
            layer->RemoveTransformable(payload);
            break;
        }
    }
    payload->SetParent(target);
}

void TSE::EDITOR::HirearchieView::AddMenu(Transformable *t, Layer *l)
{
    if(t== nullptr && l == nullptr) //Scene
    {
        if(ImGui::MenuItem("Add Layer"))
        {
            activatePopUpNamingLayer = true;
            inputPurpose = LayerCreation;
        }
    }
    else //Layer and Transformable
    {
        if(ImGui::MenuItem("Add Empty"))
        {
            if(t == nullptr)
                CreateEmpty(l);
            else
                CreateEmpty(t);
        }
        
    }
}

void TSE::EDITOR::HirearchieView::MoveUpLayer(Layer *t)
{
    if(currentScene->GetLayerAt(0) == t) return;
    currentScene->MoveLayerUp(t);
}

void TSE::EDITOR::HirearchieView::MoveDownLayer(Layer *t)
{
    int lc = currentScene->GetLayerCount();
    if(currentScene->GetLayerAt(lc - 1) == t) return;
    currentScene->MoveLayerDown(t);
}

void TSE::EDITOR::HirearchieView::CreateEmpty(Transformable *parent)
{
    Transformable* t = new Transformable("Unnamed Object");
    if(parent != nullptr)
    {
        t->SetParent(parent);
    }
    // else
    // {
    //     // TODO: need to chose a layer to put it in. I would suggest the first one?
    //     currentScene->GetLayerAt(0)->AddTransformable(t);
    // }
}

void TSE::EDITOR::HirearchieView::CreateEmpty(Layer *parent)
{
    Transformable* t = new Transformable("Unnamed Object");
    if(parent != nullptr)
    {
        parent->AddTransformable(t);
    }
}

void TSE::EDITOR::HirearchieView::CreateLayer()
{
    Layer* l = new Layer(inputBuffer);
    currentScene->AddLayer(l);
}
