#include "../helpers/string.lua"
#include "../helpers/entity.lua"
#include "../helpers/utils.lua"
#include "../helpers/mathfr.lua"

transitions = GetStringParam("light_transitions", "")
speed = GetFloatParam("transition_speed", 1.0)
velocity_scaling = GetBoolParam("velocity_scaling", false)
velocity_scaling_min = GetFloatParam("velocity_scaling_min", 0.5)
velocity_scaling_max = GetFloatParam("velocity_scaling_max", 3)
intensity_wiggle = GetFloatParam("intensity_wiggle", 0.0)
intensity_delay = GetIntParam("intensity_wiggle_frame_delay", 10)

function init()
    lights = FindLights()
    if #lights==0 then DISABLED = true cEntity:EnqueueDeletion() return end

    shapes = map(lights, function(a) return GetLightShape(a) end)
    veh = GetBodyVehicle(GetShapeBody(shapes[1]))
    if veh > 0 then
        v_b = GetVehicleBody(veh)
        topspeed = GetVehicleParams(veh).topspeed / 3.6
    end

    initTransitions()
    last_intensity = 0
end

function initTransitions()
    if transitions == "" then
        transitions = nil
    elseif transitions then
        transitions = transitions:as_values"([^,]+),?%s?"
        if #transitions < 2 then
            transitions = nil
        else
            for i = 1, #transitions do
                transitions[i] = transitions[i]:as_vec()
            end
            last_color_idx = 1
            positive_dir = true
        end
    end
end

function update(dt)
    if DISABLED then return end
    if v_b and not IsLightActive(lights[1]) then return end

    color_transition(dt)

    if v_b and velocity_scaling then
        local vel = VecLength(GetBodyVelocity(v_b))
        local clamped = math:MapRangeClamped(vel, 0, topspeed, velocity_scaling_min, velocity_scaling_max)
        for i = 1, #lights do
            local light = lights[i]
            local original = tonumber(GetTagValue(light, "intensity")) or 1
            local new = original+original*clamped
            SetLightIntensity(light, new)
            SetTag(light, "intensity", clamped)
        end
    end

    if intensity_wiggle>0 then
        if last_intensity == 0 then
            for i = 1, #lights do
                local light = lights[i]
                local original = tonumber(GetTagValue(light, "intensity")) or 1
                local new = original+original*(math.random(intensity_wiggle*100)/100)
                SetLightIntensity(light, new)
            end
            last_intensity = math.random(intensity_delay)
        else
            last_intensity = last_intensity-1
        end
    end
end

function color_transition(dt)
    if not transitions then return end

    local time = GetTime()
    local t = (math.sin(time*speed)+1)/2
    local next_ = last_color_idx%#transitions+1
    local start, stop = transitions[last_color_idx], transitions[next_]
    if not positive_dir then start, stop = stop, start end

    local r = math:Lerp(start[1], stop[1], t)
    local g = math:Lerp(start[2], stop[2], t)
    local b = math:Lerp(start[3], stop[3], t)
    for i = 1, #lights do
        local light = lights[i]
        SetLightColor(light, r, g, b)
    end

    if t >= 0.99 then
        if positive_dir then
            last_color_idx = next_
        end
        positive_dir = false
    elseif t <= 0.01 then
        if not positive_dir then
            last_color_idx = next_
        end
        positive_dir = true
    end
end
