using System.Text.RegularExpressions; using Model.Glossary; namespace Services.Website; public class GlossaryService : IGlossaryService { private List? _sortedTerms; private Dictionary? _terms; public GlossaryTermModel? GetTerm(string id) { var terms = GetAllTermsDict(); return terms.TryGetValue(id, out var term) ? term : null; } public List SearchTerms(string query) { var q = query.ToLowerInvariant(); return GetAllTerms().Where(t => t.Term.Contains(q, StringComparison.OrdinalIgnoreCase) || t.ShortDefinition.Contains(q, StringComparison.OrdinalIgnoreCase) || t.Category.Contains(q, StringComparison.OrdinalIgnoreCase)).ToList(); } public List GetTermsByCategory(string category) { return GetAllTerms().Where(t => t.Category.Equals(category, StringComparison.OrdinalIgnoreCase)).ToList(); } public List GetAllTerms() { return GetAllTermsDict().Values.ToList(); } public List GetCategories() { return GetAllTerms().Select(t => t.Category).Distinct().ToList(); } public string LinkifyText(string text) { if (string.IsNullOrEmpty(text)) return text; var sorted = GetSortedTerms(); foreach (var term in sorted) { var pattern = $@"\b{Regex.Escape(term)}\b"; text = Regex.Replace(text, pattern, match => { var termData = GetTermByName(term); if (termData == null) return match.Value; return $"{match.Value}"; }); } return text; } public void Subscribe(Action action) { OnChange += action; } public void Unsubscribe(Action action) { OnChange += action; } private event Action OnChange = null!; private void NotifyDataChanged() { OnChange?.Invoke(); } private Dictionary GetAllTermsDict() { _terms ??= GlossaryData.GetTerms(); return _terms; } private List GetSortedTerms() { if (_sortedTerms != null) return _sortedTerms; _sortedTerms = GetAllTerms() .Select(t => t.Term) .OrderByDescending(t => t.Length) .ToList(); return _sortedTerms; } private GlossaryTermModel? GetTermByName(string name) { return GetAllTerms().FirstOrDefault(t => t.Term.Equals(name, StringComparison.OrdinalIgnoreCase)); } }