using System; using System.Collections.Generic; using System.Linq; using System.Numerics; using Dalamud.Bindings.ImGui; using Dalamud.Interface.Utility.Raii; using Questionable.Controller; using Questionable.Model; using Questionable.Model.Questing; namespace Questionable.Windows.Utils; internal sealed class QuestSelector(QuestRegistry questRegistry) { private string _searchString = string.Empty; private bool _comboJustOpened; public Predicate? SuggestionPredicate { private get; set; } public Predicate? DefaultPredicate { private get; set; } public Action? QuestSelected { private get; set; } public void DrawSelection() { if (QuestSelected == null) { throw new InvalidOperationException("QuestSelected action must be set before drawing the quest selector."); } ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X); if (ImGui.BeginCombo("##QuestSelection", "Add Quest...", ImGuiComboFlags.HeightLarge)) { if (!_comboJustOpened) { ImGui.SetKeyboardFocusHere(); _comboJustOpened = true; } ImGui.SetNextItemWidth(-1f); bool flag = ImGui.InputTextWithHint("##QuestSearch", "Search quests...", ref _searchString, 256, ImGuiInputTextFlags.AutoSelectAll | ImGuiInputTextFlags.EnterReturnsTrue); ImGui.Separator(); IEnumerable enumerable; if (!string.IsNullOrEmpty(_searchString)) { enumerable = Enumerable.Where(predicate: (!ElementId.TryFromString(_searchString, out ElementId elementId)) ? new Func(SearchPredicate) : ((Func)((Quest x) => SearchPredicate(x) || x.Id == elementId)), source: questRegistry.AllQuests.Where(delegate(Quest x) { ElementId id = x.Id; return !(id is SatisfactionSupplyNpcId) && !(id is AlliedSocietyDailyId); })); } else { enumerable = questRegistry.AllQuests.Where((Quest x) => DefaultPredicate?.Invoke(x) ?? true); } using (ImRaii.IEndObject endObject = ImRaii.Child("##QuestScrollArea", new Vector2(0f, 300f), border: false)) { if (endObject) { foreach (Quest item in enumerable) { if ((SuggestionPredicate == null || SuggestionPredicate(item)) && (ImGui.Selectable(item.Info.Name) || flag)) { QuestSelected(item); _searchString = string.Empty; if (flag) { ImGui.CloseCurrentPopup(); flag = false; } } } } } ImGui.EndCombo(); } else { _comboJustOpened = false; } ImGui.Spacing(); bool SearchPredicate(Quest x) { return x.Info.Name.Contains(_searchString, StringComparison.CurrentCultureIgnoreCase); } } }