HelicopterMode = {}
local HelicopterMode_mt = Class(HelicopterMode)

function HelicopterMode.prerequisitesPresent(specializations)
    return true
end

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

function HelicopterMode:onLoad(savegame)
    self.setHelicopterInput = HelicopterMode.setHelicopterInput
    self.setSprayerState = HelicopterMode.setSprayerState

    self.heli_inputW = false
    self.heli_inputS = false
    self.heli_inputA = false
    self.heli_inputD = false
    self.heli_inputLMB = false
    self.heli_inputRMB = false

    self.lastInputW = false
    self.lastInputS = false
    self.lastInputA = false
    self.lastInputD = false
    self.lastInputLMB = false
    self.lastInputRMB = false

    self.levitatorPitch = 0
    self.levitatorAltitude = 0
    self.sprayerActive = false

    self.startDelayDuration = 4000
    self.startDelayTimer = 0
    self.engineLastState = self:getIsMotorStarted()

    local workAreaNode = I3DUtil.indexToObject(self.components[1].node, "0|0|0|0|4|0|0|0")
    if workAreaNode ~= nil then
        self.workAreaNode = workAreaNode
        self.originalWorkAreaPos = { x = 4000, y = 0, z = 0 }
        setTranslation(self.workAreaNode, 4000, 0, 0)
    end

    setCenterOfMass(self.components[1].node, 0, -1, 0)
end

function HelicopterMode:onRegisterActionEvents(isSelected, isOnActiveVehicle)
    if not self.isClient or not isOnActiveVehicle then
        return
    end

    local spec = self.spec_enterable
    if spec == nil then
        return
    end

    -- Védelem: actionEvents tábla létrehozása, ha nem létezik
    if spec.actionEvents == nil then
        spec.actionEvents = {}
    end

    -- Védelem: InputAction enum ellenőrzés (létezik-e)
    local function safeAdd(actionName)
        if InputAction[actionName] ~= nil then
            self:addActionEvent(spec.actionEvents, InputAction[actionName], self, nil, false, true, false, true)
        end
    end

    safeAdd("Heli_UP")
    safeAdd("Heli_DOWN")
    safeAdd("Heli_FORWARD")
    safeAdd("Heli_BACK")
    safeAdd("Heli_LEFT")
    safeAdd("Heli_RIGHT")
end

function HelicopterMode.setHelicopterInput(self, w, s, a, d, lmb, rmb)
    self.heli_inputW = w
    self.heli_inputS = s
    self.heli_inputA = a
    self.heli_inputD = d
    self.heli_inputLMB = lmb
    self.heli_inputRMB = rmb
end

function HelicopterMode.setSprayerState(self, state)
    if self.sprayerActive ~= state then
        self.sprayerActive = state
        if self.workAreaNode ~= nil then
            if state then
                setTranslation(self.workAreaNode, 0, 0, 0)
            else
                setTranslation(self.workAreaNode, 0, 0, 4000)
            end
        end
    end
end

function HelicopterMode:onUpdate(dt, isActiveForInput, isActiveForInputIgnoreSelection, isSelected)
    if not self:getIsControlled() then return end

    local engineState = self:getIsMotorStarted()
    if engineState ~= self.engineLastState then
        self.engineLastState = engineState
        if engineState then
            self.startDelayTimer = self.startDelayDuration
        else
            self.startDelayTimer = 0
        end
    end

    if not engineState then return end
    if self.startDelayTimer > 0 then
        self.startDelayTimer = self.startDelayTimer - dt
        return
    end

    -- CLIENT input lekérés és event küldés szervernek
    if self.isClient and self:getIsActiveForInput(true) then
        local w = Input.isKeyPressed(Input.KEY_w)
        local s = Input.isKeyPressed(Input.KEY_s)
        local a = Input.isKeyPressed(Input.KEY_a)
        local d = Input.isKeyPressed(Input.KEY_d)
        local lmb = Input.isMouseButtonPressed(Input.MOUSE_BUTTON_LEFT)
        local rmb = Input.isMouseButtonPressed(Input.MOUSE_BUTTON_RIGHT)

        if self.lastInputW ~= w or self.lastInputS ~= s or self.lastInputA ~= a or self.lastInputD ~= d
        or self.lastInputLMB ~= lmb or self.lastInputRMB ~= rmb then
            self.lastInputW = w
            self.lastInputS = s
            self.lastInputA = a
            self.lastInputD = d
            self.lastInputLMB = lmb
            self.lastInputRMB = rmb

            g_client:getServerConnection():sendEvent(HelicopterInputEvent.new(self, w, s, a, d, lmb, rmb))
        end
    end

    -- Altitude számítása mindig kell (kliensnek is!)
    local node = self.components[1].node
    local px, py, pz = getWorldTranslation(node)
    local groundY = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, px, 0, pz)
    local altAboveGround = math.max(0, py - groundY)
    self.levitatorAltitude = altAboveGround

    -- Sprayer animáció kliensen fusson
    if self.isClient then
        local sprayState = altAboveGround > 1 and altAboveGround <= 13
        self:setSprayerState(sprayState)
    end

    -- A többi mozgás csak szerveren
    if not self.isServer then return end

    local mass = self:getTotalMass(true)
    local downForce = mass * -9.81
    local yForce = downForce * -0.85

    if self.heli_inputLMB then
        self.levitatorPitch = math.min(self.levitatorPitch + 5, 30)
    elseif self.heli_inputRMB then
        self.levitatorPitch = math.max(self.levitatorPitch - 5, -30)
    else
        self.levitatorPitch = math.abs(self.levitatorPitch) > 0.1 and self.levitatorPitch * 0.75 or 0
    end

    local dX, _, dZ = localDirectionToWorld(node, 1, 0, 0)
    local sinDir = dX / 15
    local cosDir = dZ / -15
    local moveSpeed = 200

    local axisForward = self.heli_inputW and 1 or (self.heli_inputS and -1 or 0)

    local zSteer = moveSpeed * axisForward
    local xForce = zSteer * cosDir
    local zForce = zSteer * sinDir
local gravity = -6.81
local hoverCompensation = 1.00  -- pontosan ellensúlyozzuk a gravitációt
local hoverBoost = 0.01         -- pici emelkedés (0.01–0.03 a javasolt tartomány)

local yLift = 0
if not self.heli_inputLMB and not self.heli_inputRMB then
    yLift = mass * -gravity * (hoverCompensation + hoverBoost)
else
    yLift = downForce * -0.85 + self.levitatorPitch
end

yForce = yLift

    addForce(node, xForce, yForce, zForce, 0, 1.2, 0, true)

    local yTurn = self.heli_inputA and 1 or (self.heli_inputD and -1 or 0)
    local _, AVy, _ = getAngularVelocity(node)
    if yTurn == 0 then yTurn = AVy * 0.85 end
    setAngularVelocity(node, 0, yTurn, 0)

    setLinearDamping(node, 0.15)
    setAngularDamping(node, 0.01)
end

function HelicopterMode:onDraw()
    if self.components == nil or self.components[1] == nil then return end

    local node = self.components[1].node
    local px, py, pz = getWorldTranslation(node)
    local groundY = getTerrainHeightAtWorldPos(g_currentMission.terrainRootNode, px, 0, pz)
    local altAboveGround = math.max(0, py - groundY)
    local height = string.format("%.1f", altAboveGround)

    setTextAlignment(RenderText.ALIGN_CENTER)

    if not self:getIsMotorStarted() then
        setTextColor(1, 0.6, 0, 1)
        setTextBold(true)
        renderText(0.5, 0.06, 0.02, g_i18n:getText("heli_motor_off"))
        return
    end

    if self.startDelayTimer > 0 then
        setTextColor(1, 1, 0, 1)
        setTextBold(true)
        renderText(0.5, 0.06, 0.02, g_i18n:getText("heli_starting"))
        return
    end

    setTextColor(1, 1, 0, 1)
    setTextBold(false)
    renderText(0.5, 0.03, 0.016, string.format(g_i18n:getText("heli_altitude"), height))

    if altAboveGround > 1 and altAboveGround <= 13 then
        setTextColor(0.2, 1, 0.2, 1)
        setTextBold(true)
        renderText(0.5, 0.05, 0.02, g_i18n:getText("info_spray_height_ok"))
    else
        setTextColor(1, 0.2, 0.2, 1)
        setTextBold(true)
        renderText(0.5, 0.05, 0.02, g_i18n:getText("info_spray_height_not_ok"))
    end

    setTextBold(false)
    setTextColor(1, 1, 1, 1)
end
