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

#pragma once

#include "imgui.h"

namespace dragonx {
namespace ui {
namespace material {

// ============================================================================
// Material Design 8dp Grid System
// ============================================================================
// All spacing in Material Design is based on an 8dp grid.
// https://m2.material.io/design/layout/spacing-methods.html

constexpr float kGridUnit = 8.0f;  // Base unit in dp (device-independent pixels)

// ============================================================================
// Spacing Scale
// ============================================================================
// Use these values for all margins, padding, and gaps

namespace spacing {

constexpr float Xxs  = 2.0f;   // 0.25x - Very tight spacing
constexpr float Xs   = 4.0f;   // 0.5x  - Extra small
constexpr float Sm   = 8.0f;   // 1x    - Small (default minimum)
constexpr float Md   = 16.0f;  // 2x    - Medium (default standard)
constexpr float Lg   = 24.0f;  // 3x    - Large
constexpr float Xl   = 32.0f;  // 4x    - Extra large
constexpr float Xxl  = 40.0f;  // 5x    - Double extra large
constexpr float Xxxl = 48.0f;  // 6x    - Triple extra large

// Multiplier helpers
constexpr float Grid(float multiplier) { return kGridUnit * multiplier; }

} // namespace spacing

// ============================================================================
// Component Dimensions
// ============================================================================
// Standard sizes for Material Design components

namespace size {

// Buttons
constexpr float ButtonHeight       = 36.0f;
constexpr float ButtonMinWidth     = 64.0f;
constexpr float ButtonPaddingH     = 16.0f;
constexpr float ButtonPaddingV     = 8.0f;
constexpr float ButtonIconGap      = 8.0f;   // Gap between icon and label
constexpr float ButtonCornerRadius = 4.0f;

// FAB (Floating Action Button)
constexpr float FabSize            = 56.0f;
constexpr float FabMiniSize        = 40.0f;
constexpr float FabExtendedHeight  = 48.0f;
constexpr float FabExtendedPadding = 16.0f;
constexpr float FabCornerRadius    = 16.0f;  // Half of mini size for circle

// Icons
constexpr float IconSize           = 24.0f;
constexpr float IconSizeSm         = 18.0f;
constexpr float IconSizeLg         = 36.0f;
constexpr float IconButtonSize     = 48.0f;  // Touch target for icon buttons

// App Bar / Toolbar
constexpr float AppBarHeight       = 56.0f;   // Mobile
constexpr float AppBarHeightLarge  = 64.0f;   // Desktop
constexpr float AppBarPadding      = 16.0f;

// Navigation
constexpr float NavDrawerWidth     = 256.0f;
constexpr float NavRailWidth       = 72.0f;
constexpr float NavItemHeight      = 48.0f;
constexpr float NavItemPadding     = 12.0f;
constexpr float NavSectionPadding  = 8.0f;

// Cards
constexpr float CardCornerRadius   = 4.0f;
constexpr float CardPadding        = 16.0f;
constexpr float CardElevation      = 1.0f;   // Default elevation in dp

// Dialogs
constexpr float DialogMinWidth     = 280.0f;
constexpr float DialogMaxWidth     = 560.0f;
constexpr float DialogPadding      = 24.0f;
constexpr float DialogTitlePadding = 20.0f;
constexpr float DialogActionGap    = 8.0f;
constexpr float DialogCornerRadius = 4.0f;

// Lists
constexpr float ListItemHeight       = 48.0f;  // Single line
constexpr float ListItemHeightTwoLine = 64.0f;
constexpr float ListItemHeightThreeLine = 88.0f;
constexpr float ListItemPaddingH     = 16.0f;
constexpr float ListAvatarSize       = 40.0f;
constexpr float ListIconMargin       = 32.0f;

// Text Fields
constexpr float TextFieldHeight      = 56.0f;
constexpr float TextFieldPadding     = 16.0f;
constexpr float TextFieldDenseHeight = 40.0f;
constexpr float TextFieldCornerRadius = 4.0f;

// Chips
constexpr float ChipHeight           = 32.0f;
constexpr float ChipPaddingH         = 12.0f;
constexpr float ChipCornerRadius     = 16.0f;

// Tabs
constexpr float TabHeight            = 48.0f;
constexpr float TabMinWidth          = 90.0f;
constexpr float TabMaxWidth          = 360.0f;
constexpr float TabPaddingH          = 16.0f;
constexpr float TabIndicatorHeight   = 2.0f;

// Snackbar
constexpr float SnackbarMinWidth     = 288.0f;
constexpr float SnackbarMaxWidth     = 568.0f;
constexpr float SnackbarHeight       = 48.0f;
constexpr float SnackbarPadding      = 8.0f;
constexpr float SnackbarMargin       = 8.0f;

// Dividers
constexpr float DividerThickness     = 1.0f;
constexpr float DividerInset         = 16.0f;  // For inset dividers

} // namespace size

// ============================================================================
// Responsive Breakpoints
// ============================================================================
// Based on Material Design responsive layout grid

namespace breakpoint {

constexpr float Xs = 0.0f;      // Extra small: 0-599dp
constexpr float Sm = 600.0f;    // Small: 600-904dp
constexpr float Md = 905.0f;    // Medium: 905-1239dp
constexpr float Lg = 1240.0f;   // Large: 1240-1439dp
constexpr float Xl = 1440.0f;   // Extra large: 1440dp+

// Returns the current breakpoint category
enum class Category { Xs, Sm, Md, Lg, Xl };

inline Category GetCategory(float windowWidth) {
    if (windowWidth >= Xl) return Category::Xl;
    if (windowWidth >= Lg) return Category::Lg;
    if (windowWidth >= Md) return Category::Md;
    if (windowWidth >= Sm) return Category::Sm;
    return Category::Xs;
}

// Margin values for each breakpoint
inline float GetMargin(Category cat) {
    switch (cat) {
        case Category::Xs: return 16.0f;
        case Category::Sm: return 32.0f;
        case Category::Md: return 32.0f;  // Or fluid centering
        case Category::Lg: return 200.0f;
        case Category::Xl: return 200.0f; // Or fluid centering
    }
    return 16.0f;
}

// Column count for each breakpoint
inline int GetColumns(Category cat) {
    switch (cat) {
        case Category::Xs: return 4;
        case Category::Sm: return 8;
        default: return 12;
    }
}

// Recommended navigation style
enum class NavStyle { BottomNav, NavRail, NavDrawer };

inline NavStyle GetNavStyle(Category cat) {
    switch (cat) {
        case Category::Xs: return NavStyle::BottomNav;
        case Category::Sm:
        case Category::Md: return NavStyle::NavRail;
        default: return NavStyle::NavDrawer;
    }
}

} // namespace breakpoint

// ============================================================================
// Layout Helpers
// ============================================================================

/**
 * @brief Get current window's breakpoint category
 */
inline breakpoint::Category GetCurrentBreakpoint() {
    ImVec2 windowSize = ImGui::GetWindowSize();
    return breakpoint::GetCategory(windowSize.x);
}

/**
 * @brief Get recommended margin for current window
 */
inline float GetCurrentMargin() {
    return breakpoint::GetMargin(GetCurrentBreakpoint());
}

/**
 * @brief Add horizontal spacing (uses 8dp grid)
 * @param units Number of 8dp units (default 1)
 */
inline void HSpace(float units = 1.0f) {
    ImGui::SameLine(0, kGridUnit * units);
}

/**
 * @brief Add vertical spacing (uses 8dp grid)
 * @param units Number of 8dp units (default 1)
 */
inline void VSpace(float units = 1.0f) {
    ImGui::Dummy(ImVec2(0, kGridUnit * units));
}

/**
 * @brief Begin a padded region
 * @param padding Padding in pixels (use spacing:: constants)
 */
inline void BeginPadding(float padding) {
    ImGui::BeginGroup();
    ImGui::Dummy(ImVec2(0, padding));
    ImGui::Indent(padding);
}

/**
 * @brief End a padded region
 * @param padding Same padding used in BeginPadding
 */
inline void EndPadding(float padding) {
    ImGui::Unindent(padding);
    ImGui::Dummy(ImVec2(0, padding));
    ImGui::EndGroup();
}

/**
 * @brief Center the next item horizontally within available width
 * @param itemWidth Width of the item to center
 */
inline void CenterHorizontally(float itemWidth) {
    float availWidth = ImGui::GetContentRegionAvail().x;
    float offset = (availWidth - itemWidth) * 0.5f;
    if (offset > 0) {
        ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offset);
    }
}

/**
 * @brief Calculate column width for responsive grid
 * @param numColumns Number of columns to span
 * @param gutterWidth Gap between columns (default 16dp)
 */
inline float GetColumnWidth(int numColumns = 1, float gutterWidth = spacing::Md) {
    float availWidth = ImGui::GetContentRegionAvail().x;
    auto cat = GetCurrentBreakpoint();
    int totalColumns = breakpoint::GetColumns(cat);
    
    float totalGutter = gutterWidth * (totalColumns - 1);
    float columnWidth = (availWidth - totalGutter) / totalColumns;
    
    return columnWidth * numColumns + gutterWidth * (numColumns - 1);
}

// ============================================================================
// Card Layout Helper
// ============================================================================

struct CardLayout {
    float width;
    float minHeight;
    float padding;
    float cornerRadius;
    int elevation;
    
    CardLayout() 
        : width(0)  // 0 = auto width
        , minHeight(0)
        , padding(size::CardPadding)
        , cornerRadius(size::CardCornerRadius)
        , elevation(1)
    {}
    
    CardLayout& Width(float w) { width = w; return *this; }
    CardLayout& MinHeight(float h) { minHeight = h; return *this; }
    CardLayout& Padding(float p) { padding = p; return *this; }
    CardLayout& CornerRadius(float r) { cornerRadius = r; return *this; }
    CardLayout& Elevation(int e) { elevation = e; return *this; }
};

// ============================================================================
// Navigation Drawer Item
// ============================================================================

struct NavItem {
    const char* label;
    const char* icon;      // Icon font glyph or nullptr
    bool selected;
    bool enabled;
    
    NavItem(const char* lbl, const char* ico = nullptr)
        : label(lbl), icon(ico), selected(false), enabled(true)
    {}
    
    NavItem& Selected(bool s) { selected = s; return *this; }
    NavItem& Enabled(bool e) { enabled = e; return *this; }
};

// ============================================================================
// Alignment Helpers
// ============================================================================

/**
 * @brief Align item to right edge of available space
 * @param itemWidth Width of the item
 */
inline void AlignRight(float itemWidth) {
    float availWidth = ImGui::GetContentRegionAvail().x;
    ImGui::SetCursorPosX(ImGui::GetCursorPosX() + availWidth - itemWidth);
}

/**
 * @brief Push items to start from right side (call before group of items)
 */
inline void BeginRightAlign() {
    ImGui::BeginGroup();
}

/**
 * @brief End right-aligned group and position it
 */
inline void EndRightAlign() {
    ImGui::EndGroup();
    float groupWidth = ImGui::GetItemRectSize().x;
    AlignRight(groupWidth);
}

} // namespace material
} // namespace ui
} // namespace dragonx
