-- merged_cluster.lua — cluster UI + bars (no outlines, no G-force)

sim = ac.getSim()

--══════════════════════════════════════════════════════════════════════════════
--  cluster_plus_bars.lua — Combines cluster UI + masked alpha bar + dual bars
--  Notes:
--    - Single `update(dt)` entrypoint draws everything.
--    - No outlines on bars. G-force removed.
--══════════════════════════════════════════════════════════════════════════════

---------------------------------- USER SETTINGS ------------------------------
-- Speed / range
local useMph = TRUE          -- false = km/h, true = mph
local fuelKmsPerLitre = 9      -- km per litre for the range readout

-- Temperature decimal dot adjustments (pixels; negative pulls dot left / closer)
local AMBIENT_DOT_SHIFT = 10
local WATER_DOT_SHIFT   = 20
local OIL_DOT_SHIFT     = 20

-- Temperature decimals shown (e.g. 1 => “85.3”)
local TEMP_DECIMALS = 0

-- Tyre readout positions (edit to taste)
local TYRE_P_FONT  = "mg"
local TYRE_T_FONT  = "mg"
local TYRE_P_SIZE  = vec2(40, 80)    -- pressure text size
local TYRE_T_SIZE  = vec2(40, 80)    -- temperature text size
local TYRE_P_COLOR = rgbm(1,1,1,1)
local TYRE_T_COLOR = rgbm(1,1,1,1)

-- FL / FR / RL / RR positions (pressures)
local POS_P_FL = vec2( 300, 1520)
local POS_P_FR = vec2(1680, 1520)
local POS_P_RL = vec2( 300, 1700)
local POS_P_RR = vec2(1680, 1700)

-- FL / FR / RL / RR positions (temperatures)
local POS_T_FL = vec2( 300, 1588)
local POS_T_FR = vec2(1680, 1588)
local POS_T_RL = vec2( 300, 1768)
local POS_T_RR = vec2(1680, 1768)

---------------------------------- DISPLAY COLOURS ----------------------------
local white = rgbm(1, 1, 1,1)

---------------------------------- GEAR MAPS ----------------------------------
local gearT = { [-1]="R",[0]="P",[1]="1",[2]="2",[3]="3",[4]="4",[5]="5",[6]="6",[7]="7",[8]="8" }
local gearM = { [0]="N", [1]="D",[2]="D",[3]="D",[4]="4",[5]="5",[6]="6",[7]="7",[8]="8" }

---------------------------------- HELPERS ------------------------------------
local function v(str) local x,y=str:match("([^,]+),%s*([^,]+)"); return vec2(tonumber(x), tonumber(y)) end
local function clamp(val,a,b) return (val<a) and a or (val>b) and b or val end

-- Draw one decimal number with a movable dot (closer/tighter kerning)
-- pos = where the INTEGER part is anchored (alignment/width apply to that)
local function drawTightDecimal(value, decimals, pos, letter, font, color, align, width, spacing, dotShiftPx)
  local s = string.format("%."..tostring(decimals or 1).."f", value or 0)
  local intPart, decPart = s:match("^(%-?%d+)%.(%d+)$")
  if not intPart then intPart, decPart = tostring(math.floor(tonumber(value or 0)+0.5)), "0" end

  -- draw integer (normal)
  display.text{
    text = intPart,
    pos = pos,
    letter = letter,
    font = font,
    color = color,
    alignment = align or 0.5,
    width = width or 0,
    spacing = spacing or 0
  }

  -- measure approx digit advance as a fraction of letter.x (works well with mono-ish cluster fonts)
  local adv = letter.x * 0.6
  -- anchor for dot: start at end of intPart then add dotShiftPx
  local dotX = pos.x + (adv * #intPart) + (dotShiftPx or 0)
  local dotPos = vec2(dotX, pos.y)

  -- dot
  display.text{
    text = ".",
    pos = dotPos,
    letter = letter,
    font = font,
    color = color,
    alignment = 0, width = 0,
    spacing = spacing or 0
  }

  -- decimals: nudge a little after the dot
  local decPos = vec2(dotPos.x + (letter.x * 0.6), pos.y)
  display.text{
    text = decPart,
    pos = decPos,
    letter = letter,
    font = font,
    color = color,
    alignment = 0, width = 0,
    spacing = spacing or 0
  }
end

---------------------------------- RECT DRAW HELPER ---------------------------
local function rect(x,y,w,h,c,opacity)
  display.rect{ pos=vec2(x,y), size=vec2(w,h), color=c, opacity=opacity or 1 }
end

---------------------------------- MASKED ALPHA FILL (kept for your bar) ------
local ENABLE_MASKED_ALPHA_BAR = true
local ALPHA_MASK_PATH = "cluster/urus_cluster_mask.png"
local BAR_POS  = vec2(0, 0)
local BAR_SIZE = vec2(0, 0)
local BAR_FADE = 8

local _maskTex = nil
local function maskTex()
  if _maskTex ~= nil then return _maskTex end
  local ok, tex = pcall(function() return display.loadTexture(ALPHA_MASK_PATH) end)
  _maskTex = ok and tex or false
  return _maskTex
end
local function drawAlphaFillBar(pos, size, fraction, fadePx)
  local w = math.floor(size.x * clamp(fraction or 0, 0, 1) + 0.5)
  if w <= 0 then return end
  local fade = math.max(tonumber(fadePx) or 0, 0)
  local solidW = math.max(w - fade, 0)
  if solidW > 0 then display.rect{ pos = pos, size = vec2(solidW, size.y), color = rgb(0,0,0), opacity = 1 } end
  local rest = w - solidW
  if rest > 0 then
    local slices = math.max(math.ceil(rest / 4), 4)
    local segW   = rest / slices
    for i = 0, slices - 1 do
      local a  = (i + 1) / slices
      local sx = pos.x + solidW + math.floor(i * segW + 0.5)
      local sw = math.ceil(segW)
      if sw > 0 then display.rect{ pos = vec2(sx, pos.y), size = vec2(sw, size.y), color = rgb(0,0,0), opacity = a } end
    end
  end
end
local function drawMaskedAlphaFillBar(pos, size, fraction, fadePx)
  local tex = maskTex()
  if not tex then return drawAlphaFillBar(pos, size, fraction, fadePx) end
  local f = clamp(fraction or 0, 0, 1); if f <= 0 then return end
  local filledPx = size.x * f
  display.image{ texture = tex, pos = pos, size = vec2(filledPx, size.y), uvStart = vec2(0,0), uvEnd = vec2(f,1), color = rgbm(0,0,0,1) }
  local fade = math.max(tonumber(fadePx) or 0, 0)
  if fade > 0 then
    local fadeW  = math.min(fade, filledPx)
    local slices = math.max(math.ceil(fadeW / 4), 4)
    local segW   = fadeW / slices
    for i = 0, slices - 1 do
      local segPx0 = filledPx - fadeW + i * segW
      local segPx1 = segPx0 + segW
      local uv0 = segPx0 / size.x
      local uv1 = segPx1 / size.x
      local sx = pos.x + segPx0
      local sw = segW
      local a  = 1 - (i + 1) / slices
      display.image{ texture = tex, pos = vec2(sx, pos.y), size = vec2(sw, size.y), uvStart = vec2(uv0,0), uvEnd = vec2(uv1,1), color = rgbm(0,0,0,a) }
    end
  end
end
local function alphaBarFraction()
  if car and car.maxFuel and car.maxFuel > 0 then return math.max(0, math.min(1, (car.fuel or 0) / car.maxFuel)) end
  return 0
end

--══════════════════════════════════════════════════════════════════════════════
--            761              BAR CONFIG (Fuel smooth + Turbo boxes)
--══════════════════════════════════════════════════════════════════════════════

-- 
--══════════════════════════════════════════════════════════════════════════════
--                         TYRE HELPERS (pressure & temp)
--══════════════════════════════════════════════════════════════════════════════
local function readWheel(i)
  local st = (ac and ac.getCarState) and ac.getCarState(0) or nil
  local w = (st and st.wheels and st.wheels[i]) or nil
  if not w then return { pres=0, temp=0 } end
  local p = w.tyrePressure or w.tyrePressureKpa or 0
  -- auto-convert to bar if looks like kPa
  if p > 10 then p = p * 0.01 end
  local t = w.tyreCoreTemperature or w.tyreSurfaceTemperature or w.tyreContactTemperature or 0
  return { pres = p, temp = t }
end

--══════════════════════════════════════════════════════════════════════════════
--                                   UPDATE
--══════════════════════════════════════════════════════════════════════════════
local function cluster_update(dt)
  -- Live values
  local speedKmh = car.speedKmh
  local speedVal = useMph and (speedKmh / 1.609344) or speedKmh

  local timeText   = string.format("%02d:%02d", sim.timeHours, sim.timeMinutes)
  local timeText2  = string.format("%02d:%02d", sim.timeHours, sim.timeMinutes)
  local speedText  = tostring(math.floor(speedVal / 1.609344))
  local tempAmbient  = (sim.ambientTemperature)
  local gearText   = gearT[car.gear]
  local rangeText  = tostring(math.floor(car.fuel * fuelKmsPerLitre))
  local totalText  = string.format("%1.4d", car.distanceDrivenTotalKm)
  local sessText   = string.format("%1d", car.distanceDrivenSessionKm)

  -- >>> Only change here: use raw number so drawTightDecimal formats it <<<
  local waterValue = (car.waterTemperature or 0)
  local oilValue   = (car.oilTemperature or 0)

  -- 🕒 TIME
-- clock text split into hours / colon / minutes
local TIME_HOURS_POS   = "929, 985.2"
local TIME_COLON_POS   = "980, 985.2"
local TIME_MINUTES_POS = "1005.0, 985.2"

local TIME_LETTER   = "35, 80"
local TIME_FONT     = "e92_big"
local TIME_COLOR    = 1
local TIME_SPACING  = -3
local TIME_HOURS_ALIGN   = 0.9
local TIME_COLON_ALIGN   = 0.5
local TIME_MINUTES_ALIGN = 0.9

local hoursText, minutesText = tostring(timeText):match("^(%d+):(%d+)$")

if hoursText and minutesText then
  display.text({
    text = hoursText,
    pos = v(TIME_HOURS_POS),
    letter = v(TIME_LETTER),
    font = TIME_FONT,
    color = TIME_COLOR,
    alignment = TIME_HOURS_ALIGN,
    width = 0,
    spacing = TIME_SPACING
  })

  display.text({
    text = ":",
    pos = v(TIME_COLON_POS),
    letter = v(TIME_LETTER),
    font = TIME_FONT,
    color = TIME_COLOR,
    alignment = TIME_COLON_ALIGN,
    width = 0,
    spacing = TIME_SPACING
  })

  display.text({
    text = minutesText,
    pos = v(TIME_MINUTES_POS),
    letter = v(TIME_LETTER),
    font = TIME_FONT,
    color = TIME_COLOR,
    alignment = TIME_MINUTES_ALIGN,
    width = 0,
    spacing = TIME_SPACING
  })
end



  -- 📏 TOTAL KM
  display.text({ text = totalText, pos = v("755, 1179"), letter = v("35, 70"),
    font = "e92_big", color = white, alignment = 0.5, width = 250, spacing =-4 })

  -- 📏 SESSION KM
  display.text({ text = sessText, pos = v("993, 1179"), letter = v("35, 70"),
    font = "e92_big", color = white, alignment = 0.5, width = 250, spacing =0 })

  -- 🛣 gear
  display.text({ text =gearText, pos = v("1425.1, 902.5"), letter = v("35, 90"),
    font ="e92_big", color = white, alignment = 1, width = 155, spacing = -1 })

  -- 🌡 AMBIENT TEMP (tight dot)
  drawTightDecimal(tempAmbient, TEMP_DECIMALS, v("840.7, 925.9"), v("35, 75"), "e92_big", white, 0.5, 250, -4, AMBIENT_DOT_SHIFT)


  -- 🛢 OIL PRESSURE (kept as in your last version, tweak if needed)


  --═══════════════════════ Masked Alpha Bar (if used) ════════════════════════
  if ENABLE_MASKED_ALPHA_BAR then
    drawMaskedAlphaFillBar(BAR_POS, BAR_SIZE, alphaBarFraction(), BAR_FADE)
  end

  --═══════════════════════ Smooth Fuel Bar ═══════════════════════════════════
  local fuelFrac = (car and car.maxFuel and car.maxFuel > 0) and clamp((car.fuel or 0) / car.maxFuel, 0, 1) or 0
  rect(BAR_FUEL.x, BAR_FUEL.y, BAR_FUEL.w, BAR_FUEL.h, FUEL_BG_COLOR, 1)      -- background
  local fillW = BAR_FUEL.w * fuelFrac
  if fillW > 0.5 then rect(BAR_FUEL.x, BAR_FUEL.y, fillW, BAR_FUEL.h, FUEL_FILL_COLOR, 1) end

  --═══════════════════════ Turbo spool bar (boxes, no outline) ═══════════════
  local turboF = getTurboFrac()
  drawBarDiscrete(BAR_TURBO, TURBO_FILL_MODE, TURBO_BOXES_HALF, TURBO_BOXES_TOTAL, TURBO_GAP_PX, turboF, colorAtFracTurbo)

  --═══════════════════════ Tyres: pressures (bar) & temps (°C) ═══════════════
  local fl = readWheel(0)  -- FL
  local fr = readWheel(1)  -- FR
  local rl = readWheel(2)  -- RL
  local rr = readWheel(3)  -- RR

  display.text{ text = string.format("%.1f", fl.pres), pos = POS_P_FL, letter = TYRE_P_SIZE, font = TYRE_P_FONT, color = TYRE_P_COLOR, alignment = 0.5, width = 0, spacing = -5 }
  display.text{ text = string.format("%.1f", fr.pres), pos = POS_P_FR, letter = TYRE_P_SIZE, font = TYRE_P_FONT, color = TYRE_P_COLOR, alignment = 0.5, width = 0, spacing = -5 }
  display.text{ text = string.format("%.1f", rl.pres), pos = POS_P_RL, letter = TYRE_P_SIZE, font = TYRE_P_FONT, color = TYRE_P_COLOR, alignment = 0.5, width = 0, spacing = -5 }
  display.text{ text = string.format("%.1f", rr.pres), pos = POS_P_RR, letter = TYRE_P_SIZE, font = TYRE_P_FONT, color = TYRE_P_COLOR, alignment = 0.5, width = 0, spacing = -5 }

  display.text{ text = string.format("%d", math.floor(fl.temp+0.5)), pos = POS_T_FL, letter = TYRE_T_SIZE, font = TYRE_T_FONT, color = TYRE_T_COLOR, alignment = 0.5, width = 0, spacing = -5 }
  display.text{ text = string.format("%d", math.floor(fr.temp+0.5)), pos = POS_T_FR, letter = TYRE_T_SIZE, font = TYRE_T_FONT, color = TYRE_T_COLOR, alignment = 0.5, width = 0, spacing = -5 }
  display.text{ text = string.format("%d", math.floor(rl.temp+0.5)), pos = POS_T_RL, letter = TYRE_T_SIZE, font = TYRE_T_FONT, color = TYRE_T_COLOR, alignment = 0.5, width = 0, spacing = -5 }
  display.text{ text = string.format("%d", math.floor(rr.temp+0.5)), pos = POS_T_RR, letter = TYRE_T_SIZE, font = TYRE_T_FONT, color = TYRE_T_COLOR, alignment = 0.5, width = 0, spacing = -5 }
end

function update(dt)
  cluster_update(dt)
end
