--[[-- Commands - Rainbow
Adds a command that prints your message in rainbow font
]]

local Commands = require("modules/exp_commands")
local format_player_name = Commands.format_player_name_locale
local format_text = Commands.format_rich_text_color

--- Wraps one component into the next
--- @param c1 number
--- @param c2 number
--- @return number, number
local function step_component(c1, c2)
    if c1 < 0 then
        return 0, c2 + c1
    elseif c1 > 1 then
        return 1, c2 - c1 + 1
    else
        return c1, c2
    end
end

--- Wraps all components of a colour ensuring it remains valid
--- @param color Color
--- @return Color
local function step_color(color)
    color.r, color.g = step_component(color.r, color.g)
    color.g, color.b = step_component(color.g, color.b)
    color.b, color.r = step_component(color.b, color.r)
    color.r = step_component(color.r, 0)
    return color
end

--- Get the next colour in the rainbow by the given step
--- @param color Color
--- @param step number
--- @return Color
local function next_color(color, step)
    step = step or 0.1
    local new_color = { r = 0, g = 0, b = 0 }
    if color.b == 0 and color.r ~= 0 then
        new_color.r = color.r - step
        new_color.g = color.g + step
    elseif color.r == 0 and color.g ~= 0 then
        new_color.g = color.g - step
        new_color.b = color.b + step
    elseif color.g == 0 and color.b ~= 0 then
        new_color.b = color.b - step
        new_color.r = color.r + step
    end
    return step_color(new_color)
end

--- Sends an rainbow message in the chat
Commands.new("rainbow", { "exp-commands_rainbow.description" })
    :argument("message", { "exp-commands_rainbow.arg-message" }, Commands.types.string)
    :enable_auto_concatenation()
    :register(function(player, message)
        local color_step = 3 / message:len()
        if color_step > 1 then color_step = 1 end
        local current_color = { r = 1, g = 0, b = 0 }

        game.print{
            "exp-commands_rainbow.response",
            format_player_name(player),
            message:gsub("%S", function(letter)
                local rtn = format_text(letter, current_color)
                current_color = next_color(current_color, color_step)
                return rtn
            end)
        }
    end)
