using CounterStrikeSharp.API.Core; using CounterStrikeSharp.API.Core.Translations; using Microsoft.Extensions.Localization; namespace CS2_SimpleAdmin.Menus; public class MenuBuilder { private readonly string _title; private readonly CCSPlayerController? _player; private readonly IStringLocalizer? _localizer; private readonly List _options = []; private MenuBuilder? _parentMenu; private Action? _backAction; private Action? _resetAction; /// /// Constructor for player-localized menu with translation key /// public MenuBuilder(string titleKey, CCSPlayerController player, IStringLocalizer? localizer = null) { _title = titleKey; _player = player; _localizer = localizer ?? CS2_SimpleAdmin._localizer; } /// /// Constructor for static title (backward compatibility) /// public MenuBuilder(string title) { _title = title; _player = null; _localizer = null; } /// /// Gets the localized title for the player /// private string GetLocalizedTitle() { if (_player != null && _localizer != null) { using (new WithTemporaryCulture(_player.GetLanguage())) { return _localizer[_title]; } } return _title; } /// /// Adds a menu option with an action. /// /// Display name or translation key /// Action to perform when selected /// Whether the option is disabled /// Required permission /// If true, name is a translation key to be localized public MenuBuilder AddOption(string name, Action action, bool disabled = false, string? permission = null, bool isTranslationKey = false) { _options.Add(new MenuOption { Name = name, Action = action, Disabled = disabled, Permission = permission, IsTranslationKey = isTranslationKey }); return this; } /// /// Gets the localized name for a menu option /// private string GetLocalizedOptionName(MenuOption option) { if (option.IsTranslationKey && _player != null && _localizer != null) { using (new WithTemporaryCulture(_player.GetLanguage())) { return _localizer[option.Name]; } } return option.Name; } /// /// Adds a menu option that opens a submenu. /// public MenuBuilder AddSubMenu(string name, Func subMenuFactory, bool disabled = false, string? permission = null) { _options.Add(new MenuOption { Name = name, Action = player => { var subMenu = subMenuFactory(); subMenu.SetParent(this); // Automatically add back button to submenu subMenu.WithBackButton(); subMenu.OpenMenu(player); }, Disabled = disabled, Permission = permission }); return this; } /// /// Adds a menu option that opens a submenu (with player parameter in factory). /// public MenuBuilder AddSubMenu(string name, Func subMenuFactory, bool disabled = false, string? permission = null) { _options.Add(new MenuOption { Name = name, Action = player => { var subMenu = subMenuFactory(player); subMenu.SetParent(this); // Automatically add back button to submenu subMenu.WithBackButton(); subMenu.OpenMenu(player); }, Disabled = disabled, Permission = permission }); return this; } /// /// Adds a back button to return to the previous menu. /// public MenuBuilder WithBackButton() { if (_parentMenu != null) { _backAction = player => _parentMenu.OpenMenu(player); // Add back option at the end of menu // AddOption(backButtonText, _backAction); } return this; } /// /// Sets the parent menu (for navigation). /// private void SetParent(MenuBuilder parent) { _parentMenu = parent; _backAction = player => _parentMenu.OpenMenu(player); } /// /// Opens the menu for a player. /// /// The player to open the menu for. public void OpenMenu(CCSPlayerController player) { if (!player.IsValid) return; // Get localized title var localizedTitle = GetLocalizedTitle(); // Use MenuManager dependency var menu = Helper.CreateMenu(localizedTitle, _backAction); if (menu == null) return; foreach (var option in _options) { // Check permissions if required if (!string.IsNullOrEmpty(option.Permission)) { var steamId = new CounterStrikeSharp.API.Modules.Entities.SteamID(player.SteamID); if (!CounterStrikeSharp.API.Modules.Admin.AdminManager.PlayerHasPermissions(steamId, option.Permission)) { continue; // Skip option if player doesn't have permission } } // Get localized option name var localizedName = GetLocalizedOptionName(option); menu.AddMenuOption(localizedName, (menuPlayer, menuOption) => { option.Action?.Invoke(menuPlayer); }, option.Disabled); } menu.Open(player); } /// /// Clears all menu options. /// /// This MenuBuilder instance for chaining. public MenuBuilder Clear() { _options.Clear(); return this; } /// /// Sets a reset action for the menu. /// /// The action to execute on reset. /// This MenuBuilder instance for chaining. public MenuBuilder WithResetAction(Action resetAction) { _resetAction = resetAction; return this; } /// /// Sets a custom back action for the menu. /// /// The action to execute when going back (nullable). /// This MenuBuilder instance for chaining. public MenuBuilder WithBackAction(Action? backAction) { _backAction = backAction; return this; } } /// /// Represents an option within a menu. /// public class MenuOption { public string Name { get; set; } = string.Empty; public Action? Action { get; set; } public bool Disabled { get; set; } public string? Permission { get; set; } public bool IsTranslationKey { get; set; } }