local inProgress = false

local function loadTextureDict(dict)
	if not HasStreamedTextureDictLoaded(dict) then
		while not HasStreamedTextureDictLoaded(dict) do RequestStreamedTextureDict(dict) Wait(5) end
	end
end

local function loadAnimDict(animDict)
	if not DoesAnimDictExist(animDict) then
		print("^6Bridge^7: ^1ERROR^7: ^2Anim Dictionary^7 - '^6"..animDict.."^7' ^2does not exist in server") return
	else
		while not HasAnimDictLoaded(animDict) do RequestAnimDict(animDict) Wait(5) end
	end
end

local function playAnim(animDict, animName, duration, flag, ped, speed)
    loadAnimDict(animDict)
	TaskPlayAnim(ped and ped or PlayerPedId(), animDict, animName, speed or 8.0, speed or -8.0, duration or 30000, flag or 50, 1, false, false, false)
end

local function stopAnim(animDict, animName, ped)
    StopAnimTask(ped or PlayerPedId(), animDict, animName, 0.5)
    StopAnimTask(ped or PlayerPedId(), animName, animDict, 0.5)
    RemoveAnimDict(animDict)
end

function redProgressBar(data)
    local ped = PlayerPedId()

    local result = nil

    loadTextureDict("generic_textures")
    if inProgress then return false end
    inProgress = true
    local wait = debugMode and 1000 or data.time
    local endTime = GetGameTimer() + wait

    LocalPlayer.state:set("inv_busy", true, true)
    TriggerEvent('inventory:client:busy:status', true)
    TriggerEvent('canUseInventoryAndHotbar:toggle', not true)

    -- Setup Animation/Task if specified
    if data.dict then
        playAnim(data.dict, data.anim, -1, data.flag or 32)
    elseif data.task then
        TaskStartScenarioInPlace(ped, data.task, -1, true)
    end

    -- Progress bar rendering loop
    CreateThread(function()
        while GetGameTimer() < endTime and inProgress do
            Wait(0)
            local elapsed = GetGameTimer()
            local percentage = ((elapsed - (endTime - wait)) / wait) * 100
            if percentage < 0 then percentage = 0 end
            if percentage > 100 then percentage = 100 end

            -- Draw your segmented progress bar
            ShowRedProgressBar(percentage, data.label, ("%.0f%%"):format(percentage))

            -- Controls to disable during progress
            if data.disableMouse then
                DisableControlAction(0, `INPUT_LOOK_LR`, true)
                DisableControlAction(0, `INPUT_LOOK_UD`, true)
                DisableControlAction(0, `INPUT_VEH_MOUSE_CONTROL_OVERRIDE`, true)
            end

            if data.disableMovement then
                DisableControlAction(0, `INPUT_MOVE_LR`, true)
                DisableControlAction(0, `INPUT_MOVE_UD`, true)
                DisableControlAction(0, `INPUT_DUCK`, true)
                DisableControlAction(0, `INPUT_SPRINT`, true)
            end

            if data.disableCarMovement then
                DisableControlAction(0, `INPUT_VEH_MOVE_LEFT_ONLY`, true)
                DisableControlAction(0, `INPUT_VEH_MOVE_RIGHT_ONLY`, true)
                DisableControlAction(0, `INPUT_VEH_ACCELERATE`, true)
                DisableControlAction(0, `INPUT_VEH_BRAKE`, true)
                DisableControlAction(0, `INPUT_VEH_EXIT`, true)
            end

            if data.disableCombat then
                DisablePlayerFiring(PlayerId(), true)
                DisableControlAction(0, `INPUT_ATTACK`, true)
                DisableControlAction(0, `INPUT_AIM`, true)
                DisableControlAction(0, `INPUT_OPEN_WHEEL_MENU`, true)
                DisableControlAction(0, `INPUT_DETONATE`, true)
                DisableControlAction(0, `INPUT_THROW_GRENADE`, true)
                DisableControlAction(0, `INPUT_MELEE_ATTACK`, true)
                DisableControlAction(0, `INPUT_MELEE_GRAPPLE_ATTACK`, true)
            end

            if data.cancel and (
                IsControlJustReleased(0, `INPUT_FRONTEND_RS`) or
                IsControlJustReleased(0, `INPUT_SWITCH_SHOULDER`) or
                IsControlJustReleased(0, `INPUT_GAME_MENU_TAB_RIGHT_SECONDARY`) or
                IsControlJustReleased(0, `INPUT_FRONTEND_CANCEL`) or
                IsControlJustReleased(0, `INPUT_GAME_MENU_CANCEL`) or
                IsControlJustReleased(0, `INPUT_FRONTEND_RRIGHT`) or
                IsControlJustReleased(0, `INPUT_QUIT`) or
                IsControlJustReleased(0, `INPUT_MINIGAME_QUIT`)
            ) then
                inProgress = false
            end
        end
    end)

    -- Wait for completion or cancel
    while GetGameTimer() < endTime and inProgress do
        Wait(100)
    end

    -- Cleanup animations/tasks
    if data.dict then
        stopAnim(data.dict, data.anim, ped)
    end
    if data.task then
        ClearPedTasks(ped)
    end

    result = inProgress
    inProgress = false

    while result == nil do Wait(10) end

    -- Cleanup
    FreezeEntityPosition(ped, false)

    LocalPlayer.state:set("inv_busy", false, true)
    TriggerEvent('inventory:client:busy:status', false)
    TriggerEvent('canUseInventoryAndHotbar:toggle', not false)

    return result
end

function ShowRedProgressBar(percentage, title, level)
    local loc = vec2(0.40, 0.90)
    local size = vec2(0.3, 0.03)
    local tickCount = 10        -- visually split into 10 segments (9 inner lines)
    local barHeight = size.y / 3.4
    local barWidth  = 0.21      -- tuned to your existing layout
    local barLeft   = (loc.x - size.x / 4) + 0.075
    local barCenter = barLeft + barWidth / 2
    local lineW     = 0.001
    local lineH     = barHeight + 0.00

    -- Background plate
    DrawSprite("generic_textures", "inkroller_1a", loc.x + 0.1, loc.y - 0.01, 0.25, 0.07, 180.0, 0, 0, 0, 200)

    -- Title (left)
    SetTextFontForCurrentCommand(6)
    SetTextScale(0.35, 0.35)
    SetTextColor(255, 255, 255, 255)
    SetTextDropshadow(1, 0, 0, 0, 200)
    BgDisplayText(title, loc.x - size.x / 4 + 0.074, loc.y - 0.034)

    -- Percentage (right)
    SetTextFontForCurrentCommand(1)
    SetTextScale(0.35, 0.35)
    SetTextColor(255, 255, 255, 255)
    SetTextDropshadow(1, 0, 0, 0, 200)
    BgDisplayText(level, loc.x - size.x / 4 + 0.246, loc.y - 0.030)

    -- Track (bg)
    DrawRect(barCenter, loc.y, barWidth, barHeight, 100, 100, 100, 255)

    -- Fill
    local fillWidth = barWidth * (percentage / 100.0)
    if fillWidth > 0.0 then
        local fillCenter = barLeft + (fillWidth / 2.0)
        DrawRect(fillCenter, loc.y, fillWidth, barHeight, 255, 0, 0, 200)  -- red fill
    end

    -- Tick lines (9 inner lines for 10 segments)
    for i = 1, (tickCount - 1) do
        local x = barLeft + (barWidth * (i / tickCount))
        DrawRect(x, loc.y, lineW, lineH, 0, 0, 0, 120)
    end
end

function gtaProgressBar(data)
    local ped = PlayerPedId()

    local result = nil

    loadTextureDict("timerbars")
    if inProgress then return false end
    inProgress = true
    local wait = debugMode and 1000 or data.time
    local endTime = GetGameTimer() + wait

    -- Setup Animation/Task if specified
    if data.dict then
        playAnim(data.dict, data.anim, -1, data.flag or 32)
    elseif data.task then
        TaskStartScenarioInPlace(ped, data.task, -1, true)
    end

    -- Progress bar rendering loop
    CreateThread(function()
        while GetGameTimer() < endTime and inProgress do
            Wait(0)
            local elapsed = GetGameTimer()
            local percentage = ((elapsed - (endTime - wait)) / wait) * 100

            if percentage < 0 then percentage = 0 end
            if percentage > 100 then percentage = 100 end

            -- Draw your segmented progress bar
            ShowGTAProgressBar(percentage, data.label, ("%.0f%%"):format(percentage))

            -- Controls to disable during progress
            DisablePlayerFiring(PlayerId(), true)
            DisableControlAction(0, 25, true) -- Disable aim
            DisableControlAction(0, 21, true) -- Disable sprint
            DisableControlAction(0, 30, true) -- Disable move left/right
            DisableControlAction(0, 31, true) -- Disable move forward/back
            DisableControlAction(0, 36, true) -- Disable stealth

            if data.cancel and (IsControlJustReleased(0, 202) or IsControlJustReleased(0, 177) or IsControlJustReleased(0, 73)) then
                inProgress = false
            end
        end
        result = inProgress
    end)


    -- Wait for completion or cancel
    while result == nil do Wait(10) end
    inProgress = false

    -- Cleanup animations/tasks
    if data.dict then
        stopAnim(data.dict, data.anim, ped)
    end
    if data.task then
        ClearPedTasks(ped)
    end

    -- Cleanup
    FreezeEntityPosition(ped, false)

    LocalPlayer.state:set("inv_busy", false, true)
    TriggerEvent('inventory:client:busy:status', false)
    TriggerEvent('canUseInventoryAndHotbar:toggle', not false)

    return result
end

function ShowGTAProgressBar(percentage, title, level)
    local loc = vec2(0.37, 0.90)
    local size = vec2(0.3, 0.03)
    local tickCount = 10
    local barHeight = size.y / 3.4
    local barWidth  = 0.19
    local barLeft   = (loc.x - size.x / 4) + 0.075
    local barCenter = barLeft + barWidth / 2
    local lineW     = 0.001
    local lineH     = barHeight + 0.00

    -- Background plates
    DrawSprite("timerbars", "all_black_bg", loc.x + 0.028, loc.y - 0.01, 0.15, 0.07, 0.0,   255, 255, 255, 255)
    DrawSprite("timerbars", "all_black_bg", loc.x + 0.170, loc.y - 0.01, 0.15, 0.07, 180.0, 255, 255, 255, 255)

    -- Title (left)
    SetTextFont(0)
    SetTextProportional(1)
    SetTextScale(0.35, 0.35)
    SetTextColour(255, 255, 255, 255)
    SetTextDropshadow(0, 0, 0, 0, 255)
    SetTextDropShadow()
    SetTextOutline()
    SetTextEntry("STRING")
    AddTextComponentString(title)
    DrawText(loc.x - size.x / 4 + 0.074, loc.y - 0.034)

    -- Percentage (right)
    SetTextFont(0)
    SetTextProportional(1)
    SetTextScale(0.35, 0.25)
    SetTextColour(255, 255, 255, 255)
    SetTextEntry("STRING")
    AddTextComponentString(level)
    DrawText(loc.x - size.x / 4 + 0.246, loc.y - 0.030)

    -- Track (bg)
    DrawRect(barCenter, loc.y, barWidth, barHeight, 100, 100, 100, 255)

    -- Fill
    local fillWidth = barWidth * (percentage / 100.0)
    if fillWidth > 0.0 then
        local fillCenter = barLeft + (fillWidth / 2.0)
        DrawRect(fillCenter, loc.y, fillWidth, barHeight, 93, 182, 229, 255) -- GTA blue
    end

    -- Tick lines
    for i = 1, (tickCount - 1) do
        local x = barLeft + (barWidth * (i / tickCount))
        DrawRect(x, loc.y, lineW, lineH, 0, 0, 0, 120)
    end
end


function stopProgressBar() inProgress = false end
function isProgressBar() return inProgress end

function progressBar(...)
    if GetCurrentGameName() == "rdr3" then
        return redProgressBar(...)
    else
        return gtaProgressBar(...)
    end
end

exports("progressBar", function(...)
    return progressBar(...)
end)
exports("gtaProgressBar", function(...)
    return gtaProgressBar(...)
end)
exports("redProgressBar", function(...)
    return redProgressBar(...)
end)

exports("stopProgressBar", stopProgressBar)
exports("isProgressBar", isProgressBar)

--RegisterCommand("testprog", function()
--    print("test")
--    if progressBar({
--        label = "Processing...",
--        time = 10000,
--        disableMovement = true,
--        --dict = "amb@world_human_hang_out_street@female_hold_arm@base",
--        --anim = "base",
--        --flag = 49,
--        cancel = true,
--    }) then
--        Notify("Success!", "Short test message", "success")
--    else
--        Notify("Error!", "This is a longer example message to show stacking.", "error")
--    end
--end)