#include "lumacs/theme.hpp"
#include <ncurses.h>
#include <algorithm>
#include <climits>

namespace lumacs {

static std::map<Color, int> color_cache;
static int next_color_id = 8; // Start after the basic 8 colors

int Color::to_ncurses_color() const {
    // Handle default colors
    if (r == -1 && g == -1 && b == -1) {
        return -1; // Use default
    }
    
    // Check cache first
    auto it = color_cache.find(*this);
    if (it != color_cache.end()) {
        return it->second;
    }
    
    // Check if we can create new colors
    if (can_change_color() && next_color_id < COLOR_PAIRS) {
        int color_id = next_color_id++;
        // Scale RGB values to 0-1000 range for ncurses
        int nr = (r * 1000) / 255;
        int ng = (g * 1000) / 255;
        int nb = (b * 1000) / 255;
        
        init_color(color_id, nr, ng, nb);
        color_cache[*this] = color_id;
        return color_id;
    }
    
    // Fallback to closest basic color
    int min_dist = INT_MAX;
    int closest = COLOR_WHITE;
    
    struct BasicColor { int id; int r, g, b; };
    BasicColor basic_colors[] = {
        {COLOR_BLACK, 0, 0, 0},
        {COLOR_RED, 255, 0, 0},
        {COLOR_GREEN, 0, 255, 0},
        {COLOR_YELLOW, 255, 255, 0},
        {COLOR_BLUE, 0, 0, 255},
        {COLOR_MAGENTA, 255, 0, 255},
        {COLOR_CYAN, 0, 255, 255},
        {COLOR_WHITE, 255, 255, 255}
    };
    
    for (auto& basic : basic_colors) {
        int dr = r - basic.r;
        int dg = g - basic.g;
        int db = b - basic.b;
        int dist = dr*dr + dg*dg + db*db;
        if (dist < min_dist) {
            min_dist = dist;
            closest = basic.id;
        }
    }
    
    return closest;
}

std::string Theme::element_to_face_name(ThemeElement element) {
    switch (element) {
        case ThemeElement::Normal: return "default";
        case ThemeElement::Keyword: return "font-lock-keyword-face";
        case ThemeElement::String: return "font-lock-string-face";
        case ThemeElement::Comment: return "font-lock-comment-face";
        case ThemeElement::Function: return "font-lock-function-name-face";
        case ThemeElement::Type: return "font-lock-type-face";
        case ThemeElement::Number: return "font-lock-constant-face"; // Mapping number to constant for now
        case ThemeElement::Constant: return "font-lock-constant-face";
        case ThemeElement::Error: return "error";
        case ThemeElement::StatusLine: return "mode-line";
        case ThemeElement::StatusLineInactive: return "mode-line-inactive";
        case ThemeElement::MessageLine: return "minibuffer-prompt";
        case ThemeElement::LineNumber: return "line-number";
        case ThemeElement::Cursor: return "cursor";
        case ThemeElement::Selection: return "region";
        case ThemeElement::SearchMatch: return "isearch";
        case ThemeElement::SearchFail: return "isearch-fail";
        case ThemeElement::WindowBorder: return "window-divider";
        case ThemeElement::WindowBorderActive: return "window-divider-active";
        case ThemeElement::Background: return "default"; // Background usually part of default
        default: return "default";
    }
}

void Theme::set_face(const std::string& name, const FaceAttributes& attrs) {
    faces_[name] = attrs;
    // Invalidate cache
    face_pairs_.erase(name);
}

std::optional<FaceAttributes> Theme::get_face(const std::string& name) const {
    return get_face_recursive(name, 0);
}

std::optional<FaceAttributes> Theme::get_face_recursive(const std::string& name, int depth) const {
    // Prevent infinite recursion
    if (depth > 10) {
        return std::nullopt;
    }

    auto it = faces_.find(name);
    if (it == faces_.end()) {
        return std::nullopt;
    }

    FaceAttributes current = it->second;

    // Handle inheritance
    if (current.inherit) {
        auto parent = get_face_recursive(*current.inherit, depth + 1);
        if (parent) {
            // Start with parent attributes
            FaceAttributes final_attrs = *parent;
            // Merge current (child) attributes on top, overriding parent
            final_attrs.merge(current);
            return final_attrs;
        }
    }

    return current;
}

void Theme::set_color(ThemeElement element, const Color& fg, const Color& bg) {
    std::string face_name = element_to_face_name(element);
    FaceAttributes attrs;
    attrs.foreground = fg;
    attrs.background = bg;
    
    // Merge with existing if possible, or set new
    auto existing = get_face(face_name);
    if (existing) {
        FaceAttributes merged = *existing;
        merged.foreground = fg;
        merged.background = bg;
        set_face(face_name, merged);
    } else {
        set_face(face_name, attrs);
    }
}

Color Theme::get_fg_color(ThemeElement element) const {
    auto face = get_face(element_to_face_name(element));
    if (face && face->foreground) return *face->foreground;
    return Color(255, 255, 255);
}

Color Theme::get_bg_color(ThemeElement element) const {
    auto face = get_face(element_to_face_name(element));
    if (face && face->background) return *face->background;
    return Color(-1, -1, -1);
}

int Theme::get_color_pair(ThemeElement element) const {
    return get_face_color_pair(element_to_face_name(element));
}

int Theme::get_face_color_pair(const std::string& name) const {
    // Check cache
    auto it = face_pairs_.find(name);
    if (it != face_pairs_.end()) {
        return COLOR_PAIR(it->second);
    }
    
    // Get attributes
    auto face = get_face(name);
    
    // If face not found, try default
    if (!face && name != "default") {
        face = get_face("default");
    }
    
    if (!face) {
        return 0; // No attributes found
    }
    
    // Create new color pair
    int pair_id = next_pair_id_++;
    if (pair_id >= COLOR_PAIRS) {
        return 0; // Fallback to default if out of pairs
    }
    
    // Resolve colors (fallback to default if missing)
    Color fg = face->foreground.value_or(Color(255, 255, 255));
    Color bg = face->background.value_or(Color(-1, -1, -1));
    
    // Special case: if this is a face that should inherit from default, we might need logic here.
    // For now, just use what we have.
    
    int fg_color = fg.to_ncurses_color();
    int bg_color = bg.to_ncurses_color();
    
    init_pair(pair_id, fg_color, bg_color);
    face_pairs_[name] = pair_id;
    
    return COLOR_PAIR(pair_id);
}

int Theme::get_face_attributes_ncurses(const std::string& name) const {
    int pair = get_face_color_pair(name);
    int attrs = pair;
    
    auto face = get_face(name);
    if (!face && name != "default") {
        face = get_face("default");
    }
    
    if (face) {
        if (face->weight == FontWeight::Bold) attrs |= A_BOLD;
        // A_ITALIC might not be defined on all ncurses versions, use ifdef or ignore for now
        #ifdef A_ITALIC
        if (face->slant == FontSlant::Italic) attrs |= A_ITALIC;
        #endif
        if (face->underline.value_or(false)) attrs |= A_UNDERLINE;
        if (face->inverse.value_or(false)) attrs |= A_REVERSE;
    }
    
    return attrs;
}

void Theme::initialize_ncurses_colors() {
    // Initialize known standard faces
    std::vector<std::string> standard_faces = {
        "default", "font-lock-keyword-face", "font-lock-string-face", "font-lock-comment-face",
        "font-lock-function-name-face", "font-lock-type-face", "font-lock-constant-face",
        "error", "mode-line", "mode-line-inactive", "minibuffer-prompt", "line-number",
        "cursor", "region", "isearch", "isearch-fail", "window-divider"
    };
    
    for (const auto& name : standard_faces) {
        get_face_color_pair(name);
    }
}

// ... (ThemeManager implementation remains mostly same, but ensures we set faces correctly)

void ThemeManager::register_theme(std::shared_ptr<Theme> theme) {
    themes_[theme->name()] = theme;
    if (!active_theme_) {
        active_theme_ = theme;
    }
}

void ThemeManager::set_active_theme(const std::string& name) {
    auto it = themes_.find(name);
    if (it != themes_.end()) {
        active_theme_ = it->second;
        active_theme_->initialize_ncurses_colors();
    }
}

std::vector<std::string> ThemeManager::theme_names() const {
    std::vector<std::string> names;
    for (auto& [name, theme] : themes_) {
        names.push_back(name);
    }
    return names;
}

void ThemeManager::create_default_themes() {
    register_theme(create_default_theme());
    register_theme(create_everforest_theme());
    register_theme(create_dracula_theme());
    register_theme(create_solarized_dark_theme());
    register_theme(create_nord_theme());
    register_theme(create_gruvbox_light_theme());
}

std::shared_ptr<Theme> ThemeManager::create_everforest_theme() {
    auto theme = std::make_shared<Theme>("everforest-dark");
    
    // Everforest color palette
    Color bg0(45, 49, 48);          // #2d3139
    Color bg1(52, 56, 56);          // #343839
    Color fg(211, 198, 170);        // #d3c6aa
    
    Color red(230, 126, 128);       // #e67e80
    Color orange(230, 152, 117);    // #e69875
    Color yellow(219, 188, 127);    // #dbbc7f
    Color green(167, 192, 128);     // #a7c080
    Color cyan(131, 192, 146);      // #83c092
    Color blue(125, 174, 163);      // #7fbbb3
    Color purple(208, 135, 162);    // #d699b5
    Color grey(146, 131, 116);      // #928374
    
    // Text elements via set_color (which now sets faces)
    theme->set_color(ThemeElement::Normal, fg, bg0);
    theme->set_color(ThemeElement::String, green, bg0);
    theme->set_color(ThemeElement::Function, blue, bg0);
    theme->set_color(ThemeElement::Type, yellow, bg0);
    theme->set_color(ThemeElement::Number, purple, bg0);
    theme->set_color(ThemeElement::Constant, orange, bg0);
    theme->set_color(ThemeElement::Error, Color(255, 255, 255), red);

    // Demonstrate rich faces (Bold/Italic)
    FaceAttributes keyword_attrs;
    keyword_attrs.foreground = red;
    keyword_attrs.background = bg0;
    keyword_attrs.weight = FontWeight::Bold;
    theme->set_face("font-lock-keyword-face", keyword_attrs);

    FaceAttributes comment_attrs;
    comment_attrs.foreground = grey;
    comment_attrs.background = bg0;
    comment_attrs.slant = FontSlant::Italic;
    theme->set_face("font-lock-comment-face", comment_attrs);
    
    // UI elements
    theme->set_color(ThemeElement::StatusLine, bg0, fg);
    theme->set_color(ThemeElement::StatusLineInactive, grey, bg1);
    theme->set_color(ThemeElement::MessageLine, fg, bg0);
    theme->set_color(ThemeElement::LineNumber, grey, bg0);
    theme->set_color(ThemeElement::Cursor, bg0, fg);
    theme->set_color(ThemeElement::Selection, Color(255, 255, 255), blue);
    theme->set_color(ThemeElement::SearchMatch, bg0, yellow);
    theme->set_color(ThemeElement::SearchFail, Color(255, 255, 255), red);
    
    // Window elements
    theme->set_color(ThemeElement::WindowBorder, grey, bg0);
    theme->set_color(ThemeElement::WindowBorderActive, cyan, bg0);
    theme->set_color(ThemeElement::Background, fg, bg0);
    
    return theme;
}

std::shared_ptr<Theme> ThemeManager::create_default_theme() {
    auto theme = std::make_shared<Theme>("default");
    
    // Simple default theme using basic colors
    theme->set_color(ThemeElement::Normal, Color(255, 255, 255), Color(-1, -1, -1));
    theme->set_color(ThemeElement::Keyword, Color(0, 0, 255), Color(-1, -1, -1));
    theme->set_color(ThemeElement::String, Color(0, 255, 0), Color(-1, -1, -1));
    theme->set_color(ThemeElement::Comment, Color(128, 128, 128), Color(-1, -1, -1));
    theme->set_color(ThemeElement::Function, Color(0, 255, 255), Color(-1, -1, -1));
    theme->set_color(ThemeElement::Type, Color(255, 255, 0), Color(-1, -1, -1));
    theme->set_color(ThemeElement::Number, Color(255, 0, 255), Color(-1, -1, -1));
    theme->set_color(ThemeElement::Constant, Color(255, 0, 255), Color(-1, -1, -1));
    theme->set_color(ThemeElement::Error, Color(255, 255, 255), Color(255, 0, 0));
    
    theme->set_color(ThemeElement::StatusLine, Color(0, 0, 0), Color(255, 255, 255));
    theme->set_color(ThemeElement::StatusLineInactive, Color(128, 128, 128), Color(255, 255, 255));
    theme->set_color(ThemeElement::MessageLine, Color(255, 255, 255), Color(-1, -1, -1));
    theme->set_color(ThemeElement::LineNumber, Color(128, 128, 128), Color(-1, -1, -1));
    theme->set_color(ThemeElement::Cursor, Color(0, 0, 0), Color(255, 255, 255));
    theme->set_color(ThemeElement::Selection, Color(255, 255, 255), Color(0, 0, 255));
    theme->set_color(ThemeElement::SearchMatch, Color(0, 0, 0), Color(255, 255, 0));
    theme->set_color(ThemeElement::SearchFail, Color(255, 255, 255), Color(255, 0, 0));
    theme->set_color(ThemeElement::WindowBorder, Color(255, 255, 255), Color(-1, -1, -1));
    theme->set_color(ThemeElement::WindowBorderActive, Color(0, 255, 255), Color(-1, -1, -1));
    theme->set_color(ThemeElement::Background, Color(255, 255, 255), Color(-1, -1, -1));
    
    return theme;
}

std::shared_ptr<Theme> ThemeManager::create_dracula_theme() {
    auto theme = std::make_shared<Theme>("dracula");
    
    // Dracula color palette
    Color bg(40, 42, 54);             // #282a36 - Background
    Color current_line(68, 71, 90);   // #44475a - Current Line
    Color fg(248, 248, 242);          // #f8f8f2 - Foreground
    Color comment(98, 114, 164);      // #6272a4 - Comment
    Color cyan(139, 233, 253);        // #8be9fd - Cyan
    Color green(80, 250, 123);        // #50fa7b - Green
    Color orange(255, 184, 108);      // #ffb86c - Orange
    Color pink(255, 121, 198);        // #ff79c6 - Pink
    Color purple(189, 147, 249);      // #bd93f9 - Purple
    Color red(255, 85, 85);           // #ff5555 - Red
    Color yellow(241, 250, 140);      // #f1fa8c - Yellow
    
    // Text elements
    theme->set_color(ThemeElement::Normal, fg, bg);
    theme->set_color(ThemeElement::Keyword, pink, bg);
    theme->set_color(ThemeElement::String, yellow, bg);
    theme->set_color(ThemeElement::Comment, comment, bg);
    theme->set_color(ThemeElement::Function, green, bg);
    theme->set_color(ThemeElement::Type, cyan, bg);
    theme->set_color(ThemeElement::Number, purple, bg);
    theme->set_color(ThemeElement::Constant, orange, bg);
    theme->set_color(ThemeElement::Error, fg, red);
    
    // UI elements
    theme->set_color(ThemeElement::StatusLine, bg, purple);
    theme->set_color(ThemeElement::StatusLineInactive, comment, current_line);
    theme->set_color(ThemeElement::MessageLine, fg, bg);
    theme->set_color(ThemeElement::LineNumber, comment, bg);
    theme->set_color(ThemeElement::Cursor, bg, fg);
    theme->set_color(ThemeElement::Selection, fg, current_line);
    theme->set_color(ThemeElement::SearchMatch, bg, orange);
    theme->set_color(ThemeElement::SearchFail, fg, red);
    
    // Window elements
    theme->set_color(ThemeElement::WindowBorder, comment, bg);
    theme->set_color(ThemeElement::WindowBorderActive, pink, bg);
    theme->set_color(ThemeElement::Background, fg, bg);
    
    return theme;
}

std::shared_ptr<Theme> ThemeManager::create_solarized_dark_theme() {
    auto theme = std::make_shared<Theme>("solarized-dark");
    
    // Solarized Dark color palette
    Color base03(0, 43, 54);      // background
    Color base02(7, 54, 66);      // background highlights
    Color base01(88, 110, 117);   // comments / secondary content
    Color base00(101, 123, 131);  // body text / default code / primary content
    Color base0(131, 148, 150);   // primary content / body text
    Color base1(147, 161, 161);   // optional emphasized content
    Color base2(238, 232, 213);   // background highlights
    Color base3(253, 246, 227);   // background
    
    Color yellow(181, 137, 0);    // constants
    Color orange(203, 75, 22);    // regex, numbers
    Color red(220, 50, 47);       // keywords
    Color magenta(211, 54, 130);  // strings
    Color violet(108, 113, 196);  // functions
    Color blue(38, 139, 210);     // variables
    Color cyan(42, 161, 152);     // special
    Color green(133, 153, 0);     // types

    // Set face attributes using the modern face system
    FaceAttributes normal_attrs;
    normal_attrs.foreground = base0;
    normal_attrs.background = base03;
    theme->set_face("normal", normal_attrs);

    FaceAttributes keyword_attrs;
    keyword_attrs.foreground = red;
    keyword_attrs.background = base03;
    keyword_attrs.weight = FontWeight::Bold;
    theme->set_face("keyword", keyword_attrs);

    FaceAttributes string_attrs;
    string_attrs.foreground = magenta;
    string_attrs.background = base03;
    theme->set_face("string", string_attrs);

    FaceAttributes comment_attrs;
    comment_attrs.foreground = base01;
    comment_attrs.background = base03;
    comment_attrs.slant = FontSlant::Italic;
    theme->set_face("comment", comment_attrs);

    FaceAttributes function_attrs;
    function_attrs.foreground = violet;
    function_attrs.background = base03;
    theme->set_face("function", function_attrs);

    FaceAttributes type_attrs;
    type_attrs.foreground = green;
    type_attrs.background = base03;
    theme->set_face("type", type_attrs);

    FaceAttributes number_attrs;
    number_attrs.foreground = orange;
    number_attrs.background = base03;
    theme->set_face("number", number_attrs);

    FaceAttributes constant_attrs;
    constant_attrs.foreground = yellow;
    constant_attrs.background = base03;
    theme->set_face("constant", constant_attrs);

    FaceAttributes error_attrs;
    error_attrs.foreground = red;
    error_attrs.background = base02;
    error_attrs.weight = FontWeight::Bold;
    theme->set_face("error", error_attrs);

    FaceAttributes selection_attrs;
    selection_attrs.foreground = base0;
    selection_attrs.background = base02;
    theme->set_face("selection", selection_attrs);

    FaceAttributes cursor_attrs;
    cursor_attrs.foreground = base03;
    cursor_attrs.background = base0;
    theme->set_face("cursor", cursor_attrs);

    FaceAttributes statusline_attrs;
    statusline_attrs.foreground = base1;
    statusline_attrs.background = base02;
    theme->set_face("statusline", statusline_attrs);

    FaceAttributes statusline_inactive_attrs;
    statusline_inactive_attrs.foreground = base01;
    statusline_inactive_attrs.background = base02;
    theme->set_face("statusline-inactive", statusline_inactive_attrs);

    FaceAttributes line_number_attrs;
    line_number_attrs.foreground = base01;
    line_number_attrs.background = base03;
    theme->set_face("line-number", line_number_attrs);

    FaceAttributes minibuffer_prompt_attrs;
    minibuffer_prompt_attrs.foreground = cyan;
    minibuffer_prompt_attrs.background = base03;
    minibuffer_prompt_attrs.weight = FontWeight::Bold;
    theme->set_face("minibuffer-prompt", minibuffer_prompt_attrs);

    return theme;
}

std::shared_ptr<Theme> ThemeManager::create_nord_theme() {
    auto theme = std::make_shared<Theme>("nord");
    
    // Nord color palette
    Color nord0(46, 52, 64);      // Polar Night - darkest
    Color nord1(59, 66, 82);      // Polar Night
    Color nord2(67, 76, 94);      // Polar Night  
    Color nord3(76, 86, 106);     // Polar Night - lightest
    Color nord4(216, 222, 233);   // Snow Storm - dark
    Color nord5(229, 233, 240);   // Snow Storm
    Color nord6(236, 239, 244);   // Snow Storm - lightest
    Color nord7(143, 188, 187);   // Frost - cyan
    Color nord8(136, 192, 208);   // Frost - light blue
    Color nord9(129, 161, 193);   // Frost - blue
    Color nord10(94, 129, 172);   // Frost - dark blue
    Color nord11(191, 97, 106);   // Aurora - red
    Color nord12(208, 135, 112);  // Aurora - orange
    Color nord13(235, 203, 139);  // Aurora - yellow
    Color nord14(163, 190, 140);  // Aurora - green
    Color nord15(180, 142, 173);  // Aurora - purple

    // Set face attributes
    FaceAttributes normal_attrs;
    normal_attrs.foreground = nord4;
    normal_attrs.background = nord0;
    theme->set_face("normal", normal_attrs);

    FaceAttributes keyword_attrs;
    keyword_attrs.foreground = nord9;
    keyword_attrs.background = nord0;
    keyword_attrs.weight = FontWeight::Bold;
    theme->set_face("keyword", keyword_attrs);

    FaceAttributes string_attrs;
    string_attrs.foreground = nord14;
    string_attrs.background = nord0;
    theme->set_face("string", string_attrs);

    FaceAttributes comment_attrs;
    comment_attrs.foreground = nord3;
    comment_attrs.background = nord0;
    comment_attrs.slant = FontSlant::Italic;
    theme->set_face("comment", comment_attrs);

    FaceAttributes function_attrs;
    function_attrs.foreground = nord8;
    function_attrs.background = nord0;
    theme->set_face("function", function_attrs);

    FaceAttributes type_attrs;
    type_attrs.foreground = nord7;
    type_attrs.background = nord0;
    theme->set_face("type", type_attrs);

    FaceAttributes number_attrs;
    number_attrs.foreground = nord15;
    number_attrs.background = nord0;
    theme->set_face("number", number_attrs);

    FaceAttributes constant_attrs;
    constant_attrs.foreground = nord13;
    constant_attrs.background = nord0;
    theme->set_face("constant", constant_attrs);

    FaceAttributes error_attrs;
    error_attrs.foreground = nord11;
    error_attrs.background = nord1;
    error_attrs.weight = FontWeight::Bold;
    theme->set_face("error", error_attrs);

    FaceAttributes selection_attrs;
    selection_attrs.foreground = nord4;
    selection_attrs.background = nord2;
    theme->set_face("selection", selection_attrs);

    FaceAttributes cursor_attrs;
    cursor_attrs.foreground = nord0;
    cursor_attrs.background = nord4;
    theme->set_face("cursor", cursor_attrs);

    FaceAttributes statusline_attrs;
    statusline_attrs.foreground = nord6;
    statusline_attrs.background = nord1;
    theme->set_face("statusline", statusline_attrs);

    FaceAttributes statusline_inactive_attrs;
    statusline_inactive_attrs.foreground = nord3;
    statusline_inactive_attrs.background = nord1;
    theme->set_face("statusline-inactive", statusline_inactive_attrs);

    FaceAttributes line_number_attrs;
    line_number_attrs.foreground = nord3;
    line_number_attrs.background = nord0;
    theme->set_face("line-number", line_number_attrs);

    FaceAttributes minibuffer_prompt_attrs;
    minibuffer_prompt_attrs.foreground = nord8;
    minibuffer_prompt_attrs.background = nord0;
    minibuffer_prompt_attrs.weight = FontWeight::Bold;
    theme->set_face("minibuffer-prompt", minibuffer_prompt_attrs);

    return theme;
}

std::shared_ptr<Theme> ThemeManager::create_gruvbox_light_theme() {
    auto theme = std::make_shared<Theme>("gruvbox-light");
    
    // Gruvbox Light color palette
    Color bg0(251, 241, 199);     // background
    Color bg1(235, 219, 178);     // background soft
    Color bg2(213, 196, 161);     // background hard
    Color bg3(189, 174, 147);     // background harder
    Color fg0(40, 40, 40);        // foreground
    Color fg1(60, 56, 54);        // foreground
    Color fg2(80, 73, 69);        // foreground
    Color fg3(102, 92, 84);       // foreground
    Color fg4(124, 111, 100);     // gray
    
    Color red(157, 0, 6);         // red
    Color green(121, 116, 14);    // green
    Color yellow(181, 118, 20);   // yellow
    Color blue(7, 102, 120);      // blue
    Color purple(143, 63, 113);   // purple
    Color aqua(66, 123, 88);      // aqua
    Color orange(175, 58, 3);     // orange

    // Set face attributes
    FaceAttributes normal_attrs;
    normal_attrs.foreground = fg0;
    normal_attrs.background = bg0;
    theme->set_face("normal", normal_attrs);

    FaceAttributes keyword_attrs;
    keyword_attrs.foreground = red;
    keyword_attrs.background = bg0;
    keyword_attrs.weight = FontWeight::Bold;
    theme->set_face("keyword", keyword_attrs);

    FaceAttributes string_attrs;
    string_attrs.foreground = green;
    string_attrs.background = bg0;
    theme->set_face("string", string_attrs);

    FaceAttributes comment_attrs;
    comment_attrs.foreground = fg4;
    comment_attrs.background = bg0;
    comment_attrs.slant = FontSlant::Italic;
    theme->set_face("comment", comment_attrs);

    FaceAttributes function_attrs;
    function_attrs.foreground = yellow;
    function_attrs.background = bg0;
    theme->set_face("function", function_attrs);

    FaceAttributes type_attrs;
    type_attrs.foreground = purple;
    type_attrs.background = bg0;
    theme->set_face("type", type_attrs);

    FaceAttributes number_attrs;
    number_attrs.foreground = orange;
    number_attrs.background = bg0;
    theme->set_face("number", number_attrs);

    FaceAttributes constant_attrs;
    constant_attrs.foreground = aqua;
    constant_attrs.background = bg0;
    theme->set_face("constant", constant_attrs);

    FaceAttributes error_attrs;
    error_attrs.foreground = red;
    error_attrs.background = bg1;
    error_attrs.weight = FontWeight::Bold;
    theme->set_face("error", error_attrs);

    FaceAttributes selection_attrs;
    selection_attrs.foreground = fg0;
    selection_attrs.background = bg2;
    theme->set_face("selection", selection_attrs);

    FaceAttributes cursor_attrs;
    cursor_attrs.foreground = bg0;
    cursor_attrs.background = fg0;
    theme->set_face("cursor", cursor_attrs);

    FaceAttributes statusline_attrs;
    statusline_attrs.foreground = fg1;
    statusline_attrs.background = bg1;
    theme->set_face("statusline", statusline_attrs);

    FaceAttributes statusline_inactive_attrs;
    statusline_inactive_attrs.foreground = fg3;
    statusline_inactive_attrs.background = bg1;
    theme->set_face("statusline-inactive", statusline_inactive_attrs);

    FaceAttributes line_number_attrs;
    line_number_attrs.foreground = fg4;
    line_number_attrs.background = bg0;
    theme->set_face("line-number", line_number_attrs);

    FaceAttributes minibuffer_prompt_attrs;
    minibuffer_prompt_attrs.foreground = blue;
    minibuffer_prompt_attrs.background = bg0;
    minibuffer_prompt_attrs.weight = FontWeight::Bold;
    theme->set_face("minibuffer-prompt", minibuffer_prompt_attrs);

    return theme;
}

} // namespace lumacs
