-- rainbow-delimiters.lua
-- ============================================================================
-- Colorize nested delimiters (parentheses, brackets, braces) with different
-- colors based on nesting depth. Similar to Emacs rainbow-delimiters.
-- ============================================================================

local rainbow = {}

-- Configuration
rainbow.config = {
    enabled = true,
    max_depth = 9,  -- Number of colors to cycle through
    delimiters = {
        ["("] = ")",
        ["["] = "]",
        ["{"] = "}",
    },
}

-- Default rainbow colors (can be customized per theme)
rainbow.colors = {
    "#ff6b6b",  -- Red
    "#ffa94d",  -- Orange
    "#ffd43b",  -- Yellow
    "#69db7c",  -- Green
    "#38d9a9",  -- Teal
    "#4dabf7",  -- Blue
    "#748ffc",  -- Indigo
    "#da77f2",  -- Violet
    "#f783ac",  -- Pink
}

-- Alternative color schemes
rainbow.presets = {
    default = {
        "#ff6b6b", "#ffa94d", "#ffd43b", "#69db7c",
        "#38d9a9", "#4dabf7", "#748ffc", "#da77f2", "#f783ac",
    },
    pastel = {
        "#ffb3ba", "#ffdfba", "#ffffba", "#baffc9",
        "#bae1ff", "#d4baff", "#ffbae1", "#baffff", "#e1ffba",
    },
    neon = {
        "#ff0080", "#ff8000", "#ffff00", "#00ff00",
        "#00ffff", "#0080ff", "#8000ff", "#ff00ff", "#ff0040",
    },
    monochrome = {
        "#ffffff", "#e0e0e0", "#c0c0c0", "#a0a0a0",
        "#808080", "#606060", "#404040", "#303030", "#202020",
    },
    nord = {
        "#bf616a", "#d08770", "#ebcb8b", "#a3be8c",
        "#88c0d0", "#81a1c1", "#5e81ac", "#b48ead", "#bf616a",
    },
    dracula = {
        "#ff5555", "#ffb86c", "#f1fa8c", "#50fa7b",
        "#8be9fd", "#bd93f9", "#ff79c6", "#6272a4", "#ff5555",
    },
}

-- State
rainbow.active = true

-- Setup faces for each depth level
function rainbow.setup_faces()
    for i, color in ipairs(rainbow.colors) do
        local face_name = "rainbow-delimiters-depth-" .. i
        -- Use lumacs.face helper which handles hex conversion
        local attrs = lumacs.face({
            foreground = color,
            weight = "bold",
        })
        if editor.theme_manager then
            local theme = editor.theme_manager:active_theme()
            if theme then
                theme:set_face(face_name, attrs)
            end
        end
    end
end

-- Get face name for a given depth
function rainbow.get_face(depth)
    local idx = ((depth - 1) % #rainbow.colors) + 1
    return "rainbow-delimiters-depth-" .. idx
end

-- Check if char is an opener
function rainbow.is_opener(char)
    return rainbow.config.delimiters[char] ~= nil
end

-- Check if char is a closer
function rainbow.is_closer(char)
    for opener, closer in pairs(rainbow.config.delimiters) do
        if closer == char then
            return true, opener
        end
    end
    return false, nil
end

-- Highlight delimiters in the current buffer
function rainbow.highlight_buffer()
    if not rainbow.active or not rainbow.config.enabled then
        return
    end

    local buf = editor.buffer
    local line_count = buf:line_count()
    local depth = 0
    local delimiter_positions = {}

    -- First pass: find all delimiters and calculate their depths
    for line_num = 0, line_count - 1 do
        local line = buf:line(line_num)
        local in_string = false
        local string_char = nil
        local escaped = false

        for col = 0, #line - 1 do
            local char = line:sub(col + 1, col + 1)

            -- Handle escape sequences
            if escaped then
                escaped = false
            elseif char == "\\" then
                escaped = true
            -- Handle strings
            elseif not in_string and (char == '"' or char == "'") then
                in_string = true
                string_char = char
            elseif in_string and char == string_char then
                in_string = false
                string_char = nil
            -- Handle delimiters (outside strings)
            elseif not in_string then
                if rainbow.is_opener(char) then
                    depth = depth + 1
                    table.insert(delimiter_positions, {
                        line = line_num,
                        col = col,
                        depth = depth,
                        char = char,
                    })
                elseif rainbow.is_closer(char) then
                    table.insert(delimiter_positions, {
                        line = line_num,
                        col = col,
                        depth = depth,
                        char = char,
                    })
                    depth = math.max(0, depth - 1)
                end
            end
        end
    end

    -- Second pass: apply styles
    for _, pos in ipairs(delimiter_positions) do
        local face = rainbow.get_face(pos.depth)
        local range = lumacs.Range(
            lumacs.Position(pos.line, pos.col),
            lumacs.Position(pos.line, pos.col + 1)
        )
        local attr = lumacs.TextAttribute(face)
        buf:set_style(range, attr)
    end
end

-- Toggle rainbow delimiters
function rainbow.toggle()
    rainbow.active = not rainbow.active
    if rainbow.active then
        rainbow.highlight_buffer()
        editor:message("Rainbow delimiters enabled")
    else
        -- Clear rainbow styles
        editor.buffer:clear_styles()
        editor:message("Rainbow delimiters disabled")
    end
end

-- Set color preset
function rainbow.set_preset(name)
    local preset = rainbow.presets[name]
    if not preset then
        editor:message("Unknown preset: " .. name, "warning")
        return
    end

    rainbow.colors = preset
    rainbow.setup_faces()
    if rainbow.active then
        rainbow.highlight_buffer()
    end
    editor:message("Rainbow preset: " .. name)
end

-- Register commands
editor:register_command("rainbow-delimiters-mode", "Toggle rainbow delimiter coloring", function(args)
    rainbow.toggle()
    return {success = true}
end, {"rainbow"})

editor:register_command("rainbow-preset", "Set rainbow delimiter color preset", function(args)
    if #args == 0 then
        local presets = {}
        for name, _ in pairs(rainbow.presets) do
            table.insert(presets, name)
        end
        table.sort(presets)
        return {success = false, message = "Available presets: " .. table.concat(presets, ", ")}
    end

    rainbow.set_preset(args[1])
    return {success = true}
end, {}, true, "s")

editor:register_command("rainbow-highlight", "Re-apply rainbow highlighting to current buffer", function(args)
    rainbow.highlight_buffer()
    return {success = true, message = "Rainbow highlighting applied"}
end)

-- Define minor mode
lumacs.define_minor_mode("rainbow-delimiters-mode", {
    lighter = "🌈",
    global = false,
    setup = function()
        rainbow.active = true
        rainbow.setup_faces()
        rainbow.highlight_buffer()
        editor:message("Rainbow delimiters enabled")
    end,
    cleanup = function()
        rainbow.active = false
        editor.buffer:clear_styles()
        editor:message("Rainbow delimiters disabled")
    end
})

-- Initialize faces
rainbow.setup_faces()

-- Store in lumacs namespace
lumacs.rainbow_delimiters = rainbow

return rainbow
