-- entities/laundromat_machine/cl_init.lua
-- Rendu client de la machine de laverie :
--   • ENT:Draw()            — rendu du modèle standard
--   • ENT:DrawTranslucent() — HUD 3D2D billboard au-dessus (si occupée)
--   • HUDPaint hook         — tooltip 2D contextuel (throttlé 20 Hz)

include("shared.lua")

-- ============================================================================
-- Draw — rendu standard du modèle
-- ============================================================================

function ENT:Initialize()
    self:SetNextClientThink(CurTime())
end

function ENT:Draw()
    self:DrawModel()
end

-- ============================================================================
-- Think client : pilote le son loopé + l'émetteur de particules selon
-- l'état NW2 de la machine. Throttlé à ~20 Hz.
-- ============================================================================

function ENT:Think()
    if not Laundromat or not Laundromat.Config then
        self:SetNextClientThink(CurTime() + 1)
        return true
    end

    local user     = self:GetNW2Entity("laundromat_user")
    local isActive = IsValid(user)

    -- Son loopé : start/stop selon état
    if isActive and not self._loopSound then
        local path = Laundromat.Config.SoundLoop or "ambient/levels/labs/equipment_printer_loop1.wav"
        self._loopSound = CreateSound(self, path)
        self._loopSound:PlayEx(Laundromat.Config.SoundVolume or 0.6, 100)
    elseif not isActive and self._loopSound then
        self._loopSound:Stop()
        self._loopSound = nil
    end

    -- Particules de vapeur : émission throttlée tant qu'active
    if isActive and Laundromat.Config.EnableParticles then
        if not self._emitter then
            self._emitter = ParticleEmitter(self:GetPos() + Vector(0, 0, 50))
        end
        if (self._nextEmit or 0) < CurTime() then
            self._nextEmit = CurTime() + 0.15
            local pos = self:GetPos() + Vector(math.Rand(-8, 8), math.Rand(-8, 8), 55)
            local p   = self._emitter:Add("particles/smokey", pos)
            if p then
                p:SetVelocity(Vector(math.Rand(-5, 5), math.Rand(-5, 5), math.Rand(20, 35)))
                p:SetDieTime(2)
                p:SetStartAlpha(180)
                p:SetEndAlpha(0)
                p:SetStartSize(8)
                p:SetEndSize(22)
                p:SetColor(220, 220, 220)
                p:SetAirResistance(20)
                p:SetGravity(Vector(0, 0, 5))
            end
        end
    elseif not isActive and self._emitter then
        self._emitter:Finish()
        self._emitter = nil
    end

    self:SetNextClientThink(CurTime() + 0.05)
    return true
end

-- Cleanup propre des ressources (son + emitter) à la suppression
function ENT:OnRemove()
    if self._loopSound then
        self._loopSound:Stop()
        self._loopSound = nil
    end
    if self._emitter then
        self._emitter:Finish()
        self._emitter = nil
    end
end

-- ============================================================================
-- DrawTranslucent — HUD 3D2D au-dessus de la machine (visible par tous)
-- N'affiche rien si la machine est libre ou si le joueur est trop loin.
-- ============================================================================

function ENT:DrawTranslucent()
    self:DrawModel()

    -- Vérification config (lazy pour respecter l'ordre de chargement)
    if not Laundromat or not Laundromat.Config then return end

    -- Lire l'état NW2 de la machine
    local user = self:GetNW2Entity("laundromat_user")
    if not IsValid(user) then return end

    -- Lumière dynamique pulsante dorée pendant le cycle
    if Laundromat.Config.EnableDynLight then
        local dl = DynamicLight(self:EntIndex())
        if dl then
            local pulse  = 0.75 + math.sin(CurTime() * 4) * 0.25
            dl.pos        = self:GetPos() + Vector(0, 0, 40)
            dl.r          = 212
            dl.g          = 175
            dl.b          = 55
            dl.brightness = pulse * 1.6
            dl.decay      = 0
            dl.size       = 220
            dl.dietime    = CurTime() + 0.1
        end
    end

    if not Laundromat.Config.HUD3D2D then return end

    local ply = LocalPlayer()
    if not IsValid(ply) then return end

    -- LOD distance
    local maxD = Laundromat.Config.HUD3D2D_MaxDistance or 1000
    if ply:GetPos():DistToSqr(self:GetPos()) > maxD * maxD then return end

    -- Données de progression depuis les NW2 vars
    local startedAt = self:GetNW2Float("laundromat_startedAt", 0)
    local endsAt    = self:GetNW2Float("laundromat_endsAt", 0)
    local amount    = self:GetNW2Int("laundromat_amount", 0)
    local duration  = math.max(endsAt - startedAt, 0.001)
    local progress  = math.Clamp((CurTime() - startedAt) / duration, 0, 1)

    -- Position au-dessus de la machine (billboard face au joueur)
    local offsetZ = Laundromat.Config.HUD3D2D_OffsetZ or 70
    local pos     = self:GetPos() + Vector(0, 0, offsetZ)

    -- Couleurs via DBALib.Theme (lazy — fallback sur valeurs hardcodées si non dispo)
    local colBg     = (DBALib and DBALib.Theme and DBALib.Theme.palette and DBALib.Theme.palette.bg
                      and DBALib.Theme.palette.bg.surface) or Color(20, 20, 30, 220)
    local colGold   = (DBALib and DBALib.Theme and DBALib.Theme.palette and DBALib.Theme.palette.gold
                      and DBALib.Theme.palette.gold.base) or Color(212, 175, 55)
    local colText   = (DBALib and DBALib.Theme and DBALib.Theme.palette and DBALib.Theme.palette.text
                      and DBALib.Theme.palette.text.primary) or Color(230, 230, 230)
    local colMuted  = (DBALib and DBALib.Theme and DBALib.Theme.palette and DBALib.Theme.palette.text
                      and DBALib.Theme.palette.text.muted) or Color(150, 150, 150)
    local colBarBg  = (DBALib and DBALib.Theme and DBALib.Theme.palette and DBALib.Theme.palette.bg
                      and DBALib.Theme.palette.bg.elevated) or Color(40, 40, 50, 200)

    -- Polices via DBALib.Fonts (lazy — fallback sur polices GMod)
    local fontTitle = (DBALib and DBALib.Fonts and DBALib.Fonts.Body_lg) or "DermaDefaultBold"
    local fontSub   = (DBALib and DBALib.Fonts and DBALib.Fonts.Body_md) or "DermaDefault"
    local fontPct   = (DBALib and DBALib.Fonts and DBALib.Fonts.Body_sm) or "DermaDefault"

    -- Format montant
    local amountStr = (DBALib and DBALib.Format and DBALib.Format.Money)
                      and DBALib.Format.Money(amount)
                      or tostring(amount) .. " €"

    -- Angle billboard : face au joueur
    cam.Start3D2D(pos, Angle(0, ply:EyeAngles().y - 90, 90), 0.1)

        -- Fond arrondi
        draw.RoundedBox(8, -200, -60, 400, 120, colBg)

        -- Titre
        draw.SimpleText(
            "Blanchiment en cours",
            fontTitle,
            0, -40,
            colGold,
            TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER
        )

        -- Sous-titre : Nick + montant
        draw.SimpleText(
            user:Nick() .. "  —  " .. amountStr,
            fontSub,
            0, -10,
            colText,
            TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER
        )

        -- Fond de la barre de progression
        draw.RoundedBox(4, -180, 20, 360, 12, colBarBg)

        -- Barre de progression remplie
        local fillW = math.floor(360 * progress)
        if fillW > 0 then
            draw.RoundedBox(4, -180, 20, fillW, 12, colGold)
        end

        -- Pourcentage
        draw.SimpleText(
            string.format("%d%%", math.floor(progress * 100)),
            fontPct,
            0, 45,
            colMuted,
            TEXT_ALIGN_CENTER, TEXT_ALIGN_CENTER
        )

    cam.End3D2D()
end

-- ============================================================================
-- Tooltip 2D (HUDPaint) — quand le joueur regarde la machine
-- Throttlé à 20 Hz (0.05s) pour éviter la surcharge
-- ============================================================================

-- Throttle uniquement le RECALCUL (trace + NW2 reads).
-- Le draw a lieu chaque frame depuis le cache pour éviter le clignotement.
local _nextTooltipCheck = 0
local _cachedTooltip    = nil  -- { text = string, color = Color } | nil

hook.Add("HUDPaint", "Laundromat.Machine.Tooltip", function()
    -- Refresh du cache (20 Hz)
    if CurTime() >= _nextTooltipCheck then
        _nextTooltipCheck = CurTime() + 0.05
        _cachedTooltip    = nil

        local ply = LocalPlayer()
        if IsValid(ply) then
            local tr = ply:GetEyeTrace()
            if IsValid(tr.Entity) and tr.Entity:GetClass() == "laundromat_machine" then
                local machine = tr.Entity
                local maxDist = (Laundromat and Laundromat.Config and Laundromat.Config.MaxDistance) or 150
                if ply:GetPos():DistToSqr(machine:GetPos()) <= (maxDist * maxDist) then
                    local user = machine:GetNW2Entity("laundromat_user")
                    local text, color
                    local gold = (DBALib and DBALib.Theme and DBALib.Theme.palette
                                  and DBALib.Theme.palette.gold and DBALib.Theme.palette.gold.base)
                                 or Color(212, 175, 55)

                    if not IsValid(user) then
                        text  = "[E] Blanchir de l'argent (laverie)"
                        color = gold
                    elseif user == ply then
                        text  = "[E] Voir la progression"
                        color = gold
                    else
                        text  = "Occupée par " .. user:Nick()
                        color = Color(220, 100, 100)
                    end

                    _cachedTooltip = { text = text, color = color }
                end
            end
        end
    end

    -- Draw chaque frame depuis le cache
    if not _cachedTooltip then return end

    local font = (DBALib and DBALib.Fonts and DBALib.Fonts.Body_lg) or "DermaDefaultBold"

    draw.SimpleTextOutlined(
        _cachedTooltip.text,
        font,
        ScrW() / 2,
        ScrH() / 2 + 40,
        _cachedTooltip.color,
        TEXT_ALIGN_CENTER,
        TEXT_ALIGN_CENTER,
        1,
        Color(0, 0, 0, 220)
    )
end)
