// DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers
// Released under the GPLv3

#pragma once

#include "acrylic.h"
#include "imgui.h"

namespace dragonx {
namespace ui {
namespace effects {

/**
 * @brief ImGui integration for acrylic effects
 * 
 * Provides convenient wrappers around AcrylicMaterial for use with
 * standard ImGui rendering patterns.
 */
namespace ImGuiAcrylic {

// ============================================================================
// Initialization
// ============================================================================

/**
 * @brief Initialize the acrylic system
 * 
 * Call once at application startup, after OpenGL context is created.
 * @return true if successful
 */
bool Init();

/**
 * @brief Shutdown the acrylic system
 * 
 * Call at application shutdown before destroying OpenGL context.
 */
void Shutdown();

/**
 * @brief Check if acrylic is available and initialized
 */
bool IsAvailable();

// ============================================================================
// Frame Operations
// ============================================================================

/**
 * @brief Begin a new frame for acrylic rendering
 * 
 * Call this at the start of your render loop, before any ImGui rendering.
 * This captures the current screen content for blur source.
 * 
 * @param width Viewport width
 * @param height Viewport height
 */
void BeginFrame(int width, int height);

/**
 * @brief End the acrylic frame
 * 
 * Call this after all regular content is rendered but before acrylic overlays.
 * Captures the current framebuffer content for blur.
 */
void CaptureBackground();

/**
 * @brief Invalidate the acrylic capture so the next frame re-captures
 *        and re-blurs.  Call after theme/skin changes that alter the
 *        background gradient, image, or colors.
 */
void InvalidateCapture();

/**
 * @brief Get a draw callback for background capture.
 *
 * Insert this callback at the end of the BackgroundDrawList (after all
 * background commands).  During RenderDrawData() it fires right after
 * the background is rasterized — before any UI windows — and blits
 * the clean background into the acrylic capture buffer.
 *
 * Usage in main.cpp:
 * @code
 *   bgDL->AddCallback(ImGuiAcrylic::GetBackgroundCaptureCallback(), nullptr);
 *   bgDL->AddCallback(ImDrawCallback_ResetRenderState, nullptr);
 * @endcode
 */
ImDrawCallback GetBackgroundCaptureCallback();

/**
 * @brief Returns a draw callback that captures the LIVE framebuffer (no dirtyFrames_
 * gate). Insert it at the START of a full-window modal overlay's draw list — before the
 * overlay draws its own backdrop — so the acrylic blurs the live app UI behind the modal:
 * @code
 *   ImDrawList* dl = ImGui::GetWindowDrawList();
 *   dl->AddCallback(ImGuiAcrylic::GetLiveCaptureCallback(), nullptr);
 *   dl->AddCallback(ImDrawCallback_ResetRenderState, nullptr);
 *   // ... then draw the overlay's acrylic/dim backdrop ...
 * @endcode
 */
ImDrawCallback GetLiveCaptureCallback();

// ============================================================================
// Drawing Functions
// ============================================================================

/**
 * @brief Draw an acrylic-filled rectangle
 * 
 * @param drawList ImGui draw list to add the rectangle to
 * @param pMin Top-left corner (screen coordinates)
 * @param pMax Bottom-right corner (screen coordinates)
 * @param params Acrylic appearance parameters
 * @param rounding Corner rounding radius
 */
void DrawAcrylicRect(ImDrawList* drawList, 
                     const ImVec2& pMin, const ImVec2& pMax,
                     const AcrylicParams& params,
                     float rounding = 0.0f);

/**
 * @brief Draw an acrylic-filled rectangle with default preset
 */
void DrawAcrylicRect(ImDrawList* drawList,
                     const ImVec2& pMin, const ImVec2& pMax,
                     float rounding = 0.0f);

// ============================================================================
// Window Wrappers
// ============================================================================

/**
 * @brief Begin an acrylic-background window
 * 
 * Works like ImGui::Begin but with acrylic background.
 * Must be paired with EndAcrylicWindow().
 * 
 * @param name Window name/ID
 * @param p_open Optional close button flag
 * @param flags ImGui window flags
 * @param params Acrylic appearance parameters
 * @return true if window is visible
 */
bool BeginAcrylicWindow(const char* name, bool* p_open = nullptr,
                        ImGuiWindowFlags flags = 0,
                        const AcrylicParams& params = AcrylicMaterial::getPopupPreset());

/**
 * @brief End an acrylic window
 */
void EndAcrylicWindow();

// ============================================================================
// Child Region Wrappers
// ============================================================================

/**
 * @brief Begin an acrylic child region
 * 
 * Works like ImGui::BeginChild but with acrylic background.
 * Must be paired with EndAcrylicChild().
 * 
 * @param str_id Child region ID
 * @param size Child region size (0,0 = auto)
 * @param params Acrylic appearance parameters
 * @param child_flags ImGui child flags
 * @param window_flags ImGui window flags for the child
 * @return true if child is visible
 */
bool BeginAcrylicChild(const char* str_id, 
                       const ImVec2& size = ImVec2(0, 0),
                       const AcrylicParams& params = AcrylicMaterial::getDarkPreset(),
                       ImGuiChildFlags child_flags = 0,
                       ImGuiWindowFlags window_flags = 0);

/**
 * @brief End an acrylic child region
 */
void EndAcrylicChild();

// ============================================================================
// Popup Wrappers
// ============================================================================

/**
 * @brief Begin an acrylic popup
 * 
 * Works like ImGui::BeginPopup but with acrylic background.
 * Must be paired with EndAcrylicPopup().
 * 
 * @param str_id Popup ID
 * @param flags ImGui window flags
 * @param params Acrylic appearance parameters
 * @return true if popup is open
 */
bool BeginAcrylicPopup(const char* str_id,
                       ImGuiWindowFlags flags = 0,
                       const AcrylicParams& params = AcrylicMaterial::getPopupPreset());

/**
 * @brief End an acrylic popup
 */
void EndAcrylicPopup();

/**
 * @brief Begin an acrylic modal popup
 * 
 * Works like ImGui::BeginPopupModal but with acrylic background.
 * Must be paired with EndAcrylicPopup().
 */
bool BeginAcrylicPopupModal(const char* name, bool* p_open = nullptr,
                            ImGuiWindowFlags flags = 0,
                            const AcrylicParams& params = AcrylicMaterial::getPopupPreset());

// ============================================================================
// Context Menu Helpers
// ============================================================================

/**
 * @brief Begin an acrylic context menu for the last item
 * 
 * Works like ImGui::BeginPopupContextItem but with acrylic background.
 * Must be paired with EndAcrylicPopup().
 * 
 * @param str_id Popup ID (nullptr to use last item ID)
 * @param popup_flags ImGui popup flags
 * @param params Acrylic appearance parameters
 * @return true if context menu is open
 */
bool BeginAcrylicContextItem(const char* str_id = nullptr,
                             ImGuiPopupFlags popup_flags = 0,
                             const AcrylicParams& params = AcrylicMaterial::getPopupPreset());

/**
 * @brief Begin an acrylic context menu for the current window
 * 
 * Works like ImGui::BeginPopupContextWindow but with acrylic background.
 * Must be paired with EndAcrylicPopup().
 */
bool BeginAcrylicContextWindow(const char* str_id = nullptr,
                               ImGuiPopupFlags popup_flags = 0,
                               const AcrylicParams& params = AcrylicMaterial::getPopupPreset());

// ============================================================================
// Sidebar Helper
// ============================================================================

/**
 * @brief Draw an acrylic sidebar background
 * 
 * Convenience function for drawing sidebar with DragonX branded acrylic.
 * 
 * @param width Sidebar width
 * @param params Optional custom parameters (default: sidebar preset)
 */
void DrawSidebarBackground(float width, 
                           const AcrylicParams& params = AcrylicMaterial::getSidebarPreset());

// ============================================================================
// Settings
// ============================================================================

/**
 * @brief Set global acrylic quality
 */
void SetQuality(AcrylicQuality quality);

/**
 * @brief Get current quality setting
 */
AcrylicQuality GetQuality();

/**
 * @brief Enable/disable acrylic globally
 * 
 * When disabled, all acrylic functions fall back to solid colors.
 */
void SetEnabled(bool enabled);

/**
 * @brief Check if acrylic is enabled
 */
bool IsEnabled();

/**
 * @brief Set blur radius multiplier (scales all blur radii)
 * @param multiplier Value from 0.5 to 2.0 (1.0 = default)
 */
void SetBlurMultiplier(float multiplier);

/**
 * @brief Get current blur multiplier
 */
float GetBlurMultiplier();

/**
 * @brief Set reduced transparency mode (accessibility)
 * 
 * When enabled, uses solid fallback colors instead of blur effects.
 */
void SetReducedTransparency(bool reduced);

/**
 * @brief Check if reduced transparency mode is active
 */
bool GetReducedTransparency();

/**
 * @brief Set UI opacity multiplier for cards/sidebar (0.3–1.0, 1=opaque)
 */
void SetUIOpacity(float opacity);

/**
 * @brief Get UI opacity multiplier
 */
float GetUIOpacity();

/**
 * @brief Set noise opacity multiplier (0.0 = no noise, 1.0 = default, 2.0 = max)
 */
void SetNoiseOpacity(float multiplier);

/**
 * @brief Get noise opacity multiplier
 */
float GetNoiseOpacity();

/**
 * @brief Get full acrylic settings
 */
const AcrylicSettings& GetSettings();

/**
 * @brief Set full acrylic settings
 */
void SetSettings(const AcrylicSettings& settings);

// ============================================================================
// Presets — combined quality + blur amount
// ============================================================================

/// Number of built-in presets (Off … Frosted)
constexpr int kPresetCount = 6;

/**
 * @brief Apply a preset that sets both quality and blur multiplier.
 * @param preset Index 0–5 (Off, Subtle, Light, Standard, Strong, Frosted)
 */
void SetPreset(int preset);

/**
 * @brief Derive the closest preset index from current quality + blur.
 */
int GetPreset();

/**
 * @brief Human-readable label for a preset index.
 */
const char* GetPresetLabel(int preset);

/**
 * @brief Get the quality enum for a given preset index.
 */
AcrylicQuality PresetQuality(int preset);

/**
 * @brief Get the blur multiplier for a given preset index.
 */
float PresetBlur(int preset);

/**
 * @brief Find closest preset matching a quality + blur pair.
 *        Useful for migrating from legacy separate settings.
 */
int MatchPreset(AcrylicQuality quality, float blur);

/**
 * @brief Apply a continuous blur amount.
 *
 * Uses Low quality (like the old "Subtle" preset) at any non-zero blur
 * level, giving fine-grained control without stepped presets.
 * When blur is near zero the effect is disabled entirely.
 *
 * @param blur Blur multiplier (0.0 = off, up to 4.0 = maximum)
 */
void ApplyBlurAmount(float blur);

} // namespace ImGuiAcrylic

} // namespace effects
} // namespace ui
} // namespace dragonx
