-- Lua Mode for Lumacs
-- Extracted from init.lua

-- Define highlighting function locally so it can be used in setup
local function highlight_lua()
    local buf = editor.buffer
    buf:clear_styles()

    -- Keywords to highlight
    local keywords = {
        "function", "local", "end", "if", "then", "else", "elseif",
        "for", "while", "do", "return", "break", "and", "or", "not",
        "true", "false", "nil", "in", "repeat", "until"
    }

    -- Highlight each line
    for line_num = 0, buf:line_count() - 1 do
        local line_text = buf:line(line_num)
        local len = #line_text
        local pos = 1

        -- Parse line to handle priority (Comments > Strings > Keywords)
        while pos <= len do
            -- Find nearest tokens
            local comment_start = string.find(line_text, "--", pos, true)
            local string_dq_start = string.find(line_text, '"', pos, true)
            local string_sq_start = string.find(line_text, "'", pos, true)

            -- Determine the first token
            local mode = "code"
            local token_start = len + 2 -- Sentinel

            if comment_start and comment_start < token_start then
                token_start = comment_start
                mode = "comment"
            end
            if string_dq_start and string_dq_start < token_start then
                token_start = string_dq_start
                mode = "string_dq"
            end
            if string_sq_start and string_sq_start < token_start then
                token_start = string_sq_start
                mode = "string_sq"
            end

            -- 1. Process code/keywords BEFORE the token
            local code_end = token_start - 1
            if code_end >= pos then
                local code_chunk = string.sub(line_text, pos, code_end)
                
                for _, keyword in ipairs(keywords) do
                    local s = 1
                    while true do
                        -- Match whole words only
                        local p_start, p_end = string.find(code_chunk, "%f[%w]" .. keyword .. "%f[%W]", s)
                        if not p_start then break end

                        local abs_start = pos + p_start - 1
                        local abs_end = pos + p_end - 1
                        
                        local range = lumacs.Range(
                            lumacs.Position(line_num, abs_start - 1),
                            lumacs.Position(line_num, abs_end)
                        )
                        buf:set_style(range, lumacs.TextAttribute(lumacs.ColorType.Keyword, 0))
                        s = p_end + 1
                    end
                end
            end

            -- 2. Process the token
            if mode == "comment" then
                -- Comment goes to end of line
                local range = lumacs.Range(
                    lumacs.Position(line_num, token_start - 1),
                    lumacs.Position(line_num, len)
                )
                buf:set_style(range, lumacs.TextAttribute(lumacs.ColorType.Comment, 0))
                break -- Done with this line

            elseif mode == "string_dq" then
                local _, s_end = string.find(line_text, '"', token_start + 1, true)
                if not s_end then s_end = len end
                local range = lumacs.Range(
                    lumacs.Position(line_num, token_start - 1),
                    lumacs.Position(line_num, s_end)
                )
                buf:set_style(range, lumacs.TextAttribute(lumacs.ColorType.String, 0))
                pos = s_end + 1

            elseif mode == "string_sq" then
                local _, s_end = string.find(line_text, "'", token_start + 1, true)
                if not s_end then s_end = len end
                local range = lumacs.Range(
                    lumacs.Position(line_num, token_start - 1),
                    lumacs.Position(line_num, s_end)
                )
                buf:set_style(range, lumacs.TextAttribute(lumacs.ColorType.String, 0))
                pos = s_end + 1

            else
                -- No more tokens
                pos = len + 1
            end
        end
    end
end

define_major_mode("lua-mode", {
    file_patterns = {"%.lua$"},
    comment_syntax = "--",

    highlight = highlight_lua,

    setup = function()
        editor:message("[lua-mode] Lua mode activated")
        
        -- Register a hook to re-highlight on change
        -- Note: This adds a listener every time the mode is setup. 
        -- Ideally, we'd track and remove it, but for now this ensures responsiveness.
        editor.buffer:on_buffer_event(function(data)
            if data.event == lumacs.BufferEvent.AfterChange then
                -- Only run if we are still in lua-mode (simple check)
                -- Using a protected call in case global state changes
                local status, mode_name = pcall(current_major_mode)
                if status and mode_name == "lua-mode" then
                    highlight_lua()
                end
            end
        end)
    end,

    cleanup = function()
        editor:message("[lua-mode] Lua mode deactivated")
    end,

    keybindings = {
        -- Fix: Explicitly bind space since empty keybindings table might be causing issues
        [" "] = function() editor:execute_command("self-insert-command", {" "}) end,
    }
})
