#include "HelpOverlay.h"
#include "Font.h"
#include <array>
#include <algorithm>

namespace {
struct ShortcutEntry {
    const char* combo;
    const char* description;
};

void drawRect(SDL_Renderer* renderer, float x, float y, float w, float h, SDL_Color color) {
    SDL_SetRenderDrawColor(renderer, color.r, color.g, color.b, color.a);
    SDL_FRect rect{x, y, w, h};
    SDL_RenderFillRect(renderer, &rect);
}

float fitScale(FontAtlas& font, const char* text, float initialScale, float maxWidth) {
    int textW = 0, textH = 0;
    float scale = initialScale;
    font.measure(text, scale, textW, textH);
    if (textW > maxWidth && textW > 0) {
        float factor = maxWidth / static_cast<float>(textW);
        scale = std::max(0.65f, scale * factor);
    }
    return scale;
}

} // anonymous namespace

namespace HelpOverlay {

void Render(SDL_Renderer* renderer, FontAtlas& font, float logicalWidth, float logicalHeight, float offsetX, float offsetY) {
    if (!renderer) return;

    const std::array<ShortcutEntry, 5> generalShortcuts{{
        {"F1", "Toggle this help overlay"},
        {"ESC", "Back / cancel current popup"},
        {"F11 or ALT+ENTER", "Toggle fullscreen"},
        {"M", "Mute or unmute music"},
        {"K", "Toggle sound effects"}
    }};

    const std::array<ShortcutEntry, 2> menuShortcuts{{
        {"ARROW KEYS", "Navigate menu buttons"},
        {"ENTER / SPACE", "Activate highlighted action"}
    }};

    const std::array<ShortcutEntry, 8> gameplayShortcuts{{
        {"LEFT / RIGHT", "Move active piece"},
        {"DOWN", "Soft drop (faster fall)"},
        {"SPACE", "Hard drop / instant lock"},
        {"UP", "Rotate clockwise"},
        {"H", "Hold / swap current piece"},
        {"X", "Toggle rotation direction used by UP"},
        {"P", "Pause or resume"},
        {"ESC", "Open exit confirmation"}
    }};

    const float boxW = logicalWidth * 0.7f;
    const float boxH = logicalHeight * 0.55f;
    const float boxX = offsetX + (logicalWidth - boxW) * 0.5f;
    const float boxY = offsetY + (logicalHeight - boxH) * 0.5f;

    drawRect(renderer, boxX - 6.0f, boxY - 6.0f, boxW + 12.0f, boxH + 12.0f, {70, 90, 150, 255});
    drawRect(renderer, boxX - 2.0f, boxY - 2.0f, boxW + 4.0f, boxH + 4.0f, {10, 12, 20, 255});
    drawRect(renderer, boxX, boxY, boxW, boxH, {18, 22, 35, 240});

    // Slightly smaller overall title to fit tighter layouts
    const float titleScale = 1.45f;
    font.draw(renderer, boxX + 28.0f, boxY + 24.0f, "HELP & SHORTCUTS", titleScale, {255, 220, 0, 255});

    const float contentPadding = 32.0f;
    const float columnGap = 30.0f;
    const float columnWidth = (boxW - contentPadding * 2.0f - columnGap) * 0.5f;
    const float leftColumnX = boxX + contentPadding;
    const float rightColumnX = leftColumnX + columnWidth + columnGap;
    const float footerHeight = 46.0f;
    const float footerPadding = 18.0f;

    // Slightly reduced scales for a more compact popup
    const float sectionTitleScale = 1.0f;
    const float comboScale = 0.82f;
    const float descBaseScale = 0.72f;
    // Increase vertical spacing between combo label and description for readability
    const float comboSpacing = 28.0f;
    // Increase spacing between sections and after titles
    const float sectionSpacing = 22.0f;

    // Helper to draw text with extra letter-spacing (tracking) for section titles
    auto drawSpaced = [&](float sx, float sy, const char* text, float scale, SDL_Color color, float extraPx) {
        std::string stext(text);
        float x = sx;
        for (size_t i = 0; i < stext.size(); ++i) {
            std::string ch(1, stext[i]);
            font.draw(renderer, x, sy, ch.c_str(), scale, color);
            int cw = 0, chh = 0;
            font.measure(ch.c_str(), scale, cw, chh);
            x += static_cast<float>(cw) + extraPx;
        }
    };

    auto drawSection = [&](float startX, float& cursorY, const char* title, const auto& entries) {
        drawSpaced(startX, cursorY, title, sectionTitleScale, {180, 200, 255, 255}, 4.0f);
        // extra gap after section title
        cursorY += 34.0f;
        for (const auto& entry : entries) {
            font.draw(renderer, startX, cursorY, entry.combo, comboScale, {255, 255, 255, 255});
            // larger spacing between combo label and description
            cursorY += comboSpacing;

            float descScale = fitScale(font, entry.description, descBaseScale, columnWidth - 10.0f);
            font.draw(renderer, startX, cursorY, entry.description, descScale, {200, 210, 230, 255});
            int descW = 0, descH = 0;
            font.measure(entry.description, descScale, descW, descH);
            // a bit more space after description row
            cursorY += static_cast<float>(descH) + 14.0f;
        }
        cursorY += sectionSpacing;
    };

    float leftCursorY = boxY + 80.0f;
    float rightCursorY = boxY + 80.0f;
    drawSection(leftColumnX, leftCursorY, "GENERAL", generalShortcuts);
    drawSection(leftColumnX, leftCursorY, "MENUS", menuShortcuts);
    drawSection(rightColumnX, rightCursorY, "GAMEPLAY", gameplayShortcuts);

    SDL_FRect footerRect{
        boxX + contentPadding,
        boxY + boxH - contentPadding - footerHeight,
        boxW - contentPadding * 2.0f,
        footerHeight
    };
    drawRect(renderer, footerRect.x, footerRect.y, footerRect.w, footerRect.h, {24, 30, 50, 255});
    SDL_SetRenderDrawColor(renderer, 90, 110, 170, 255);
    SDL_RenderRect(renderer, &footerRect);

    const char* closeLabel = "PRESS F1 OR ESC TO CLOSE";
    float closeScale = fitScale(font, closeLabel, 1.0f, footerRect.w - footerPadding * 2.0f);
    int closeW = 0, closeH = 0;
    font.measure(closeLabel, closeScale, closeW, closeH);
    float closeX = footerRect.x + (footerRect.w - static_cast<float>(closeW)) * 0.5f;
    float closeY = footerRect.y + (footerRect.h - static_cast<float>(closeH)) * 0.5f;
    font.draw(renderer, closeX, closeY, closeLabel, closeScale, {215, 220, 240, 255});
}

} // namespace HelpOverlay
