-- SlotMachine.lua – Slot gép FS22/25 tartás + tét + Extra Óra Bónusz + Dupla vagy Semmi + egyedi HUD + Kettős 3D Kivetítő (Óra és Bank) + hangok + Szimbólum kiírása + EXTRA DOBÓKOCKA JÁTÉK

SlotMachine = {}
SlotMachine.MOD_NAME = g_currentModName

local STEPS, STEP_DEG = 12, 30
local EPS = 1e-4

local function easeOutCubic(t) local i=1-t; return 1-i*i*i end

local REEL_MAP = {
    {"Hetes","Citrom","Szőlő","Szilva","Cseresznye","Bonus","Óra","Harang","Narancs","Dinnye","Csillag","Dobókocka"},
    {"Cseresznye","Óra","Szőlő","Narancs","Bonus","Hetes","Szilva","Citrom","Dobókocka","Harang","Dinnye","Csillag"},
    {"Cseresznye","Citrom","Csillag","Dobókocka","Szőlő","Dinnye","Szilva","Óra","Harang","Hetes","Bonus","Narancs"}
}

-- Szimbólum → alap nyeremény érték € (1-es téten)
local PAYOUT = {
    ["Cseresznye"]=20, ["Citrom"]=30, ["Narancs"]=40, ["Harang"]=65,
    ["Szőlő"]=80, ["Hetes"]=100, ["Dinnye"]=110, ["Csillag"]=120,
    ["Szilva"]=50, ["Bonus"]=130, ["Dobókocka"]=140, ["Óra"]=150
}

local function angleToIndexZNeg(r) local d=math.deg(r); return (math.floor(((-d)+15)/30)%12)+1 end
local function indexToAngleZNeg(i) return math.rad(-((i-1)*STEP_DEG)) end

-- Segédfüggvény: Keresi az adott szimbólum indexét a tárcsán (a garantált nyereményhez)
local function findSymbolIndex(reelIdx, symbolStr)
    for i, sym in ipairs(REEL_MAP[reelIdx]) do
        if sym == symbolStr then return i end
    end
    return 1
end

local function sm_createAndLoadSample(absPath, sampleName)
    local s = createSample(sampleName or "slotSample")
    if not loadSample(s, absPath, false) then
        print(("[SlotMachine] Hang betöltés hiba: %s"):format(tostring(absPath)))
        delete(s); return nil
    end
    return s
end

-- ========= SEGÉDFÜGGVÉNY: 3D Szöveg Kivetítése =========
local function draw3D(node, text, size)
    if not node then return end
    local x, y, z = getWorldTranslation(node)
    local rx, ry, rz = getWorldRotation(node)
    renderText3D(x, y, z, rx, ry, rz, size, text)
end

-- ========= PENZ változtatás EVENT =========
SlotMachinePenzEvent = {}
local SlotMachinePenzEvent_mt = Class(SlotMachinePenzEvent, Event)
InitEventClass(SlotMachinePenzEvent, "SlotMachinePenzEvent")

function SlotMachinePenzEvent.emptyNew() return Event.new(SlotMachinePenzEvent_mt) end
function SlotMachinePenzEvent.new(vehicle, delta)
    local self=SlotMachinePenzEvent.emptyNew(); self.vehicle=vehicle; self.delta=delta; return self
end
function SlotMachinePenzEvent:writeStream(s, c)
    NetworkUtil.writeNodeObject(s, self.vehicle); streamWriteFloat32(s, self.delta)
end
function SlotMachinePenzEvent:readStream(s, c)
    self.vehicle=NetworkUtil.readNodeObject(s); self.delta=streamReadFloat32(s); self:run(c)
end
function SlotMachinePenzEvent:run(connection)
    if self.vehicle ~= nil and self.vehicle.addFillUnitFillLevel ~= nil then
        local spec = self.vehicle.spec_slotMachine
        if spec ~= nil and spec.fillTypePENZ ~= nil then
            local ft = spec.fillTypePENZ
            local idx = 1
            local farmId = self.vehicle:getOwnerFarmId() or g_currentMission:getFarmId() or 1
            if self.vehicle:getFillUnitFillType(idx) ~= ft then
                self.vehicle:setFillUnitFillType(idx, ft)
            end
            self.vehicle:addFillUnitFillLevel(farmId, idx, self.delta, ft, ToolType.UNDEFINED, nil)
        end
    end
end

local function changePENZ(self, delta)
    if delta == 0 then return end
    if self.isServer then
        SlotMachinePenzEvent.run(SlotMachinePenzEvent.new(self, delta))
    else
        g_client:getServerConnection():sendEvent(SlotMachinePenzEvent.new(self, delta))
    end
end

-- ========= spec / hooks =========
function SlotMachine.prerequisitesPresent(specializations) return true end

function SlotMachine.initSpecialization()
    local schema = Vehicle.xmlSchema
    schema:setXMLSpecializationType("slotMachine")
    schema:setXMLSpecializationType()
end

function SlotMachine.registerFunctions(vehicleType)
    SpecializationUtil.registerFunction(vehicleType, "startSpin",           SlotMachine.startSpin)
    SpecializationUtil.registerFunction(vehicleType, "checkWinGrid",        SlotMachine.checkWinGrid)
    SpecializationUtil.registerFunction(vehicleType, "checkPairGrid",       SlotMachine.checkPairGrid)
    SpecializationUtil.registerFunction(vehicleType, "requestWithdraw",     SlotMachine.requestWithdraw)
    SpecializationUtil.registerFunction(vehicleType, "performWithdrawPENZ", SlotMachine.performWithdrawPENZ)
    SpecializationUtil.registerFunction(vehicleType, "toggleHold",          SlotMachine.toggleHold)
    SpecializationUtil.registerFunction(vehicleType, "donChoose",           SlotMachine.donChoose)
    SpecializationUtil.registerFunction(vehicleType, "donBank",             SlotMachine.donBank)
    SpecializationUtil.registerFunction(vehicleType, "changeBet",           SlotMachine.changeBet)
    SpecializationUtil.registerFunction(vehicleType, "stopDiceSpin",        SlotMachine.stopDiceSpin)
end

function SlotMachine.registerEventListeners(vehicleType)
    SpecializationUtil.registerEventListener(vehicleType, "onLoad",                 SlotMachine)
    SpecializationUtil.registerEventListener(vehicleType, "onDelete",               SlotMachine)
    SpecializationUtil.registerEventListener(vehicleType, "onUpdate",               SlotMachine)
    SpecializationUtil.registerEventListener(vehicleType, "onRegisterActionEvents", SlotMachine)
    SpecializationUtil.registerEventListener(vehicleType, "onDraw",                 SlotMachine)
end

function SlotMachine:onLoad(savegame)
    self.spec_slotMachine = {}
    local spec = self.spec_slotMachine

    spec.reelNodes = {
        I3DUtil.indexToObject(self.components, "0>8|0", self.i3dMappings),
        I3DUtil.indexToObject(self.components, "0>8|1", self.i3dMappings),
        I3DUtil.indexToObject(self.components, "0>8|2", self.i3dMappings)
    }
    
    spec.displayNode = I3DUtil.indexToObject(self.components, "23", self.i3dMappings)
    spec.displayNodeBank = I3DUtil.indexToObject(self.components, "24", self.i3dMappings)
    
    -- ÚJ: Dobókocka Node bekötése (25-ös index a kérés szerint)
    spec.diceNode = I3DUtil.indexToObject(self.components, "25", self.i3dMappings)
    
    spec.isSpinning=false; spec.startZ={0,0,0}; spec.targetZ={0,0,0}; spec.targetIdx={1,1,1}
    spec.durationMs={1500,1500,1500}; spec.elapsedMs={0,0,0}; spec.done={false,false,false}; spec.grid={{},{},{}}

    spec.hold = {false,false,false}
    spec.holdUsed = false
    
    spec.betLevel = 1 
    spec.maxBetLevel = 5
    spec.clockBonus = math.random(0, 4000)

    -- ÚJ: Dobókocka Játék Változói
    spec.diceState = "INACTIVE" -- Lehetséges állapotok: INACTIVE, SPINNING, PUMMING, ACTIVE
    spec.diceSpinsLeft = 0
    spec.diceValue = 0
    spec.pummTimer = 0
    spec.pummCount = 0
    spec.nextGuaranteedWin = "Cseresznye" -- Váltakozik: Cseresznye -> Citrom -> Cseresznye...

    local base = self.baseDirectory or ""
    spec.sampleSpin   = sm_createAndLoadSample(base .. "sounds/push.wav", "slot_spin")
    spec.sampleWin    = sm_createAndLoadSample(base .. "sounds/win.wav",  "slot_win")
    spec.sampleStop   = sm_createAndLoadSample(base .. "sounds/megall.wav", "slot_stop")
    spec.sampleYes    = sm_createAndLoadSample(base .. "sounds/yes.wav", "slot_yes")
    spec.sampleNo     = sm_createAndLoadSample(base .. "sounds/no.wav",  "slot_no")
    spec.sampleDoN    = sm_createAndLoadSample(base .. "sounds/duplavagysemmi.wav", "slot_don")
    spec.sampleBankba = sm_createAndLoadSample(base .. "sounds/bankba.wav", "slot_bankba")
    spec.sampleSansz  = sm_createAndLoadSample(base .. "sounds/sansz.wav", "slot_sansz")
    spec.sampleTet    = sm_createAndLoadSample(base .. "sounds/tet.wav", "slot_tet")
    spec.sampleOra    = sm_createAndLoadSample(base .. "sounds/ora.wav", "slot_ora")
    
    -- ÚJ: Dobókocka Hangok Betöltése
    spec.sampleDiceStart = sm_createAndLoadSample(base .. "sounds/dbokocka_kezdet.wav", "slot_dicestart")
    spec.sampleDiceSpin  = sm_createAndLoadSample(base .. "sounds/porgetes.wav", "slot_dicespin")
    spec.sampleDiceStop  = sm_createAndLoadSample(base .. "sounds/dobokocka_veg.wav", "slot_dicestop")
    spec.sampleDicePumm  = sm_createAndLoadSample(base .. "sounds/pumm.wav", "slot_dicepumm")
    spec.sampleDiceKoci  = sm_createAndLoadSample(base .. "sounds/koci1.wav", "slot_dicekoci")

    spec.fillTypePENZ  = g_fillTypeManager:getFillTypeIndexByName("PENZ")
    spec.fillUnitIndex = 1 

    spec.actionEvents = {}
    spec.doubleOrNothingActive = false
    spec.currentWin = 0
    spec.doubleSide = nil
end

function SlotMachine:onDelete()
    local spec=self.spec_slotMachine
    local del=function(s) if s~=nil then delete(s) end end
    del(spec.sampleSpin); del(spec.sampleWin); del(spec.sampleStop)
    del(spec.sampleYes); del(spec.sampleNo); del(spec.sampleDoN)
    del(spec.sampleBankba); del(spec.sampleSansz); del(spec.sampleTet); del(spec.sampleOra)
    
    -- ÚJ hangok törlése
    del(spec.sampleDiceStart); del(spec.sampleDiceSpin); del(spec.sampleDiceStop)
    del(spec.sampleDicePumm); del(spec.sampleDiceKoci)
end

function SlotMachine:onRegisterActionEvents(isActiveForInput, isActiveForInputIgnoreSelection)
    if self.isClient then
        local spec = self.spec_slotMachine
        self:clearActionEventsTable(spec.actionEvents)
        if isActiveForInput then
            local spinAction = InputAction.SLOTSPIN or InputAction.IMPLEMENT_EXTRA
            self:addActionEvent(spec.actionEvents, spinAction, self, SlotMachine.startSpin, false,true,false,true,nil)
            
            if InputAction.SLOT_WITHDRAW ~= nil then self:addActionEvent(spec.actionEvents, InputAction.SLOT_WITHDRAW, self, SlotMachine.requestWithdraw, false,true,false,true,nil) end
            if InputAction.SLOT_HOLD_LEFT ~= nil then self:addActionEvent(spec.actionEvents, InputAction.SLOT_HOLD_LEFT, self, function() self:toggleHold(1) end, false,true,false,true,nil) end
            if InputAction.SLOT_HOLD_MID ~= nil then self:addActionEvent(spec.actionEvents, InputAction.SLOT_HOLD_MID, self, function() self:toggleHold(2) end, false,true,false,true,nil) end
            if InputAction.SLOT_HOLD_RIGHT ~= nil then self:addActionEvent(spec.actionEvents, InputAction.SLOT_HOLD_RIGHT, self, function() self:toggleHold(3) end, false,true,false,true,nil) end
            if InputAction.SLOT_DON_LEFT ~= nil then self:addActionEvent(spec.actionEvents, InputAction.SLOT_DON_LEFT, self, function() self:donChoose("left") end, false,true,false,true,nil) end
            if InputAction.SLOT_DON_RIGHT ~= nil then self:addActionEvent(spec.actionEvents, InputAction.SLOT_DON_RIGHT, self, function() self:donChoose("right") end, false,true,false,true,nil) end
            if InputAction.SLOT_DON_BANK ~= nil then self:addActionEvent(spec.actionEvents, InputAction.SLOT_DON_BANK, self, SlotMachine.donBank, false,true,false,true,nil) end
            if InputAction.SLOT_BET_UP ~= nil then self:addActionEvent(spec.actionEvents, InputAction.SLOT_BET_UP, self, function() self:changeBet(1) end, false,true,false,true,nil) end
            if InputAction.SLOT_BET_DOWN ~= nil then self:addActionEvent(spec.actionEvents, InputAction.SLOT_BET_DOWN, self, function() self:changeBet(-1) end, false,true,false,true,nil) end
            
            -- ÚJ: Kocka megállítása (B gomb)
            local diceStopAction = InputAction.SLOT_DICE_STOP or InputAction.IMPLEMENT_EXTRA3
            self:addActionEvent(spec.actionEvents, diceStopAction, self, SlotMachine.stopDiceSpin, false,true,false,true,nil)
        end
    end
end

-- ========= Tét állítás logika =========
function SlotMachine:changeBet(direction)
    local spec = self.spec_slotMachine
    if spec.isSpinning or spec.doubleOrNothingActive or spec.diceState == "SPINNING" or spec.diceState == "PUMMING" then return end

    if direction > 0 and spec.betLevel < spec.maxBetLevel then
        spec.betLevel = spec.betLevel + 1
        if spec.sampleTet ~= nil then playSample(spec.sampleTet, 1, 1, 0, 0, 0) end
    elseif direction < 0 and spec.betLevel > 1 then
        spec.betLevel = spec.betLevel - 1
        if spec.sampleTet ~= nil then playSample(spec.sampleTet, 1, 1, 0, 0, 0) end
    end
end

function SlotMachine:toggleHold(idx)
    local spec = self.spec_slotMachine
    if spec.isSpinning or spec.diceState == "SPINNING" or spec.diceState == "PUMMING" then return end
    if spec.holdUsed then
        g_currentMission:showBlinkingWarning("Tartás már felhasználva!", 2000)
        return
    end
    spec.hold[idx] = not spec.hold[idx]
    local state = spec.hold[idx] and "BE" or "KI"
    g_currentMission:showBlinkingWarning(("Tárcsa %d tartás: %s"):format(idx, state), 1500)
end

-- ========= Pörgetés =========
function SlotMachine:startSpin()
    local spec = self.spec_slotMachine
    
    -- Blokkolás, ha valami folyamatban van
    if spec.isSpinning or spec.doubleOrNothingActive or spec.diceState == "SPINNING" or spec.diceState == "PUMMING" then return end 
    
    local isGuaranteedWin = (spec.diceState == "ACTIVE" and spec.diceSpinsLeft > 0)

    -- Pénz levonása (Ha Extra Pörgetés van, azt ingyenesnek vesszük, vagy ha fizetősnek szánod, akkor a lenti blokk érvényes rá is)
    if spec.fillTypePENZ ~= nil and not isGuaranteedWin then
        local idx = spec.fillUnitIndex or 1
        local lvl = self:getFillUnitFillLevel(idx) or 0
        local baseSpinCost = 3
        local baseHoldCost = 6
        local currentCost = spec.holdUsed and (baseHoldCost * spec.betLevel) or (baseSpinCost * spec.betLevel)

        if lvl < currentCost then
            g_currentMission:showBlinkingWarning(("Nincs elég PÉNZ a pörgetéshez! (min. %d €)"):format(currentCost), 2500)
            return
        end
        changePENZ(self, -currentCost)
    end

    spec.isSpinning = true
    spec.clockBonus = math.random(0, 4000)

    for i=1,3 do
        if not spec.hold[i] then
            spec.done[i] = false
            spec.elapsedMs[i] = 0
            local _,_,rz = getRotation(spec.reelNodes[i])
            spec.startZ[i] = rz

            if isGuaranteedWin then
                -- GARANTÁLT NYEREMÉNY KISZÁMÍTÁSA (Cseresznye vagy Citrom a középső sorba)
                local targetSym = spec.nextGuaranteedWin
                local targetIdxForReel = findSymbolIndex(i, targetSym)
                
                spec.targetIdx[i] = targetIdxForReel
                local baseAngle = indexToAngleZNeg(targetIdxForReel)
                -- Adunk hozzá pár extra fordulatot a látványért
                local extraRotations = math.random(3, 5) * 360
                spec.targetZ[i] = baseAngle - math.rad(extraRotations)
            else
                -- NORMÁL VÉLETLEN PÖRGETÉS
                local minDeg, maxDeg, step = 60, 2160, 30
                local rndSteps = math.random(minDeg/step, maxDeg/step)
                local targetDeltaDeg = -(rndSteps * step)
                spec.targetZ[i] = rz + math.rad(targetDeltaDeg)
                spec.targetIdx[i] = angleToIndexZNeg(rz + math.rad(targetDeltaDeg))
            end
        else
            spec.done[i] = true
        end
    end

    if spec.hold[1] or spec.hold[2] or spec.hold[3] then
        spec.holdUsed = true
        spec.hold = {false,false,false}
    else
        spec.holdUsed = false
    end

    local baseL = math.random(1200,1500)
    local addM  = math.random(180,420)
    local addR  = math.random(180,420)
    spec.durationMs[1] = baseL
    spec.durationMs[2] = baseL + addM
    spec.durationMs[3] = baseL + addR + addM

    -- Hangok lejátszása az állapottól függően
    if isGuaranteedWin then
        if spec.sampleDiceKoci ~= nil then playSample(spec.sampleDiceKoci, 1, 1, 0, 0, 0) end
    else
        if spec.sampleSpin ~= nil then playSample(spec.sampleSpin, 1, 1, 0, 0, 0) end
    end
end

-- ========= Kocka Megállítása ("B" gomb) =========
function SlotMachine:stopDiceSpin()
    local spec = self.spec_slotMachine
    if spec.diceState ~= "SPINNING" then return end
    
    spec.diceState = "STOPPED"
    
    if spec.sampleDiceSpin ~= nil then stopSample(spec.sampleDiceSpin, 0, 0) end
    if spec.sampleDiceStop ~= nil then playSample(spec.sampleDiceStop, 1, 1, 0, 0, 0) end

    -- Aktuális rotáció lekérése és pozicionálása a legközelebbi 60 fokhoz
    local rx, ry, rz = getRotation(spec.diceNode)
    local degX = math.deg(rx) % -360
    if degX > 0 then degX = degX - 360 end 
    
    -- Kiszámoljuk az indexet 0 és 5 között (0=1, 1=2, 2=3, 3=4, 4=5, 5=6)
    local faceIndex = math.floor(((-degX) + 30) / 60) % 6
    spec.diceValue = faceIndex + 1
    
    local finalRotX = math.rad(-(faceIndex * 60))
    setRotation(spec.diceNode, finalRotX, 0, 0)

    -- Átmenet PUMMING állapotba
    spec.diceState = "PUMMING"
    spec.pummCount = spec.diceValue
    spec.pummTimer = 500 -- Fél másodpercenként játssza le a pumm hangot
end

-- ========= Update Logika =========
function SlotMachine:onUpdate(dt)
    local spec=self.spec_slotMachine
    
    -- 1. KOCKA PÖRGETÉS (Villámgyors rotáció)
    if spec.diceState == "SPINNING" and spec.diceNode ~= nil then
        local rx, ry, rz = getRotation(spec.diceNode)
        -- Villámgyors pörgés az X tengelyen
        local newRx = (rx - (dt * 0.02)) % (math.pi * -2) 
        setRotation(spec.diceNode, newRx, ry, rz)
    end
    
    -- 2. PUMM HANGOK LEJÁTSZÁSA
    if spec.diceState == "PUMMING" then
        spec.pummTimer = spec.pummTimer - dt
        if spec.pummTimer <= 0 then
            if spec.pummCount > 0 then
                if spec.sampleDicePumm ~= nil then playSample(spec.sampleDicePumm, 1, 1, 0, 0, 0) end
                spec.pummCount = spec.pummCount - 1
                spec.pummTimer = 500 -- Várakozás a következő hangig
            else
                -- Végzett a pumm hangokkal, aktiváljuk a bónusz pörgetéseket
                spec.diceSpinsLeft = spec.diceValue
                spec.diceState = "ACTIVE"
                spec.nextGuaranteedWin = "Cseresznye" -- Kezdjük cseresznyével
                g_currentMission:showBlinkingWarning(("Kocka Bónusz! %d garantált találat indul!"):format(spec.diceValue), 3000)
            end
        end
    end

    -- 3. NORMÁL PÖRGETÉS VÉGREHAJTÁSA
    if not spec.isSpinning then return end
    
    local allDone=true
    for i=1,3 do
        if not spec.done[i] then
            allDone=false
            spec.elapsedMs[i]=math.min(spec.durationMs[i], spec.elapsedMs[i]+dt)
            local t=spec.elapsedMs[i]/spec.durationMs[i]; local e=easeOutCubic(t)
            local z=MathUtil.lerp(spec.startZ[i], spec.targetZ[i], e); setRotation(spec.reelNodes[i],0,0,z)
            if spec.elapsedMs[i]>=spec.durationMs[i] then
                setRotation(spec.reelNodes[i],0,0,indexToAngleZNeg(spec.targetIdx[i]))
                spec.done[i]=true
                if spec.sampleStop ~= nil then
                    playSample(spec.sampleStop, 1, 1, 0, 0, 0)
                end
            end
        end
    end
    
    if allDone then
        spec.isSpinning=false
        
        -- Grid feltöltése
        for r=1,3 do spec.grid[r]={} end
        for k=1,3 do
            local _,_,rz = getRotation(spec.reelNodes[k])
            local mid=angleToIndexZNeg(rz); local prev=((mid-2+STEPS)%STEPS)+1; local nxt=((mid)%STEPS)+1
            spec.grid[1][k]=REEL_MAP[k][prev]; spec.grid[2][k]=REEL_MAP[k][mid]; spec.grid[3][k]=REEL_MAP[k][nxt]
        end
        
        -- KOCKA MEGSZÁMLÁLÁSA A 9 MEZŐN (Csak ha nincs aktív kockajáték!)
        if spec.diceState == "INACTIVE" then
            local diceCount = 0
            for r=1,3 do
                for c=1,3 do
                    if spec.grid[r][c] == "Dobókocka" then diceCount = diceCount + 1 end
                end
            end
            
            if diceCount >= 3 then
                -- BÓNUSZ KOCKA JÁTÉK INDÍTÁSA
                spec.diceState = "SPINNING"
                if spec.sampleDiceStart ~= nil then playSample(spec.sampleDiceStart, 1, 1, 0, 0, 0) end
                if spec.sampleDiceSpin ~= nil then playSample(spec.sampleDiceSpin, 0, 1, 0, 0, 0) end -- Végtelen loop
                
                -- Alaphelyzetbe állítjuk a kockát
                setRotation(spec.diceNode, 0, 0, 0)
                g_currentMission:showBlinkingWarning("EXTRA KOCKA JÁTÉK! Állítsd meg a 'B' gombbal!", 5000)
                return -- Kilépünk az Update-ből, nem vizsgálunk sima nyereményt
            end
        end
        
        -- Nyeremények és Párok vizsgálata
        local won,sym = self:checkWinGrid(spec.grid)
        
        if won then
            local baseValue = PAYOUT[sym] or 0
            if baseValue > 0 then
                spec.currentWin = baseValue * spec.betLevel

                if sym == "Óra" then
                    spec.currentWin = spec.currentWin + spec.clockBonus
                    if spec.sampleOra ~= nil then playSample(spec.sampleOra, 1, 1, 0, 0, 0) end
                    
                    changePENZ(self, spec.currentWin)
                    g_currentMission:showBlinkingWarning(("ÓRA BÓNUSZ! Azonnali jóváírás: +%d €"):format(spec.currentWin), 4500)
                    spec.currentWin = 0
                else
                    if spec.sampleWin ~= nil then playSample(spec.sampleWin, 1, 1, 0, 0, 0) end
                    
                    spec.doubleOrNothingActive = true
                    spec.doubleSide = (math.random(0,1)==0) and "left" or "right"
                    if spec.sampleDoN ~= nil then playSample(spec.sampleDoN, 1, 1, 0, 0, 0) end
                    g_currentMission:showBlinkingWarning(("NYERTÉL! Nyeremény: %d € - Válassz BAL / JOBB, vagy BANK!"):format(spec.currentWin), 4000)
                end
            end
            
            -- Ha garantált nyereményünk volt, csökkentjük a számlálót és váltjuk a szimbólumot
            if spec.diceState == "ACTIVE" and spec.diceSpinsLeft > 0 then
                spec.diceSpinsLeft = spec.diceSpinsLeft - 1
                if spec.nextGuaranteedWin == "Cseresznye" then
                    spec.nextGuaranteedWin = "Citrom"
                else
                    spec.nextGuaranteedWin = "Cseresznye"
                end
                
                -- Ha lejárt a bónusz
                if spec.diceSpinsLeft <= 0 then
                    spec.diceState = "INACTIVE"
                end
            end
            
        else
            local hasPair, pairSymbol = self:checkPairGrid(spec.grid)
            
            if not spec.holdUsed and hasPair then
                if spec.sampleSansz ~= nil then playSample(spec.sampleSansz, 1, 1, 0, 0, 0) end
                g_currentMission:showBlinkingWarning(("Sansz! Kettes találat: %s - használd a tartást!"):format(pairSymbol), 3000)
            else
                g_currentMission:showBlinkingWarning("Nem nyertél!",1500)
            end
        end
    end
end

-- ========= Nyerés és Párok ellenőrzése =========
local function triple(a,b,c) return (a~=nil and b~=nil and c~=nil) and (a==b and b==c) end
local function pair(a,b,c)
    if triple(a,b,c) then return false, nil end
    if (a~=nil and b~=nil and a==b) then return true, a end
    if (b~=nil and c~=nil and b==c) then return true, b end
    if (a~=nil and c~=nil and a==c) then return true, a end
    return false, nil
end

function SlotMachine:checkWinGrid(g)
    if triple(g[1][1],g[1][2],g[1][3]) then return true,g[1][1] end
    if triple(g[2][1],g[2][2],g[2][3]) then return true,g[2][1] end
    if triple(g[3][1],g[3][2],g[3][3]) then return true,g[3][1] end
    if triple(g[1][1],g[2][2],g[3][3]) then return true,g[1][1] end
    if triple(g[1][3],g[2][2],g[3][1]) then return true,g[1][3] end
    return false,nil
end

function SlotMachine:checkPairGrid(g)
    local isPair, sym
    isPair, sym = pair(g[1][1],g[1][2],g[1][3]); if isPair then return true, sym end
    isPair, sym = pair(g[2][1],g[2][2],g[2][3]); if isPair then return true, sym end
    isPair, sym = pair(g[3][1],g[3][2],g[3][3]); if isPair then return true, sym end
    isPair, sym = pair(g[1][1],g[2][2],g[3][3]); if isPair then return true, sym end
    isPair, sym = pair(g[1][3],g[2][2],g[3][1]); if isPair then return true, sym end
    return false, nil
end

-- ========= Dupla vagy Semmi logika =========
function SlotMachine:donChoose(side)
    local spec = self.spec_slotMachine
    if not spec.doubleOrNothingActive then return end

    if side == spec.doubleSide then
        spec.currentWin = spec.currentWin * 2
        changePENZ(self, spec.currentWin)
        if spec.sampleYes ~= nil then playSample(spec.sampleYes, 1, 1, 0, 0, 0) end
        g_currentMission:showBlinkingWarning("Dupláztál! Aktuális nyeremény: "..spec.currentWin.." €", 4000)
        spec.doubleSide = (math.random(0,1)==0) and "left" or "right"
    else
        spec.currentWin = 0
        if spec.sampleNo ~= nil then playSample(spec.sampleNo, 1, 1, 0, 0, 0) end
        g_currentMission:showBlinkingWarning("Elbuktad a nyereményt!", 3500)
        if spec.sampleDoN ~= nil then stopSample(spec.sampleDoN, 0, 0) end
        spec.doNPlaying = false
        spec.doubleOrNothingActive = false
    end
end

function SlotMachine:donBank()
    local spec = self.spec_slotMachine
    if not spec.doubleOrNothingActive then return end
    if spec.sampleDoN ~= nil then stopSample(spec.sampleDoN, 0, 0) end
    changePENZ(self, spec.currentWin)
    if spec.sampleBankba ~= nil then playSample(spec.sampleBankba, 1, 1, 0, 0, 0) end
    g_currentMission:showBlinkingWarning("Bankba tetted: +"..spec.currentWin.." €", 3500)
    spec.doubleOrNothingActive = false
end

-- ========= Kifizetés EVENT =========
SlotMachineWithdrawEvent = {}
local SlotMachineWithdrawEvent_mt = Class(SlotMachineWithdrawEvent, Event)
InitEventClass(SlotMachineWithdrawEvent, "SlotMachineWithdrawEvent")
function SlotMachineWithdrawEvent.emptyNew() return Event.new(SlotMachineWithdrawEvent_mt) end
function SlotMachineWithdrawEvent.new(vehicle)
    local self=SlotMachineWithdrawEvent.emptyNew(); self.vehicle=vehicle; return self
end
function SlotMachineWithdrawEvent:writeStream(s,c) NetworkUtil.writeNodeObject(s,self.vehicle) end
function SlotMachineWithdrawEvent:readStream(s,c) self.vehicle=NetworkUtil.readNodeObject(s); self:run(c) end
function SlotMachineWithdrawEvent:run(c)
    if self.vehicle~=nil and self.vehicle.performWithdrawPENZ~=nil then
        self.vehicle:performWithdrawPENZ()
    end
end

function SlotMachine:requestWithdraw()
    if self.isServer then
        self:performWithdrawPENZ()
    else
        g_client:getServerConnection():sendEvent(SlotMachineWithdrawEvent.new(self))
    end
end

function SlotMachine:performWithdrawPENZ()
    if not self.isServer then return end
    local spec=self.spec_slotMachine
    if spec==nil or spec.fillTypePENZ==nil then
        g_currentMission:showBlinkingWarning("Nincs beállítva a PENZ fillType.", 2000)
        return
    end
    local ft   = spec.fillTypePENZ
    local srcI = 1
    if self:getFillUnitFillType(srcI) ~= ft then
        self:setFillUnitFillType(srcI, ft)
    end
    local farmId = self:getOwnerFarmId() or g_currentMission:getFarmId() or 1
    local amount = self:getFillUnitFillLevel(srcI) or 0
    if amount <= 0 then
        g_currentMission:showBlinkingWarning("Üres a gép – nincs kifizetés.", 2000)
        return
    end
    self:addFillUnitFillLevel(farmId, srcI, -amount, ft, ToolType.UNDEFINED, nil)
    g_currentMission:addMoney(amount, farmId, MoneyType.OTHER, true, true)
    g_currentMission:showBlinkingWarning(("Kifizetés kész! +%d €"):format(amount), 3500)
end

-- ========= Egyedi képernyő (HUD és 3D) rajzolás az irányításhoz =========
function SlotMachine:onDraw()
    if not self.isClient then return end
    local spec = self.spec_slotMachine

    if spec.displayNode ~= nil then
        setTextColor(1, 0, 0, 1) 
        setTextAlignment(RenderText.ALIGN_CENTER) 
        local text3D = string.format("%d", spec.clockBonus)
        draw3D(spec.displayNode, text3D, 0.036)
        setTextColor(1, 1, 1, 1)
        setTextAlignment(RenderText.ALIGN_LEFT)
    end
    
    if spec.displayNodeBank ~= nil then
        local currentBank = 0
        if self.getFillUnitFillLevel ~= nil then
            currentBank = self:getFillUnitFillLevel(spec.fillUnitIndex or 1) or 0
        end
        setTextColor(1, 0, 0, 1) 
        setTextAlignment(RenderText.ALIGN_CENTER)
        local bankText3D = string.format("%d", currentBank)
        draw3D(spec.displayNodeBank, bankText3D, 0.036)
        setTextColor(1, 1, 1, 1)
        setTextAlignment(RenderText.ALIGN_LEFT)
    end

    if self.getIsEntered ~= nil and self:getIsEntered() then
        setTextColor(1, 1, 1, 1) 
        setTextAlignment(RenderText.ALIGN_LEFT)
        
        local posX = 0.02 
        local posY = 0.65 
        local textSize = 0.016 
        local gap = 0.025 
        
        -- HA KOCKA BÓNUSZ VAN, ÍRJUK KI A HUD-RA
        if spec.diceState == "ACTIVE" then
            local diceBonusString = string.format("Extra Kocka Bónusz: %d / %d hátra", spec.diceSpinsLeft, spec.diceValue)
            setTextColor(0, 1, 0, 1) -- Zöld szín a szerencsének
            renderText(posX, posY, textSize * 1.5, diceBonusString)
            posY = posY - gap * 1.5
        end
        
        local clockBonusString = string.format("%s: +%d €", g_i18n:getText("hud_slot_clock_bonus"), spec.clockBonus)
        setTextColor(0, 0.8, 1, 1) 
        renderText(posX, posY, textSize * 1.4, clockBonusString)
        posY = posY - gap * 1.5

        local currentBetString = string.format("%s: %d € (Hold: %d €)", g_i18n:getText("hud_slot_current_bet"), spec.betLevel * 3, spec.betLevel * 6)
        setTextColor(1, 0.8, 0, 1) 
        renderText(posX, posY, textSize * 1.3, currentBetString)
        posY = posY - gap * 1.5

        setTextColor(1, 1, 1, 1)
        renderText(posX, posY, textSize * 1.2, g_i18n:getText("hud_slot_title"))
        posY = posY - gap
        
        -- Itt egy kis HUD segítség a Kocka Megállításhoz
        if spec.diceState == "SPINNING" then
            setTextColor(1, 0, 0, 1)
            renderText(posX, posY, textSize * 1.5, "KOCKA PÖRÖG! NYOMD MEG A 'X' GOMBOT!")
            posY = posY - gap
            setTextColor(1, 1, 1, 1)
        end
        
        renderText(posX, posY, textSize, g_i18n:getText("hud_slot_spin"))
        posY = posY - gap
        renderText(posX, posY, textSize, g_i18n:getText("hud_slot_withdraw"))
        posY = posY - gap
        renderText(posX, posY, textSize, g_i18n:getText("hud_slot_bet_up"))
        posY = posY - gap
        renderText(posX, posY, textSize, g_i18n:getText("hud_slot_bet_down"))
        posY = posY - gap
        renderText(posX, posY, textSize, g_i18n:getText("hud_slot_hold"))
        posY = posY - gap
        renderText(posX, posY, textSize, g_i18n:getText("hud_slot_don"))
        posY = posY - gap
        renderText(posX, posY, textSize, g_i18n:getText("hud_slot_bank"))
    end
end