-- Создаем глобальную таблицу, если ее еще нет
RadialVehicleSwitcher = RadialVehicleSwitcher or {}
RadialVehicleSwitcher.modDir = g_currentModDirectory

function RadialVehicleSwitcher:loadMap(name)
    -- ЭТО ДОЛЖНО ПОЯВИТЬСЯ ПЕРВЫМ
    print("--> [RVS Debug] ВХОД В LOADMAP")

    -- === УСТАНОВКА ЖУЧКА FS25 (С ИНДИКАТОРОМ ПЕРЕХВАТА) ===
    if PlayerHUDUpdater ~= nil and PlayerHUDUpdater.fieldAddFarmland ~= nil then
        PlayerHUDUpdater.fieldAddFarmland = Utils.appendedFunction(PlayerHUDUpdater.fieldAddFarmland,
            function(hudUpdater, data, box)
                if data ~= nil then
                    -- ПРОСТО СОХРАНЯЕМ ССЫЛКУ НА ОРИГИНАЛЬНУЮ ТАБЛИЦУ!
                    -- Теперь RVS будет смотреть в те же живые данные, что и логгер
                    RadialVehicleSwitcher.lastFieldData = data
                end
            end)
        print("--> [RVS Debug] Правильный жучок на PlayerHUDUpdater установлен!")
    end
    -- ====================================================

    print("--> [RadialVehicleSwitcher] Мод загружен (Toggle Mode + 360 Axis + Custom Select!)")

    PlayerInputComponent.registerGlobalPlayerActionEvents = Utils.appendedFunction(
        PlayerInputComponent.registerGlobalPlayerActionEvents, RadialVehicleSwitcher.registerActionEvents)
        
    self.isMenuOpen = false
    self.tabHoldTime = 0
    self.isLoaded = false

    self.menuLevel = 1
    self.selectedCategoryVehicles = {}
    self.favoritesMap = {}

    self.itemHoverTime = 0
    self.lastHoveredIndex = 0
    self.hoveredIndex = 0
    self.lastSoundHoveredIndex = 0

    self:loadSounds()

    self.animTime = 0
    self.hoverWeights = {}
    self.currentPage = 1
    self.maxItemsPerPage = 8
    self.selectionWeights = {} -- Прогресс удержания для каждого сектора
    self.activeMode = "SWITCH"
    self.holdTimeThreshold = 500 -- Время удержания в миллисекундах (0.5 сек)   

    -- Переменные состояний меню и кнопок
    self.actionMenuOpenDown = false
    self.actionSelectDown = false -- Универсальная кнопка выбора (вместо жесткого ЛКМ)
    self.actionSelectHandled = false -- Флаг для защиты от зажатия

    -- Сырые значения 4 направлений
    self.stickRight = 0
    self.stickLeft = 0
    self.stickDown = 0
    self.stickUp = 0

    -- Итоговые склеенные оси
    self.gamepadX = 0
    self.gamepadY = 0

    self.actionEventIds = {}
    self.contextActionIds = nil

end

function RadialVehicleSwitcher:loadSounds()
    self.samples = {}
    local soundDir = self.modDir .. "sounds/"

    local function loadS(name, filename)
        local path = soundDir .. filename
        -- print(string.format("--> [RVS Audio Debug] Пытаемся загрузить: %s по пути: %s", name,
        --     path))

        if fileExists(path) then
            local s = createSample(name)
            loadSample(s, path, false)
            -- print("--> [RVS Audio Debug] УСПЕХ: Звук '" .. name .. "' загружен. ID: " .. tostring(s))
            return s
        else
            -- print("--> [RVS Audio Debug] ОШИБКА: Файл " .. filename .. " НЕ НАЙДЕН!")
            return nil
        end
    end

    self.samples.hover = loadS("rvs_hover", "tick.ogg")
    self.samples.open = loadS("rvs_open", "menu_open.ogg")
    self.samples.close = loadS("rvs_close", "menu_close.ogg")
    self.samples.select = loadS("rvs_select", "select.ogg")
    self.samples.tick = loadS("rvs_tick", "tick.ogg")
    self.samples.confirm = loadS("rvs_confirm", "confirm.ogg")
    self.samples.page = loadS("rvs_page", "page.ogg")
    self.samples.back = loadS("rvs_back", "back.ogg")
end

function RadialVehicleSwitcher:deleteSounds()
    for k, sample in pairs(self.samples) do
        if sample ~= nil then
            delete(sample) -- Исправлено: универсальная функция удаления GIANTS
        end
    end
    self.samples = {}
end

function RadialVehicleSwitcher:deleteMap()
    self:deleteSounds()
end

-- === РЕГИСТРАЦИЯ БАЗОВЫХ КЛАВИШ ===
function RadialVehicleSwitcher:registerActionEvents()
    RadialVehicleSwitcher.actionEventIds = {}

    local tUpM, tDownM, tAlwaysM, sActiveM, cbStateM, disConflictM = true, true, false, true, nil, true
    local successM, idMenu = g_inputBinding:registerActionEvent(InputAction.RVS_OPEN_MENU, RadialVehicleSwitcher,
        RadialVehicleSwitcher.onMenuAction, tUpM, tDownM, tAlwaysM, sActiveM, cbStateM, disConflictM)
    if successM then
        RadialVehicleSwitcher.actionEventIds.openMenu = idMenu
        g_inputBinding:setActionEventTextPriority(idMenu, GS_PRIO_VERY_HIGH)
        g_inputBinding:setActionEventActive(idMenu, true)
        g_inputBinding:setActionEventTextVisibility(idMenu, true)
    end

    local tUpA, tDownA, tAlwaysA, sActiveA, cbStateA, disConflictA = false, true, false, false, nil, true
    g_inputBinding:registerActionEvent(InputAction.RVS_PAGE_LEFT, RadialVehicleSwitcher,
        RadialVehicleSwitcher.onPageLeftAction, tUpA, tDownA, tAlwaysA, sActiveA, cbStateA, disConflictA)
    g_inputBinding:registerActionEvent(InputAction.RVS_PAGE_RIGHT, RadialVehicleSwitcher,
        RadialVehicleSwitcher.onPageRightAction, tUpA, tDownA, tAlwaysA, sActiveA, cbStateA, disConflictA)
    g_inputBinding:registerActionEvent(InputAction.RVS_FAVORITE, RadialVehicleSwitcher,
        RadialVehicleSwitcher.onFavoriteAction, tUpA, tDownA, tAlwaysA, sActiveA, cbStateA, disConflictA)
    g_inputBinding:registerActionEvent(InputAction.RVS_BACK, RadialVehicleSwitcher, RadialVehicleSwitcher.onBackAction,
        tUpA, tDownA, tAlwaysA, sActiveA, cbStateA, disConflictA)
    -- g_inputBinding:registerActionEvent(InputAction.RVS_TOGGLE_MODE, RadialVehicleSwitcher,
    --     RadialVehicleSwitcher.onToggleMode, tUpA, tDownA, tAlwaysA, sActiveA, cbStateA, disConflictA)

    -- РЕГИСТРИРУЕМ УНИВЕРСАЛЬНЫЙ ВЫБОР (Вместо ЛКМ)
    local tUpS, tDownS, tAlwaysS, sActiveS, cbStateS, disConflictS = true, true, false, false, nil, true
    g_inputBinding:registerActionEvent(InputAction.RVS_SELECT, RadialVehicleSwitcher,
        RadialVehicleSwitcher.onSelectAction, tUpS, tDownS, tAlwaysS, sActiveS, cbStateS, disConflictS)
    -- g_inputBinding:registerActionEvent(InputAction.RVS_CYCLE_SEED, RadialVehicleSwitcher, RadialVehicleSwitcher.onCycleSeed, false, true, false, true, nil, true)

    -- РЕГИСТРИРУЕМ 4 НАПРАВЛЕНИЯ СТИКА
    local tUpAx, tDownAx, tAlwaysAx, sActiveAx, cbStateAx, disConflictAx = false, false, true, false, nil, true
    g_inputBinding:registerActionEvent(InputAction.RVS_STICK_RIGHT, RadialVehicleSwitcher,
        RadialVehicleSwitcher.onStickRight, tUpAx, tDownAx, tAlwaysAx, sActiveAx, cbStateAx, disConflictAx)
    g_inputBinding:registerActionEvent(InputAction.RVS_STICK_LEFT, RadialVehicleSwitcher,
        RadialVehicleSwitcher.onStickLeft, tUpAx, tDownAx, tAlwaysAx, sActiveAx, cbStateAx, disConflictAx)
    g_inputBinding:registerActionEvent(InputAction.RVS_STICK_DOWN, RadialVehicleSwitcher,
        RadialVehicleSwitcher.onStickDown, tUpAx, tDownAx, tAlwaysAx, sActiveAx, cbStateAx, disConflictAx)
    g_inputBinding:registerActionEvent(InputAction.RVS_STICK_UP, RadialVehicleSwitcher, RadialVehicleSwitcher.onStickUp,
        tUpAx, tDownAx, tAlwaysAx, sActiveAx, cbStateAx, disConflictAx)
end

-- === БЛОКИРОВКА КАМЕРЫ И ВРЕМЕННЫЕ КНОПКИ ===
function RadialVehicleSwitcher:setMenuContext(isActive)
    if isActive then
        g_inputBinding:setContext("RadialMenu", true, false)
        self.contextActionIds = {}

        local tUp, tDown, tAlways, sActive, cbState, disConflict = true, true, false, true, nil, true
        local s1, id1 = g_inputBinding:registerActionEvent(InputAction.RVS_OPEN_MENU, self, self.onMenuAction, tUp,
            tDown, tAlways, sActive, cbState, disConflict)
        if s1 then
            self.contextActionIds.menu = id1
        end

        local tUpN, tDownN = false, true
        local s2, id2 = g_inputBinding:registerActionEvent(InputAction.RVS_PAGE_LEFT, self, self.onPageLeftAction, tUpN,
            tDownN, tAlways, sActive, cbState, disConflict)
        if s2 then
            self.contextActionIds.pageLeft = id2
        end
        local s3, id3 = g_inputBinding:registerActionEvent(InputAction.RVS_PAGE_RIGHT, self, self.onPageRightAction,
            tUpN, tDownN, tAlways, sActive, cbState, disConflict)
        if s3 then
            self.contextActionIds.pageRight = id3
        end
        local s4, id4 = g_inputBinding:registerActionEvent(InputAction.RVS_FAVORITE, self, self.onFavoriteAction, tUpN,
            tDownN, tAlways, sActive, cbState, disConflict)
        if s4 then
            self.contextActionIds.favorite = id4
        end
        local s5, id5 = g_inputBinding:registerActionEvent(InputAction.RVS_BACK, self, self.onBackAction, tUpN, tDownN,
            tAlways, sActive, cbState, disConflict)
        if s5 then
            self.contextActionIds.back = id5
        end

        local s6, id6 = g_inputBinding:registerActionEvent(InputAction.RVS_SELECT, self, self.onSelectAction, tUp,
            tDown, tAlways, sActive, cbState, disConflict)
        if s6 then
            self.contextActionIds.select = id6
        end

        local tUpAx, tDownAx, tAlwaysAx = false, false, true
        local s7, id7 = g_inputBinding:registerActionEvent(InputAction.RVS_STICK_RIGHT, self, self.onStickRight, tUpAx,
            tDownAx, tAlwaysAx, sActive, cbState, disConflict)
        if s7 then
            self.contextActionIds.stickRight = id7
        end
        local s8, id8 = g_inputBinding:registerActionEvent(InputAction.RVS_STICK_LEFT, self, self.onStickLeft, tUpAx,
            tDownAx, tAlwaysAx, sActive, cbState, disConflict)
        if s8 then
            self.contextActionIds.stickLeft = id8
        end
        local s9, id9 = g_inputBinding:registerActionEvent(InputAction.RVS_STICK_DOWN, self, self.onStickDown, tUpAx,
            tDownAx, tAlwaysAx, sActive, cbState, disConflict)
        if s9 then
            self.contextActionIds.stickDown = id9
        end
        local s10, id10 = g_inputBinding:registerActionEvent(InputAction.RVS_STICK_UP, self, self.onStickUp, tUpAx,
            tDownAx, tAlwaysAx, sActive, cbState, disConflict)
        if s10 then
            self.contextActionIds.stickUp = id10
        end
        local s11, id11 = g_inputBinding:registerActionEvent(InputAction.RVS_TOGGLE_MODE, self, self.onToggleMode,
            false, true, false, true, nil, true)
        if s11 then
            self.contextActionIds.toggleMode = id11
        end
        local s12, id12 = g_inputBinding:registerActionEvent(InputAction.RVS_CYCLE_SEED, self, self.onCycleSeed, tUpN, tDownN, tAlways, sActive, cbState, disConflict)
        if s12 then
            self.contextActionIds.cycleSeed = id12
        end
        self:updateActionHints()
    else
        if self.contextActionIds ~= nil then
            for _, id in pairs(self.contextActionIds) do
                g_inputBinding:removeActionEvent(id)
            end
            self.contextActionIds = nil
        end
        g_inputBinding:revertContext(true)
    end
end

-- === МАТЕМАТИКА СТИКОВ ===
function RadialVehicleSwitcher:onStickRight(actionName, inputValue)
    self.stickRight = inputValue;
    self.gamepadX = self.stickRight - self.stickLeft
end
function RadialVehicleSwitcher:onStickLeft(actionName, inputValue)
    self.stickLeft = inputValue;
    self.gamepadX = self.stickRight - self.stickLeft
end
function RadialVehicleSwitcher:onStickDown(actionName, inputValue)
    self.stickDown = inputValue;
    self.gamepadY = self.stickDown - self.stickUp
end
function RadialVehicleSwitcher:onStickUp(actionName, inputValue)
    self.stickUp = inputValue;
    self.gamepadY = self.stickDown - self.stickUp
end

-- === СТАРЫЕ КОЛЛБЭКИ ===
function RadialVehicleSwitcher:onSelectAction(actionName, inputValue)
    if inputValue ~= 0 then
        self.actionSelectDown = true
    else
        self.actionSelectDown = false
    end
end

function RadialVehicleSwitcher:onMenuAction(actionName, inputValue)

    if inputValue ~= 0 then
        if self.isMenuOpen then
            self:closeMenu()
        else
            self.actionMenuOpenDown = true
        end
    else
        self.actionMenuOpenDown = false
    end
end

function RadialVehicleSwitcher:onPageLeftAction(actionName, inputValue)
    if self.isMenuOpen and self.menuLevel == 2 and self.currentPage > 1 then
        self.currentPage = self.currentPage - 1
        self.animTime = 0
        self.hoveredIndex = 0

        -- ВОТ НАШ ЗВУК (громкость 0.6 обычно оптимальна для перелистывания)
        self:playUISound(self.samples.page, 0.6)
    end
end

function RadialVehicleSwitcher:onPageRightAction(actionName, inputValue)
    if self.isMenuOpen and self.menuLevel == 2 then
        local maxPages = math.max(1, math.ceil(#self.selectedCategoryVehicles / self.maxItemsPerPage))
        if self.currentPage < maxPages then
            self.currentPage = self.currentPage + 1
            self.animTime = 0
            self.hoveredIndex = 0

            -- ВОТ НАШ ЗВУК 
            self:playUISound(self.samples.page, 0.6)
        end
    end
end

function RadialVehicleSwitcher:onFavoriteAction(actionName, inputValue)
    if self.isMenuOpen and self.menuLevel == 2 and self.hoveredIndex > 0 then
        local actualIndex = (self.currentPage - 1) * self.maxItemsPerPage + self.hoveredIndex
        local vInfo = self.selectedCategoryVehicles[actualIndex]
        if vInfo and vInfo.vehicle then
            local vId = self:getVehicleId(vInfo.vehicle)
            if self.favoritesMap[vId] then
                self.favoritesMap[vId] = nil
            else
                self.favoritesMap[vId] = true
            end
            self.currentVehicles = self:scanVehicles()
            if self.currentCategoryIndex == 1 then
                self.selectedCategoryVehicles = self.currentVehicles.FAVORITES
                local maxPages = math.max(1, math.ceil(#self.selectedCategoryVehicles / self.maxItemsPerPage))
                if self.currentPage > maxPages then
                    self.currentPage = maxPages
                end
            end
        end
    end
end

function RadialVehicleSwitcher:onBackAction(actionName, inputValue)
    if self.isMenuOpen then
        if self.menuLevel == 2 then
            self.menuLevel = 1

            self:updateActionHints()

            self.hoveredIndex = 0
            self.animTime = 0
            self.currentVehicles = self:scanVehicles()

            self:playUISound(self.samples.back, 0.6)

        else
            self:closeMenu()
        end
    end
end

-- === ОСНОВНОЙ ЦИКЛ ОБНОВЛЕНИЯ ===
function RadialVehicleSwitcher:update(dt)
    if not self.isLoaded and g_currentMission ~= nil and g_currentMission.missionInfo ~= nil then
        self.isLoaded = true
        if self.loadFavorites ~= nil then
            self:loadFavorites()
        end
    end

    if g_gui ~= nil and g_gui:getIsGuiVisible() then
        if self.isMenuOpen then
            self:closeMenu()
        end
        self.tabHoldTime = 0
        self.actionMenuOpenDown = false
        return
    end

    local isSelectPressed = self.actionSelectDown
    local justClicked = false
    if isSelectPressed then
        if not self.actionSelectHandled then
            self.actionSelectHandled = true
            justClicked = true
        end
    else
        self.actionSelectHandled = false
    end

    if self.actionMenuOpenDown and not self.isMenuOpen then
        self.tabHoldTime = self.tabHoldTime + dt

        if self.tabHoldTime > 300 then
            self.isMenuOpen = true
            RadialVehicleSwitcher.lastFieldData = nil
            self.activeMode = "SWITCH"

            -- ЗВУК ОТКРЫТИЯ
            self:playUISound(self.samples.open, 0.5)

            self.menuLevel = 1
            self.animTime = 0

            local isGamepad = g_inputBinding:getInputHelpMode() == GS_INPUT_HELP_MODE_GAMEPAD
            g_inputBinding:setShowMouseCursor(not isGamepad)

            self:setMenuContext(true)
            self.currentVehicles = self:scanVehicles()
            self:updateCommandCategories()
        end
    elseif not self.actionMenuOpenDown then
        if self.tabHoldTime > 0 then
            if self.tabHoldTime <= 300 and not self.isMenuOpen then
                if g_currentMission.toggleVehicle ~= nil then
                    g_currentMission:toggleVehicle(1)
                else
                    g_currentMission.requestToEnterNextVehicle = true;
                    g_currentMission.requestToEnterNextVehicleDir = 1
                end
            end
            self.tabHoldTime = 0
        end
    end

    if self.isMenuOpen then
        -- === БЛОК ЗАДЕРЖКИ ДЛЯ ВСПЫШКИ ===
        if self.isConfirming then
            self.confirmTimer = self.confirmTimer - dt
            if self.confirmTimer <= 0 then
                self.isConfirming = false
                self:handleSelection(self.confirmedIndex) -- Вызываем настоящее закрытие
            end
            return -- ПРЕРЫВАЕМ UPDATE! Иконка застынет и будет вспыхивать.
        end
        -- =================================

        self.animTime = self.animTime + dt

        -- ЗВУК НАВЕДЕНИЯ (ХОВЕР)
        if self.hoveredIndex ~= nil and self.hoveredIndex ~= self.lastSoundHoveredIndex then
            if self.hoveredIndex > 0 then
                self:playUISound(self.samples.hover, 0.1)
            end
            self.lastSoundHoveredIndex = self.hoveredIndex
        end

        if self.menuLevel == 2 then
            if self.hoveredIndex ~= self.lastHoveredIndex then
                self.itemHoverTime = 0
                self.lastHoveredIndex = self.hoveredIndex
            elseif self.hoveredIndex > 0 then
                self.itemHoverTime = self.itemHoverTime + dt
            end
        else
            self.itemHoverTime = 0
        end

        for i = 1, 20 do
            self.hoverWeights[i] = self.hoverWeights[i] or 0
            self.selectionWeights[i] = self.selectionWeights[i] or 0

            if self.hoveredIndex == i then
                self.hoverWeights[i] = math.min(self.hoverWeights[i] + dt * 0.006, 1)
            else
                self.hoverWeights[i] = math.max(self.hoverWeights[i] - dt * 0.004, 0)
            end

            if self.menuLevel == 1 then
                if justClicked and self.hoveredIndex == i then
                    self:handleSelection(i)
                end
                self.selectionWeights[i] = 0
            else
                if self.hoveredIndex == i and self.actionSelectDown then
                    -- Запоминаем вес до прибавления времени
                    local oldWeight = self.selectionWeights[i]

                    self.selectionWeights[i] = math.min(self.selectionWeights[i] + dt / self.holdTimeThreshold, 1.0)

                    -- Запоминаем новый вес
                    local newWeight = self.selectionWeights[i]

                    -- === ЛОГИКА УСКОРЯЮЩЕЙСЯ ТРЕЩОТКИ ===
                    if newWeight > 0 and newWeight < 1.0 then
                        -- Возводим линейный прогресс в квадрат (степень 2).
                        -- Чем выше степень (например, 2.5 или 3), тем сильнее контраст скорости!
                        local oldCurve = math.pow(oldWeight, 2)
                        local newCurve = math.pow(newWeight, 2)

                        -- Шаг 0.1 означает, что всего будет около 10 щелчков
                        local tickStep = 0.1

                        -- Проверяем, пересекли ли мы очередную границу на нашей искривленной шкале
                        if math.floor(newCurve / tickStep) > math.floor(oldCurve / tickStep) then
                            self:playUISound(self.samples.tick, 0.4)
                        end
                    end
                    -- =====================================

                    if self.selectionWeights[i] >= 1.0 then
                        -- НАЧИНАЕМ ВСПЫШКУ ВМЕСТО ЗАКРЫТИЯ
                        if not self.isConfirming then
                            self.isConfirming = true
                            self.confirmTimer = 150 -- 150 мс чистого кайфа
                            self.confirmedIndex = i
                            self:playUISound(self.samples.confirm, 1.0) -- Звук играем ПРЯМО ЗДЕСЬ!
                        end
                    end
                else
                    local dropSpeed = (self.hoveredIndex == i) and (dt / 200) or (dt / 100)
                    self.selectionWeights[i] = math.max(self.selectionWeights[i] - dropSpeed, 0)
                end
            end
        end
    end
end

function RadialVehicleSwitcher:handleSelection(index)

    -- Убрали отсюда общий звук! Теперь он внутри условий:

    if self.menuLevel == 1 then
        self:playUISound(self.samples.select, 0.4)

        local catList = nil

        -- НОВОЕ: Выбираем источник техники в зависимости от режима
        if self.activeMode == "COMMAND" then
            local taskCategory = self.commandCategories[index]
            if taskCategory and taskCategory.isAvailable then
                catList = taskCategory.vehicles
                self.selectedCategoryId = taskCategory.id
            end
        else
            catList = self:getCategoryByIndex(index)
        end

        if catList then
            self.selectedCategoryVehicles = catList
            self.menuLevel = 2

            self:updateActionHints()

            self.hoveredIndex = 0
            self.currentPage = 1
            self.animTime = 0
            for i = 1, 20 do
                self.selectionWeights[i] = 0
            end
        else
            -- Если категория недоступна (серая), играем звук ошибки и не пускаем дальше
            self:playUISound(self.samples.back, 0.5)
        end

    elseif self.menuLevel == 2 then
        
        -- 2. ВЫБОР САМОЙ ТЕХНИКИ
        local actualIndex = (self.currentPage - 1) * self.maxItemsPerPage + index
        local selectedVehicleInfo = self.selectedCategoryVehicles[actualIndex]
        local targetVehicle = nil

        if selectedVehicleInfo and selectedVehicleInfo.vehicle then
            targetVehicle = selectedVehicleInfo.vehicle
        end

        self:closeMenu()

        if targetVehicle ~= nil then
            -- === РАЗДЕЛЯЕМ ЛОГИКУ В ЗАВИСИМОСТИ ОТ РЕЖИМА ===
            if self.activeMode == "COMMAND" then
                -- РЕЖИМ ПРИКАЗОВ ИИ (Вызываем функцию из нашего нового файла)
                self:giveCommandToVehicle(targetVehicle, "TEST_START")
            else
                -- ОБЫЧНЫЙ РЕЖИМ: САДИМСЯ В ТЕХНИКУ
                if g_localPlayer ~= nil and g_localPlayer.requestToEnterVehicle ~= nil then
                    g_localPlayer:requestToEnterVehicle(targetVehicle)
                elseif g_currentMission.vehicleSystem ~= nil and g_currentMission.vehicleSystem.requestToEnterVehicle ~=
                    nil then
                    g_currentMission.vehicleSystem:requestToEnterVehicle(targetVehicle)
                end
            end
        end
    end
end

function RadialVehicleSwitcher:closeMenu()

    if self.isMenuOpen then
        self:playUISound(self.samples.close, 0.4)
    end

    self.isMenuOpen = false
    self.menuLevel = 1

    self.itemHoverTime = 0
    self.lastHoveredIndex = 0
    self.lastSoundHoveredIndex = 0

    g_inputBinding:setShowMouseCursor(false)

    self.tabHoldTime = 0
    self.actionMenuOpenDown = false
    self.actionSelectDown = false
    self.actionSelectHandled = false

    self:setMenuContext(false)
end

function RadialVehicleSwitcher:onToggleMode(actionName, inputValue)
    if not self.isMenuOpen then return end

    if self.menuLevel == 1 then
        -- МЫ НА ПЕРВОМ УРОВНЕ: Стандартная логика переключения вкладок
        if self.activeMode == "SWITCH" then
            self.activeMode = "COMMAND"
            self:updateCommandCategories()
        else
            self.activeMode = "SWITCH"
        end

        self:updateActionHints()

        -- Сбрасываем анимации, чтобы UI красиво перерисовался с нуля
        self.hoveredIndex = 0
        self.animTime = 0
        for i = 1, 20 do
            self.selectionWeights[i] = 0
            self.hoverWeights[i] = 0
        end

        -- Играем звук перелистывания страницы
        self:playUISound(self.samples.page, 0.7)

    elseif self.menuLevel == 2 then
        -- МЫ НА ВТОРОМ УРОВНЕ!
        -- Если мы зашли сюда по нажатию с геймпада, значит движок "съел" сигнал
        -- от RVS_CYCLE_SEED. Поэтому мы вызываем смену семян вручную!
        if self.activeMode == "COMMAND" and self.selectedCategoryId == "SOW" then
            if self.onCycleSeed then
                self:onCycleSeed()
            end
        end
    end
end

function RadialVehicleSwitcher:updateActionHints()
    if self.contextActionIds == nil then return end
 
    local isLevel1 = self.menuLevel == 1
    local isLevel2 = self.menuLevel == 2
    local isCommand = self.activeMode == "COMMAND"
    local isSow = isLevel2 and isCommand and self.selectedCategoryId == "SOW"
 
    -- ВИЗУАЛ: Показываем или прячем текст в меню F1 в зависимости от уровня
    g_inputBinding:setActionEventTextVisibility(self.contextActionIds.menu,       true)
    g_inputBinding:setActionEventTextVisibility(self.contextActionIds.toggleMode, isLevel1)
    g_inputBinding:setActionEventTextVisibility(self.contextActionIds.back,       isLevel2)
    g_inputBinding:setActionEventTextVisibility(self.contextActionIds.favorite,   isLevel2 and not isCommand)
    g_inputBinding:setActionEventTextVisibility(self.contextActionIds.select,     isLevel2)
    g_inputBinding:setActionEventTextVisibility(self.contextActionIds.pageLeft,   isLevel2)
    g_inputBinding:setActionEventTextVisibility(self.contextActionIds.pageRight,  isLevel2)
    if self.contextActionIds.cycleSeed ~= nil then
        g_inputBinding:setActionEventTextVisibility(self.contextActionIds.cycleSeed, isSow)
    end
 
    -- ЛОГИКА: ОБЕ КНОПКИ ВСЕГДА АКТИВНЫ (true)! 
    -- Это предотвратит конфликт биндов на одном стике/кнопке.
    g_inputBinding:setActionEventActive(self.contextActionIds.toggleMode, true)
    if self.contextActionIds.cycleSeed ~= nil then
        g_inputBinding:setActionEventActive(self.contextActionIds.cycleSeed, true)
    end
end

addModEventListener(RadialVehicleSwitcher)
