S7Explorer/Helpers/SearchHelper.cs

143 lines
5.0 KiB
C#

using S7Explorer.Models;
using S7Explorer.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
namespace S7Explorer.Helpers
{
public class SearchHelper
{
private readonly LogService _logService;
public SearchHelper()
{
_logService = LogService.Instance;
}
public List<SearchResult> Search(ProjectStructure project, string searchText, bool caseSensitive, bool useRegex)
{
_logService.LogInfo($"Searching for '{searchText}' (Case sensitive: {caseSensitive}, Regex: {useRegex})");
List<SearchResult> results = new List<SearchResult>();
try
{
if (string.IsNullOrWhiteSpace(searchText))
return results;
// Prepare regex if needed
Regex? regex = null;
if (useRegex)
{
try
{
RegexOptions options = caseSensitive ? RegexOptions.None : RegexOptions.IgnoreCase;
regex = new Regex(searchText, options);
}
catch (Exception ex)
{
_logService.LogError($"Invalid regex pattern: {ex.Message}");
return results;
}
}
// Search blocks
SearchProjectItem(project.BlocksFolder, results, searchText, caseSensitive, regex);
// Search symbols
SearchProjectItem(project.SymbolsFolder, results, searchText, caseSensitive, regex);
// Search hardware
SearchProjectItem(project.HardwareFolder, results, searchText, caseSensitive, regex);
_logService.LogInfo($"Found {results.Count} results");
return results;
}
catch (Exception ex)
{
_logService.LogError($"Error during search: {ex.Message}");
return results;
}
}
private void SearchProjectItem(ProjectItem item, List<SearchResult> results, string searchText,
bool caseSensitive, Regex? regex)
{
// Check name
bool nameMatch = MatchesSearch(item.Name, searchText, caseSensitive, regex);
// For blocks, check content and comments
bool contentMatch = false;
if (item is BlockItem blockItem)
{
contentMatch = MatchesSearch(blockItem.BlockContent, searchText, caseSensitive, regex) ||
MatchesSearch(blockItem.BlockComment, searchText, caseSensitive, regex);
}
// For symbols, check address, type, and comment
else if (item is SymbolItem symbolItem)
{
contentMatch = MatchesSearch(symbolItem.SymbolAddress, searchText, caseSensitive, regex) ||
MatchesSearch(symbolItem.SymbolDataType, searchText, caseSensitive, regex) ||
MatchesSearch(symbolItem.SymbolComment, searchText, caseSensitive, regex);
}
// For hardware, check module info
else if (item is HardwareItem hardwareItem)
{
contentMatch = MatchesSearch(hardwareItem.ModuleType, searchText, caseSensitive, regex) ||
MatchesSearch(hardwareItem.OrderNumber, searchText, caseSensitive, regex) ||
MatchesSearch(hardwareItem.Position, searchText, caseSensitive, regex) ||
MatchesSearch(hardwareItem.Address, searchText, caseSensitive, regex);
}
if (nameMatch || contentMatch)
{
results.Add(new SearchResult
{
Item = item,
MatchType = nameMatch ? (contentMatch ? MatchType.Both : MatchType.Name) : MatchType.Content
});
}
// Search children recursively
foreach (var child in item.Children)
{
SearchProjectItem(child, results, searchText, caseSensitive, regex);
}
}
private bool MatchesSearch(string text, string searchText, bool caseSensitive, Regex? regex)
{
if (string.IsNullOrEmpty(text))
return false;
if (regex != null)
return regex.IsMatch(text);
return caseSensitive
? text.Contains(searchText)
: text.ToLower().Contains(searchText.ToLower());
}
}
public class SearchResult
{
public ProjectItem Item { get; set; } = null!;
public MatchType MatchType { get; set; }
public override string ToString()
{
return $"{Item.Name} - {MatchType}";
}
}
public enum MatchType
{
Name,
Content,
Both
}
}