#pragma once

#include <string>
#include <map>
#include <memory>
#include <vector>
#include <optional>
#include "lumacs/color.hpp"
#include "lumacs/face.hpp"

namespace lumacs {

/// @brief Enumeration of standard UI elements for theming (Legacy).
/// Used for mapping legacy theme definitions to the new Face system.
enum class ThemeElement {
    // Text elements
    Normal,
    Keyword,
    String,
    Comment,
    Function,
    Type,
    Number,
    Constant,
    Error,
    Warning,
    Variable,
    Builtin,
    Preprocessor,
    Operator,

    // UI elements
    StatusLine,
    StatusLineInactive,
    MessageLine,
    LineNumber,
    LineNumberCurrent,
    Cursor,
    Selection,
    SearchMatch,
    SearchFail,
    MatchParen,

    // Minibuffer elements
    MinibufferPrompt,
    MinibufferInput,
    MinibufferCompletion,
    MinibufferMatch,

    // Window elements
    WindowBorder,
    WindowBorderActive,
    WindowSeparator,
    TabLine,
    TabLineSel,

    // Special
    Background,
    Foreground
};

/// @brief Defines a complete visual theme for the editor.
/// 
/// A Theme is a collection of Faces (named sets of visual attributes like color and font style).
/// It supports standard UI elements and custom face names.
class Theme {
public:
    explicit Theme(const std::string& name) : name_(name) {}

    /// @brief Set simple colors for a legacy theme element.
    void set_color(ThemeElement element, const Color& fg, const Color& bg = Color(-1, -1, -1));

    /// @brief Define a face with full attributes.
    void set_face(const std::string& name, const FaceAttributes& attrs);
    
    /// @brief Get attributes for a named face.
    std::optional<FaceAttributes> get_face(const std::string& name) const;

    /// @brief Get foreground color for an element (Legacy).
    Color get_fg_color(ThemeElement element) const;

    /// @brief Get background color for an element (Legacy).
    Color get_bg_color(ThemeElement element) const;

    /// @brief Get ncurses color pair ID for an element (Legacy).
    int get_color_pair(ThemeElement element) const;
    
    /// @brief Get ncurses color pair ID for a named face.
    int get_face_color_pair(const std::string& name) const;
    
    /// @brief Get ncurses attributes (color pair + flags) for a named face.
    int get_face_attributes_ncurses(const std::string& name) const;

    /// @brief Get the theme name.
    const std::string& name() const { return name_; }

    /// @brief Initialize all color pairs for ncurses (must be called after ncurses init).
    void initialize_ncurses_colors();

    /// @brief Helper to convert ThemeElement enum to standard face name string.
    static std::string element_to_face_name(ThemeElement element);

private:
    std::string name_;
    
    // Storage for face definitions
    std::map<std::string, FaceAttributes> faces_;
    
    // Cache for ncurses pairs (mutable because generated on demand or at init)
    mutable std::map<std::string, int> face_pairs_;
    mutable int next_pair_id_ = 1;

    // Helper for inheritance resolution
    std::optional<FaceAttributes> get_face_recursive(const std::string& name, int depth) const;
};

/// @brief Manages available themes and the active theme.
class ThemeManager {
public:
    /// @brief Register a new theme.
    void register_theme(std::shared_ptr<Theme> theme);

    /// @brief Set the active theme by name.
    void set_active_theme(const std::string& name);

    /// @brief Get the currently active theme.
    std::shared_ptr<Theme> active_theme() const { return active_theme_; }

    /// @brief Get a list of all registered theme names.
    std::vector<std::string> theme_names() const;

    /// @brief Create and register the set of built-in themes.
    void create_default_themes();

    // Factory methods for built-in themes
    std::shared_ptr<Theme> create_everforest_theme();
    std::shared_ptr<Theme> create_default_theme();
    std::shared_ptr<Theme> create_dracula_theme();
    std::shared_ptr<Theme> create_solarized_dark_theme();
    std::shared_ptr<Theme> create_nord_theme();
    std::shared_ptr<Theme> create_gruvbox_light_theme();

private:
    std::map<std::string, std::shared_ptr<Theme>> themes_;
    std::shared_ptr<Theme> active_theme_;
};

} // namespace lumacs