#include "LoggerWindow.h"
#include <imgui.h>
#include <string>

namespace OX
{
    static bool s_AutoScroll = true;
    static bool s_ShowOk = true;
    static bool s_ShowInfo = true;
    static bool s_ShowWarning = true;
    static bool s_ShowError = true;
    static bool s_ShowDebug = false;
    static bool s_ShowVerbose = false;
    static char s_FilterBuf[256] = "";

    void LoggerWindow::Init()
    {
        Logger::LogVerbose("Editor::LoggerWindow Initialized");
    }

    void LoggerWindow::Draw(const char *title)
    {
        OX_PROFILE_FUNCTION();

        if (!ImGui::Begin(title)) {
            ImGui::End();
            return;
        }

        if (ImGui::Button("Clear Log")) Logger::Clear();
        ImGui::SameLine();
        ImGui::Checkbox("Auto-scroll", &s_AutoScroll);
        ImGui::SameLine();
        ImGui::SetNextItemWidth(200);
        ImGui::InputTextWithHint("##Filter", "Filter...", s_FilterBuf, sizeof(s_FilterBuf));

        ImGui::Separator();
        ImGui::Text("Levels: ");
        ImGui::SameLine();
        ImGui::Checkbox("Ok", &s_ShowOk);
        ImGui::SameLine();
        ImGui::Checkbox("Info", &s_ShowInfo);
        ImGui::SameLine();
        ImGui::Checkbox("Warning", &s_ShowWarning);
        ImGui::SameLine();
        ImGui::Checkbox("Error", &s_ShowError);
        ImGui::SameLine();
        ImGui::Checkbox("Debug", &s_ShowDebug);
        ImGui::SameLine();
        ImGui::Checkbox("Verbose", &s_ShowVerbose);
        ImGui::Separator();

        constexpr ImGuiTableFlags flags =
                ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg |
                ImGuiTableFlags_ScrollY | ImGuiTableFlags_BordersOuter;

        if (const float tableHeight = ImGui::GetContentRegionAvail().y - 10.0f;
            ImGui::BeginTable("LogTable", 3, flags, ImVec2(0, tableHeight))) {
            ImGui::TableSetupColumn("Level", ImGuiTableColumnFlags_WidthFixed, 80.0f);
            ImGui::TableSetupColumn("Time", ImGuiTableColumnFlags_WidthFixed, 80.0f);
            ImGui::TableSetupColumn("Message", ImGuiTableColumnFlags_WidthStretch);
            ImGui::TableHeadersRow();

            for (const auto &message: Logger::GetMessages()) {
                const MessageType level = message.type;
                const std::string &text = message.text;
                const std::string &timestamp = message.timestamp;

                const bool show =
                        (level == MessageType::Ok && s_ShowOk) ||
                        (level == MessageType::Info && s_ShowInfo) ||
                        (level == MessageType::Warning && s_ShowWarning) ||
                        (level == MessageType::Error && s_ShowError) ||
                        (level == MessageType::Debug && s_ShowDebug) ||
                        (level == MessageType::Verbose && s_ShowVerbose);

                if (!show ||
                    (s_FilterBuf[0] != '\0' &&
                     text.find(s_FilterBuf) == std::string::npos))
                    continue;

                ImGui::TableNextRow();
                ImGui::TableSetColumnIndex(0);

                const Color color = Logger::GetRGBColor(level);
                ImVec4 col(color.r, color.g, color.b, color.a);
                const ImVec2 cursor = ImGui::GetCursorScreenPos();
                constexpr float barWidth = 4.0f;
                const float textHeight = ImGui::GetTextLineHeight();
                ImVec2 barStart = cursor;
                ImVec2 barEnd = ImVec2(cursor.x + barWidth, cursor.y + textHeight);

                ImGui::GetWindowDrawList()->AddRectFilled(barStart, barEnd, ImGui::ColorConvertFloat4ToU32(col), 1.0f);
                ImGui::Dummy(ImVec2(barWidth + 6.0f, 0));
                ImGui::SameLine();
                ImGui::PushStyleColor(ImGuiCol_Text, col);
                ImGui::TextUnformatted(Logger::MessageTypeToString(level).c_str());
                ImGui::PopStyleColor();

                ImGui::TableSetColumnIndex(1);
                ImGui::Text("%s", timestamp.c_str());

                ImGui::TableSetColumnIndex(2);
                ImGui::TextWrapped("%s", text.c_str());

                if (s_AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY() - 5.0f)
                    ImGui::SetScrollHereY(1.0f);
            }

            ImGui::EndTable();
        }

        ImGui::End();
    }

    void LoggerWindow::ClearFilters()
    {
        s_FilterBuf[0] = '\0';
        s_ShowOk = s_ShowInfo = s_ShowWarning = s_ShowError = s_ShowDebug = s_ShowVerbose = true;
    }
} // namespace OX
