-- ============================================================================
--  AUDI RS cluster — Single Vertical RPM Bar, Separate Indicators, Oil/Boost Bars, and all Text
--  **CRITICAL FIX: Oil and Boost bar drawing is moved to Layer 4 (above the mask) and smoothing variables are fixed.**
--  **All text, bars, and background should now be visible and functional.**
-- ============================================================================

local car = ac.getCar(0)

-- 🟢 CONFIGURATION: IMAGES (Paths confirmed from previous steps)
local CLUSTER_BACKGROUND_IMAGE = "cluster/CLUSTER_ALPHA.png" 
local CLUSTER_OVERLAY_IMAGE    = "cluster/CLUSTER_ALPHA_42.png"        
local CLUSTER_SIZE = vec2(2048, 2048) 

local gearT = { [-1]="R",[0]="N",[1]="1",[2]="2",[3]="3",[4]="4",[5]="5",[6]="6",[7]="7",[8]="8",[9]="9"  }
local white = rgb(1, 1, 1)

-- ----------------------------------------------------------------------
-- 🟢 CONFIGURATION: SINGLE VERTICAL RPM BAR (Positions untouched)
-- ----------------------------------------------------------------------
local BAR_X_CENTER  = 970
local BAR_WIDTH     = 850
local BAR_Y_TOP     = 760   -- Bottom of Bar (Y-coordinate closer to bottom of screen)
local BAR_Y_BOTTOM  = 1195    -- Top of Bar (Y-coordinate closer to top of screen)
local BAR_HEIGHT    = BAR_Y_TOP - BAR_Y_BOTTOM -- Total height of the bar area

local BAR_RPM = { 
  pos = vec2(BAR_X_CENTER - BAR_WIDTH/2, BAR_Y_BOTTOM), -- Top-left corner of the whole bar area
  size = vec2(BAR_WIDTH, BAR_HEIGHT),              
  fill = rgbm(0.5, 0.5, 0.5, 0.5),                  
  bg = rgbm(0, 0, 0, 0.5)                           
}
local RPM_EDGE   = { width = BAR_WIDTH, height = 8, color = rgb(1, 1, 1) } 

-- 🟢 CONFIGURATION: RPM MAPPING POINTS (Non-Linear Interpolation, untouched)
local RPM_MAX = 7000 
local RPM_MAP_POINTS = {
    { rpm = 0,    frac = 0.00 },
    { rpm = 1000, frac = 0.08 },
    { rpm = 2000, frac = 0.16 },
    { rpm = 3000, frac = 0.25 },
    { rpm = 4000, frac = 0.35 },
    { rpm = 5000, frac = 0.50 }, 
    { rpm = 6000, frac = 0.70 }, 
    { rpm = 7000, frac = 1 }, 

}

-- 🟢 CONFIGURATION: RPM SHIFT INDICATOR BOXES (Positions untouched)
local RPM_COL_GREEN   = rgbm(0.00, 1.00, 0.00,0.35) 
local RPM_COL_YELLOW  = rgbm(1.00, 0.7, 0.00,0.5)
local RPM_COL_RED     = rgbm(1.00, 0.00, 0.10,0.5)

local RPM_INDICATORS = {
    { pos = vec2(650, 972), size = vec2(650, 50), rpm_threshold = 4750, color = RPM_COL_GREEN },
    { pos = vec2(630, 1022), size = vec2(680, 50), rpm_threshold = 5250, color = RPM_COL_YELLOW },
    { pos = vec2(610, 1070), size = vec2(720, 120), rpm_threshold = 6500, color = RPM_COL_RED }
}

-- ----------------------------------------------------------------------
-- 🟢 CONFIGURATION: OIL & BOOST BARS (Positions untouched, MAX_BOOST set to 1.5 bar)
-- ----------------------------------------------------------------------
local BAR_OIL   = { pos = vec2(91.4, 1261),   size = vec2(650, 9),  bg = rgbm(0,0,0,0), fill = rgb(1,1,1) }
local BAR_BOOST = { pos = vec2(1531, 1260.7), size = vec2(320, 7),   bg = rgbm(0,0,0,0), fill = rgb(1,1,1) }
local OIL_EDGE   = { width = 6, color = rgbm(1, 0, 0, 0.95) }
local BOOST_EDGE = { width = 4, color = rgbm(1.0, 0., 0, 0.95) }
local OIL_MIN_C, OIL_MAX_C = 50, 130
local MAX_BOOST = 1.5 

-- Torque/Power Settings (Retained)
local IDLE_RPM = 1000
local PEAK_TORQUE_NM = 4200
local PEAK_TORQUE_RPM = 4250
local PLATEAU_END_RPM = 4500
local REDLINE_RPM = 7000
local TORQUE_AT_REDLINE_FRACTION = 0.85
local THROTTLE_EFFECT = 1
local SMOOTH_HZ_POWER = 10

-- Other settings
local fuelKmsPerLitre = 9 
local SMOOTH_HZ = 10
local smoothRPMFrac, smoothOil, smoothBoost = 0, 0, 0 -- 🗹 GLOBAL SMOOTHING VARIABLES
local movingTimeSec = 0.0
local smoothTorqueNm, smoothPowerKW = 0, 0
local smoothPowerFrac = 0 
local PRECOMP_MAX_TORQUE = PEAK_TORQUE_NM

-- ----------------------------------------------------------------------
-- HELPER FUNCTIONS (Retained)
-- ----------------------------------------------------------------------
local function v(str) local x,y=str:match("([^,]+),%s*([^,]+)"); return vec2(tonumber(x), tonumber(y)) end
local function clamp(x,a,b) return (x<a) and a or (x>b) and b or x end
local function lerp(a,b,t) return a + (b - a) * t end
local function ema(prev, target, hz, dt) dt = dt or 0.016; local k = math.exp(-hz * dt); return target + (prev - target) * k end
local function rect(x,y,w,h,c,o) display.rect{ pos=vec2(x,y), size=vec2(w,h), color=c, opacity=o or 1 } end

local function mapRPMToFraction(rpm)
    rpm = clamp(rpm, 0, RPM_MAX)
    if rpm == 0 then return 0.0 end
    local p1, p2
    for i = 1, #RPM_MAP_POINTS do
        local p = RPM_MAP_POINTS[i]
        if p.rpm <= rpm then p1 = p end
        if p.rpm >= rpm and not p2 then p2 = p; break end
    end
    if not p1 or not p2 or p1.rpm == p2.rpm then return p2 and p2.frac or 0.0 end
    local range_rpm = p2.rpm - p1.rpm
    local t = (rpm - p1.rpm) / range_rpm
    return lerp(p1.frac, p2.frac, t)
end

local function simulatedTorqueNm(rpm, throttle) 
    rpm = clamp(rpm or 0, IDLE_RPM, REDLINE_RPM)
    local tIdle    = PEAK_TORQUE_NM * 0.35
    local tPeak    = PEAK_TORQUE_NM
    local tRedline = PEAK_TORQUE_NM * TORQUE_AT_REDLINE_FRACTION
    local base
    if rpm <= PEAK_TORQUE_RPM then
      local t = (rpm - IDLE_RPM) / math.max(1, (PEAK_TORQUE_RPM - IDLE_RPM))
      base = lerp(tIdle, tPeak, clamp(t,0,1))
    elseif rpm <= PLATEAU_END_RPM then
      base = tPeak
    else
      local t = (rpm - PLATEAU_END_RPM) / math.max(1, (REDLINE_RPM - PLATEAU_END_RPM))
      base = lerp(tPeak, tRedline, clamp(t,0,1))
    end
    local gas = clamp(throttle or 0, 0, 1)
    base = base * (gas ^ THROTTLE_EFFECT)
    return math.max(0, base)
end
local function powerKWfromNm(torqueNm, rpm) return (torqueNm or 0) * (rpm or 0) / 9549.0 end

local PRECOMP_MAX_POWER_KW = (function()
  local best = 0
  for r = IDLE_RPM, REDLINE_RPM, 50 do
    local tNm = simulatedTorqueNm(r, 1.0) 
    local pKW = powerKWfromNm(tNm, r)
    if pKW > best then best = pKW end
  end
  return math.max(1, best)
end)()

local function drawVerticalRPMBar(bar, fraction, edge)
  local f = clamp(fraction or 0, 0, 1)
  local absHeight = bar.size.y 
  local barTopY = bar.pos.y 
  local barWidth = bar.size.x
  local barBottomY = barTopY + absHeight 
  display.rect{ pos = vec2(bar.pos.x, barTopY), size = vec2(barWidth, absHeight), color = bar.bg, opacity=1 }
  if f > 0 then
    local fillHeight = math.floor(absHeight * f + 0.5)
    local filledY = barBottomY - fillHeight 
    display.rect{ pos = vec2(bar.pos.x, filledY), size = vec2(barWidth, fillHeight), color = bar.fill, opacity = 1 }
    if edge and edge.height and edge.height > 0 then
      local edgeY = filledY - edge.height / 2 
      display.rect{ pos=vec2(bar.pos.x, edgeY), size=vec2(edge.width, edge.height), color=edge.color }
    end
  end
end

local function drawBar(bar, fraction, edge) 
  local f = clamp(fraction or 0, 0, 1)
  display.rect{ pos = bar.pos, size = bar.size, color = bar.bg, opacity=1, corner=3 }
  if f > 0 then
    display.rect{ pos = bar.pos, size = vec2(math.floor(bar.size.x * f + 0.5), bar.size.y),
                  color = bar.fill, opacity=1, corner=3 }
  end
  if edge and edge.width and edge.width>0 then
    local x = bar.pos.x + bar.size.x * f - (edge.width * 0.5)
    display.rect{ pos=vec2(math.floor(x + 0.5), bar.pos.y), size=vec2(edge.width, bar.size.y), color=edge.color }
  end
end


-- G-Force Logic (Retained for completeness, was not the crash source)
local DOT_TEXTURE = "cluster/g_force_dot_red.png"
local DOT_SIZE    = vec2(65.5, 65.5)
local GF_CENTER   = vec2(278, 1032)
local G_RADIUS, MAX_G, EMA_HZ_G = 73, 2.0, 7.5
local GF_SmoothedAccel = { x = 0, z = 0 }
local function gforce_update(dt)
  local gx, gz = ema(GF_SmoothedAccel.x, car.acceleration.x or 0, EMA_HZ_G, dt), ema(GF_SmoothedAccel.z, car.acceleration.z or 0, EMA_HZ_G, dt)
  GF_SmoothedAccel.x, GF_SmoothedAccel.z = gx, gz
  local ang = math.atan2(gz, gx)
  local mag = clamp(math.sqrt(gx*gx + gz*gz) / math.max(0.001, MAX_G), 0, 1)
  local pos = GF_CENTER + vec2(math.cos(ang), math.sin(ang)) * (G_RADIUS * mag)

  display.image({ image = DOT_TEXTURE, pos = vec2(pos.x - DOT_SIZE.x * 0.5, pos.y - DOT_SIZE.y * 0.5), size = DOT_SIZE })
  local col = rgbm(1, 0.2, 0.25, 1)
  display.text({ text = string.format("%.1f", math.max(gx, 0)),  pos = vec2(380, 1012), letter = vec2(30, 60), font="audi_vln_hd", width=46, alignment=1, spacing=-10, color=col })
  display.text({ text = string.format("%.1f", math.max(-gx, 0)), pos = vec2(100, 1012), letter = vec2(30, 60), font="audi_vln_hd", width=46, alignment=1, spacing=-10, color=col })
  display.text({ text = string.format("%.1f", math.max(-gz, 0)), pos = vec2(240,  895), letter = vec2(30, 60), font="audi_vln_hd", width=46, alignment=1, spacing=-10, color=col })
  display.text({ text = string.format("%.1f", math.max(gz, 0)),  pos = vec2(240, 1130), letter = vec2(30, 60), font="audi_vln_hd", width=46, alignment=1, spacing=-10, color=col })
end


-- ───────────────────────────────── MAIN CLUSTER LOOP ─────────────────────────
local function cluster_update(dt)
  local rpmNow   = car.rpm or 0
  
  -- Use non-linear mapped fraction
  local rpmFrac  = mapRPMToFraction(rpmNow) 
  smoothRPMFrac = ema(smoothRPMFrac, rpmFrac, 10, dt)
  
  local speedKmh = car.speedKmh
  local speed    = (speedKmh / 1.609344) -- Assumes MPH display
  if speedKmh > 0.5 then movingTimeSec = movingTimeSec + dt end

  -- Oil & Boost Calculation & Smoothing (MOVED TO TOP)
  local oilC     = car.oilTemperature or 0
  local oilFrac  = clamp((oilC - OIL_MIN_C) / math.max(1, (OIL_MAX_C - OIL_MIN_C)), 0, 1)
  local boostRaw = (car.turboBoost or car.boostRatio or 0)
  local boostFrac= clamp(boostRaw / MAX_BOOST, 0, 1) 
  
  smoothOil      = ema(smoothOil,   oilFrac,   10, dt) -- 🗹 REMOVED 'local'
  smoothBoost    = ema(smoothBoost, boostFrac, 10, dt) -- 🗹 REMOVED 'local'


  -- 🟢 LAYER 1: BACKGROUND (The solid base)
  display.image{ image = CLUSTER_BACKGROUND_IMAGE, pos = vec2(0,0), size = CLUSTER_SIZE }

  -- 🟢 LAYER 2: RPM BARS AND INDICATORS (Drawn under the mask)

  -- 2a. Draw the main VERTICAL RPM bar
  drawVerticalRPMBar(BAR_RPM, smoothRPMFrac, RPM_EDGE)
  
  -- 2b. RPM SHIFT INDICATORS (Behind the overlay mask)
  for _, indicator in ipairs(RPM_INDICATORS) do
      if rpmNow >= indicator.rpm_threshold then
          display.rect({ 
              pos = indicator.pos, 
              size = indicator.size, 
              color = indicator.color 
          })
      end
  end
  
  
  -- 🟢 LAYER 3: OVERLAY (The Mask) - Now covers the bars and indicators
  display.image{ image = CLUSTER_OVERLAY_IMAGE, pos = vec2(0,0), size = CLUSTER_SIZE }


  -- 🟢 LAYER 4: BARS, TEXT & UI (Always on top)

  -- 🗹 Oil & Boost Bars (Horizontal) - MOVED HERE, CORRECTLY DRAWN OVER THE OVERLAY
  drawBar(BAR_OIL,   smoothOil,   OIL_EDGE) -- OIL BAR
  drawBar(BAR_BOOST, smoothBoost, BOOST_EDGE) -- BOOST BAR
  
  -- Text Definitions
  local TIME_LETTER = vec2(30, 100) 
  local GEAR_LETTER = vec2(70, 110)
  local SPEED_LETTER = vec2(80, 120)

  -- Ambient Temperature 
  display.text({  
    text=string.format("%02.1f", sim.ambientTemperature or 0),  
    pos=v("955, 1325"),      
    letter=v("30, 100"),   
    font='rs62', 
    color=white, 
    alignment=1, 
    width=250, 
    spacing=-5 
  })
  
  -- Time
  local TIME_POS, TIME_FONT = v("720, 1312"), 'rs62'
  display.text({ text=string.format("%02d", sim.timeHours),   pos=TIME_POS, letter=TIME_LETTER, font=TIME_FONT, color=white, alignment=1, spacing=-1 })
  display.text({ text=":",                                    pos=TIME_POS + vec2(50, -4), letter=TIME_LETTER, font=TIME_FONT, color=white, alignment=1, spacing=0 })
  display.text({ text=string.format("%02d", sim.timeMinutes), pos=TIME_POS + vec2(70, 0), letter=TIME_LETTER, font=TIME_FONT, color=white, alignment=1, spacing=0 })
  
  
  -- Speed, Odo/Trip, Water Temp, Gear, Fuel Range
  display.text({ text=math.floor(speed),                 pos=v("835, 1124"),     letter=SPEED_LETTER, font='Seat_Leon_CUP_big', color=white, alignment=0.5, width=285 })
  display.text({ text=math.floor((car.distanceDrivenTotalKm or 0)/1.6), pos=v("957, 1269"), letter=TIME_LETTER, font='rs62', color=white, alignment=1, width=250 })
  display.text({ text=math.floor((car.distanceDrivenSessionKm or 0)/1.6), pos=v("595, 1269"), letter=TIME_LETTER, font='rs62', color=white, alignment=1, width=250 })
  display.text({ text=math.floor(car.waterTemperature),  pos=v("40, 1277"),      letter=vec2(20, 35),   font='Seat_Leon_CUP_big', color=white, alignment=1, width=250 })
  display.text({ text=gearT[car.gear],                   pos=v("940, 976"),      letter=GEAR_LETTER,  font='Seat_Leon_CUP_big', color=white, alignment=0.5 })
  display.text({ text=math.floor(car.fuel * fuelKmsPerLitre / 1.6), pos=v("495, 694.7"), letter=vec2(32, 40), font='b', color=white, alignment=0.75, width=255, spacing=-15 })

  -- Torque/Power Calculation & Display
  local gas = car.gas or 0
  local tNm = (rpmNow > 1050 and gas > 0.001) and simulatedTorqueNm(rpmNow, gas) or 0
  local pKW = tNm * rpmNow / 9549.0
  smoothTorqueNm = ema(smoothTorqueNm, tNm, SMOOTH_HZ_POWER, dt)
  smoothPowerKW  = ema(smoothPowerKW,  pKW, SMOOTH_HZ_POWER, dt)
  
  local tqFrac = clamp(smoothTorqueNm / PRECOMP_MAX_TORQUE, 0, 1)
  local pwFrac = clamp(smoothPowerKW / PRECOMP_MAX_POWER_KW, 0, 1)
  smoothPowerFrac = ema(smoothPowerFrac, pwFrac, 10, dt)

  local tqPct = math.floor(tqFrac * 100 + 0.5)
  local pwPct = math.floor(smoothPowerFrac * 100 + 0.5) 

  display.text({ text=tostring(tqPct), pos=v("1758, 1044"), letter=vec2(60, 160), font='rs62', color=white, alignment=.5, width=200, spacing=-5 })
  display.text({ text=tostring(pwPct), pos=v("1471, 1044"), letter=vec2(60, 160), font='rs62', color=white, alignment=.5, width=200, spacing=-5 })

  -- Handbrake/Headlight indicator rects
  if car.handbrake < 0.1 then rect(12894.2, 1306.6, 85, 85, rgb(0,0,0), 1) end 
end

function update(dt)
  cluster_update(dt)
  gforce_update(dt)
end