#include "FrostEdModule.h"
#include "Modules/ModuleManager.h"
#include "Logging/LogMacros.h"
#include "Windows/WindowsApplication.h"
#include "D3D11Device.h"

#include "imgui.h"

#if PLATFORM_WINDOWS
    #include "backends/imgui_impl_dx11.h"
    #include "backends/imgui_impl_win32.h"
#endif

#include <iostream>

FConsoleModule* FFrostEdModule::ConsoleModule = nullptr;
FContentBrowserModule* FFrostEdModule::ContentBrowserModule = nullptr;
FHierarchyModule* FFrostEdModule::HierarchyModule = nullptr;
FPropertiesModule* FFrostEdModule::PropertiesModule = nullptr;
FSceneInteractionModule* FFrostEdModule::SceneInteractionModule = nullptr;

ImVec4 ClearColor = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);

void FFrostEdModule::StartupModule()
{
    FROST_LOG_INFO("Initializing FrostEd...");

    FrostLogo = CreateScope<FD3D11Texture>("../../Content/Editor/About/FrostLogo.png");

    ConsoleModule = &FModuleManager::Get().LoadModule<FConsoleModule>("Console");
    ContentBrowserModule = &FModuleManager::Get().LoadModule<FContentBrowserModule>("ContentBrowser");
    HierarchyModule = &FModuleManager::Get().LoadModule<FHierarchyModule>("Hierarchy");
    PropertiesModule = &FModuleManager::Get().LoadModule<FPropertiesModule>("Properties");
    SceneInteractionModule = &FModuleManager::Get().LoadModule<FSceneInteractionModule>("SceneInteraction");

    IMGUI_CHECKVERSION();

    ImGui::CreateContext();

    ImGuiIO& IO = ImGui::GetIO(); (void)IO;
    IO.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
    IO.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
    IO.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
    IO.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;

    ImGui::StyleColorsDark();

    ImGuiStyle& Style = ImGui::GetStyle();
    if (IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
    {
        Style.WindowRounding = 0.0f;
        Style.Colors[ImGuiCol_WindowBg].w = 1.0f;
    }

    ImGui_ImplWin32_Init(FWindowsApplication::GetWindow()->GetHwnd());
    ImGui_ImplDX11_Init(FD3D11Device::GetDevice()->GetID3D11Device(), FD3D11Device::GetDevice()->GetID3D11DeviceContext());

    ImFontConfig ConfigRegular;
    ConfigRegular.OversampleH = 3;
    ConfigRegular.OversampleV = 3;
    ConfigRegular.PixelSnapH = true;

    ImFont* FontRegular = IO.Fonts->AddFontFromFileTTF("../../Content/ImGui/Fonts/Inter-Regular.ttf", 16.0f, &ConfigRegular);

    ImFontConfig ConfigMedium;
    ConfigRegular.OversampleH = 3;
    ConfigRegular.OversampleV = 3;
    ConfigRegular.PixelSnapH = true;
    ConfigRegular.MergeMode = true;

    ImFont* FontMedium = IO.Fonts->AddFontFromFileTTF("../../Content/ImGui/Fonts/Inter-Medium.ttf", 16.0f, &ConfigMedium);

    ImFontConfig ConfigSemiBold;
    ConfigSemiBold.OversampleH = 3;
    ConfigSemiBold.OversampleV = 3;
    ConfigSemiBold.PixelSnapH = true;
    ConfigSemiBold.MergeMode = true;

    ImFont* FontSemiBold = IO.Fonts->AddFontFromFileTTF("../../Content/ImGui/Fonts/Inter-SemiBold.ttf", 16.0f, &ConfigSemiBold);

    ImFontConfig ConfigBold;
    ConfigBold.OversampleH = 3;
    ConfigBold.OversampleV = 3;
    ConfigBold.PixelSnapH = true;
    ConfigBold.MergeMode = true;

    ImFont* FontBold = IO.Fonts->AddFontFromFileTTF("../../Content/ImGui/Fonts/Inter-Bold.ttf", 16.0f, &ConfigBold);

    ImGui::GetIO().FontDefault = FontRegular;

    FROST_LOG_INFO("Initialized FrostEd!");
}

void FFrostEdModule::ShutdownModule()
{
    FModuleManager::Get().UnloadModule("SceneInteraction");
    FModuleManager::Get().UnloadModule("Properties");
    FModuleManager::Get().UnloadModule("Hierarchy");
    FModuleManager::Get().UnloadModule("ContentBrowser");
    FModuleManager::Get().UnloadModule("Console");
}

void FFrostEdModule::Update()
{
    ImGui_ImplDX11_NewFrame();
    ImGui_ImplWin32_NewFrame();
    ImGui::NewFrame();

    ImVec4* Colors = ImGui::GetStyle().Colors;

    Colors[ImGuiCol_Text]                   = ImVec4(0.98f, 0.98f, 0.98f, 1.00f);
    Colors[ImGuiCol_TextDisabled]           = ImVec4(0.64f, 0.64f, 0.64f, 1.00f);
    Colors[ImGuiCol_WindowBg]               = ImVec4(0.15f, 0.15f, 0.15f, 1.00f);
    Colors[ImGuiCol_PopupBg]                = ImVec4(0.09f, 0.09f, 0.09f, 1.00f);
    Colors[ImGuiCol_Border]                 = ImVec4(0.25f, 0.25f, 0.25f, 1.00f);
    Colors[ImGuiCol_FrameBg]                = ImVec4(0.25f, 0.25f, 0.25f, 1.00f);
    Colors[ImGuiCol_FrameBgHovered]         = ImVec4(0.32f, 0.32f, 0.32f, 1.00f);
    Colors[ImGuiCol_FrameBgActive]          = ImVec4(0.32f, 0.32f, 0.32f, 1.00f);
    Colors[ImGuiCol_TitleBg]                = ImVec4(0.09f, 0.09f, 0.09f, 1.00f);
    Colors[ImGuiCol_TitleBgActive]          = ImVec4(0.09f, 0.09f, 0.09f, 1.00f);
    Colors[ImGuiCol_TitleBgCollapsed]       = ImVec4(0.09f, 0.09f, 0.09f, 1.00f);
    Colors[ImGuiCol_MenuBarBg]              = ImVec4(0.13f, 0.13f, 0.13f, 1.00f);
    Colors[ImGuiCol_ScrollbarBg]            = ImVec4(0.09f, 0.09f, 0.09f, 1.00f);
    Colors[ImGuiCol_ScrollbarGrab]          = ImVec4(0.15f, 0.15f, 0.15f, 1.00f);
    Colors[ImGuiCol_ScrollbarGrabHovered]   = ImVec4(0.25f, 0.25f, 0.25f, 1.00f);
    Colors[ImGuiCol_ScrollbarGrabActive]    = ImVec4(0.32f, 0.32f, 0.32f, 1.00f);
    Colors[ImGuiCol_CheckMark]              = ImVec4(0.64f, 0.64f, 0.64f, 1.00f);
    Colors[ImGuiCol_SliderGrab]             = ImVec4(0.15f, 0.15f, 0.15f, 1.00f);
    Colors[ImGuiCol_SliderGrabActive]       = ImVec4(0.25f, 0.25f, 0.25f, 1.00f);
    Colors[ImGuiCol_Button]                 = ImVec4(0.25f, 0.25f, 0.25f, 1.00f);
    Colors[ImGuiCol_ButtonHovered]          = ImVec4(0.32f, 0.32f, 0.32f, 1.00f);
    Colors[ImGuiCol_ButtonActive]           = ImVec4(0.32f, 0.32f, 0.32f, 1.00f);
    Colors[ImGuiCol_Header]                 = ImVec4(0.32f, 0.32f, 0.32f, 1.00f);
    Colors[ImGuiCol_HeaderHovered]          = ImVec4(0.32f, 0.32f, 0.32f, 1.00f);
    Colors[ImGuiCol_HeaderActive]           = ImVec4(0.45f, 0.45f, 0.45f, 1.00f);
    Colors[ImGuiCol_Separator]              = ImVec4(0.25f, 0.25f, 0.25f, 1.00f);
    Colors[ImGuiCol_SeparatorHovered]       = ImVec4(0.32f, 0.32f, 0.32f, 1.00f);
    Colors[ImGuiCol_SeparatorActive]        = ImVec4(0.45f, 0.45f, 0.45f, 1.00f);
    Colors[ImGuiCol_ResizeGrip]             = ImVec4(0.25f, 0.25f, 0.25f, 1.00f);
    Colors[ImGuiCol_ResizeGripHovered]      = ImVec4(0.32f, 0.32f, 0.32f, 1.00f);
    Colors[ImGuiCol_ResizeGripActive]       = ImVec4(0.45f, 0.45f, 0.45f, 1.00f);
    Colors[ImGuiCol_Tab]                    = ImVec4(0.25f, 0.25f, 0.25f, 1.00f);
    Colors[ImGuiCol_TabHovered]             = ImVec4(0.15f, 0.15f, 0.15f, 1.00f);
    Colors[ImGuiCol_TabActive]              = ImVec4(0.15f, 0.15f, 0.15f, 1.00f);
    Colors[ImGuiCol_TabUnfocused]           = ImVec4(0.25f, 0.25f, 0.25f, 1.00f);
    Colors[ImGuiCol_TabUnfocusedActive]     = ImVec4(0.15f, 0.15f, 0.15f, 1.00f);
    Colors[ImGuiCol_DockingPreview]         = ImVec4(0.32f, 0.32f, 0.32f, 1.00f);
    Colors[ImGuiCol_DockingEmptyBg]         = ImVec4(0.09f, 0.09f, 0.09f, 1.00f);
    Colors[ImGuiCol_PlotLines]              = ImVec4(0.64f, 0.64f, 0.64f, 1.00f);
    Colors[ImGuiCol_PlotLinesHovered]       = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
    Colors[ImGuiCol_PlotHistogram]          = ImVec4(0.64f, 0.64f, 0.64f, 1.00f);
    Colors[ImGuiCol_PlotHistogramHovered]   = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
    Colors[ImGuiCol_TableHeaderBg]          = ImVec4(0.25f, 0.25f, 0.25f, 1.00f);
    Colors[ImGuiCol_TableBorderStrong]      = ImVec4(0.32f, 0.32f, 0.32f, 1.00f);
    Colors[ImGuiCol_TableBorderLight]       = ImVec4(0.25f, 0.25f, 0.25f, 1.00f);
    Colors[ImGuiCol_TableRowBgAlt]          = ImVec4(0.09f, 0.09f, 0.09f, 1.00f);
    Colors[ImGuiCol_DragDropTarget]         = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);

    ImGuiStyle& Style = ImGui::GetStyle();
    
    Style.WindowPadding                     = ImVec2(12.0f, 12.0f);
    Style.FramePadding                      = ImVec2(12.0f, 6.0f);
    Style.ItemSpacing                       = ImVec2(12.0f, 6.0f);
    Style.ItemInnerSpacing                  = ImVec2(12.0f, 6.0f);
    Style.IndentSpacing                     = 6.0f;
    Style.ScrollbarSize                     = 12.0f;
    Style.GrabMinSize                       = 12.0f;
    Style.WindowRounding                    = 6.0f;
    Style.FrameRounding                     = 4.0f;
    Style.TabRounding                       = 6.0f;

    Style.WindowTitleAlign = ImVec2(0.5f, 0.5f);
    Style.WindowMenuButtonPosition = ImGuiDir_Right;
    Style.ColorButtonPosition = ImGuiDir_Left;
    Style.SeparatorTextBorderSize = 2.0f;

    RenderWindowToolbar();

    static bool OptFullscreen = true;
    static bool OptPadding = false;

    static ImGuiDockNodeFlags DockspaceFlags = ImGuiDockNodeFlags_None;

    ImGuiWindowFlags WindowFlags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoDocking;

    if (OptFullscreen)
    {
        const ImGuiViewport* Viewport = ImGui::GetMainViewport();

        ImGui::SetNextWindowPos(ImVec2(Viewport->WorkPos.x, Viewport->WorkPos.y + 50.0f));
        ImGui::SetNextWindowSize(ImVec2(Viewport->WorkSize.x, Viewport->WorkSize.y - 50.0f));

        ImGui::SetNextWindowViewport(Viewport->ID);

        ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
        ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);

        WindowFlags |= ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
        WindowFlags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
    }
    else
    {
        DockspaceFlags &= ~ImGuiDockNodeFlags_PassthruCentralNode;
    }

    if (DockspaceFlags & ImGuiDockNodeFlags_PassthruCentralNode)
    {
        WindowFlags |= ImGuiWindowFlags_NoBackground;
    }

    if (!OptPadding)
    {
        ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
    }

    ImGui::Begin("FrostEd", (bool*)true, WindowFlags);

    if (!OptPadding)
    {
        ImGui::PopStyleVar();
    }

    if (OptFullscreen)
    {
        ImGui::PopStyleVar(2);
    }

    ImGuiIO& IO = ImGui::GetIO();
    if (IO.ConfigFlags & ImGuiConfigFlags_DockingEnable)
    {
        ImGuiID DockspaceID = ImGui::GetID("FrostEd");
        ImGui::DockSpace(DockspaceID, ImVec2(0.0f, 0.0f), DockspaceFlags);
    }

    ConsoleModule->RenderConsole();
    ContentBrowserModule->RenderContentBrowser();
    HierarchyModule->RenderHierarchy();
    PropertiesModule->RenderProperties();
    SceneInteractionModule->RenderSceneInteraction();

    ImGui::End();

    ImGui::Render();

    const float ClearColorWithAlpha[4] = { ClearColor.x * ClearColor.w, ClearColor.y * ClearColor.w, ClearColor.z * ClearColor.w, ClearColor.w };

    FD3D11Device::GetDevice()->GetID3D11DeviceContext()->OMSetRenderTargets(1, &FD3D11RenderTarget::GetRenderTarget()->GetID3D11RenderTargetView(), NULL);
    FD3D11Device::GetDevice()->GetID3D11DeviceContext()->ClearRenderTargetView(FD3D11RenderTarget::GetRenderTarget()->GetID3D11RenderTargetView(), ClearColorWithAlpha);

    ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());

    if (IO.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
    {
        ImGui::UpdatePlatformWindows();
        ImGui::RenderPlatformWindowsDefault();
    }
}

void FFrostEdModule::RenderWindowToolbar()
{
    ImGuiIO& IO = ImGui::GetIO();

    ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f));
    ImGui::SetNextWindowSize(ImVec2(IO.DisplaySize.x, 50.0f));

    ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
    ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(0.0f, 0.0f));
    ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);

    ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0.09f, 0.09f, 0.09f, 1.00f));

    ImGui::Begin("WindowToolbar", (bool*)true, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav);

    ImGui::SetCursorPos(ImVec2(5.0f, 5.0f));
    ImGui::Image((void*)FrostLogo->GetShaderResourceView(), ImVec2(40, 40));

    ImGui::SetCursorPos(ImVec2(40 + 12.0f, 8.0f));

    ImGui::BeginGroup();

    // Draw toolbar buttons
    // ...

    ImGui::EndGroup();

    ImGui::SetCursorPos(ImVec2(5.0f, 20.0f));

    if (ImGui::BeginMenuBar())
    {
        if (ImGui::BeginMenu("File"))
        {
            // Handle menu item click
            // ...

            ImGui::EndMenu();
        }

        if (ImGui::BeginMenu("Edit"))
        {
            // Handle menu item click
            // ...

            ImGui::EndMenu();
        }

        if (ImGui::BeginMenu("Window"))
        {
            // Handle menu item click
            // ...

            ImGui::EndMenu();
        }

        if (ImGui::BeginMenu("Tools"))
        {
            // Handle menu item click
            // ...

            ImGui::EndMenu();
        }

        if (ImGui::BeginMenu("Build"))
        {
            // Handle menu item click
            // ...

            ImGui::EndMenu();
        }

        if (ImGui::BeginMenu("Help"))
        {
            // Handle menu item click
            // ...

            ImGui::EndMenu();
        }

        ImGui::EndMenuBar();
    }

    ImGui::SetCursorPos(ImVec2(5.0f, 55.0f));

    ImGui::Text("Hello, world!");

    ImGui::End();

    ImGui::PopStyleColor();
    ImGui::PopStyleVar(3);
}