using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using CtrEditor.ObjetosSim; using CtrEditor.ObjetosSim.Extraccion_Datos; using System.Collections.ObjectModel; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Linq; namespace CtrEditor.PopUps { public class MatrixItem : ObservableObject { public string TagName { get; set; } private string columnName; public string ColumnName { get => columnName; set => SetProperty(ref columnName, value); } private int columnNumber; public int ColumnNumber { get => columnNumber; set => SetProperty(ref columnNumber, value); } public string Value { get; set; } public string Type { get; set; } public bool IsCloned { get; set; } public osBase SourceObject { get; set; } } public partial class MatrixPreviewViewModel : ObservableObject { private Window _window; private MainViewModel _mainViewModel; private DataGrid _dataGrid; [ObservableProperty] private ObservableCollection matrixItems; [ObservableProperty] private ObservableCollection> matrixRows; [ObservableProperty] private GridLength detailsHeight = new GridLength(150); [ObservableProperty] private double detailsHeightValue = 150; partial void OnDetailsHeightValueChanged(double value) { DetailsHeight = new GridLength(value); } public void Initialize(MainViewModel mainViewModel, Window window) { _mainViewModel = mainViewModel; _window = window; _dataGrid = (_window as MatrixPreviewWindow)?.MatrixPreview; MatrixItems = new ObservableCollection(); MatrixRows = new ObservableCollection>(); AnalyzeMatrix(); } private void UpdateMatrixPreview() { if (_dataGrid == null) return; if (MatrixRows == null) MatrixRows = new ObservableCollection>(); MatrixRows.Clear(); _dataGrid.Columns.Clear(); if (!MatrixItems.Any()) return; // Ordenar items por número de columna var orderedItems = MatrixItems .GroupBy(x => x.ColumnNumber) .OrderBy(g => g.Key) .Select(g => g.First()) .ToList(); // Crear columnas foreach (var item in orderedItems) { var column = new DataGridTextColumn { Header = $"{item.ColumnNumber}:{item.ColumnName}", Binding = new Binding($"[{item.ColumnNumber}]"), Width = DataGridLength.Auto }; _dataGrid.Columns.Add(column); } // Calcular número de filas necesarias int maxRows = 1; var clonedItems = MatrixItems.Where(x => x.IsCloned).ToList(); if (clonedItems.Any()) { maxRows = clonedItems.Max(x => x.SourceObject is osExtraccionTag tag ? tag.Copy_Number : 0) + 1; } // Crear filas con valores for (int row = 0; row < maxRows; row++) { var rowData = new Dictionary(); // Agregar valores fijos (no clonados) en todas las filas foreach (var item in MatrixItems.Where(x => !x.IsCloned)) { if (item.ColumnNumber > 0) { rowData[item.ColumnNumber.ToString()] = item.Value ?? string.Empty; } } // Agregar valores clonados solo en su fila correspondiente foreach (var item in MatrixItems.Where(x => x.IsCloned)) { if (item.ColumnNumber > 0 && item.SourceObject is osExtraccionTag tag && tag.Copy_Number == row) { rowData[item.ColumnNumber.ToString()] = item.Value ?? string.Empty; } } MatrixRows.Add(rowData); } } private void UpdateColumnHeaders() { if (_dataGrid == null) return; foreach (var col in _dataGrid.Columns.Cast()) { if (col is DataGridTextColumn textCol) { var item = MatrixItems.FirstOrDefault(x => x.ColumnName == (textCol.Header?.ToString() ?? "").Split(':').Last()); if (item != null) { textCol.Header = $"{item.ColumnNumber}:{item.ColumnName}"; } } } } private void AnalyzeMatrix() { var osBuscarCoincidencias_List = _mainViewModel.ObjetosSimulables .OfType() .Where(tag => tag.Show_On_This_Page) .ToList(); var osExtraccionTagBaseGrouped_List = _mainViewModel.ObjetosSimulables .OfType() .Where(tag => tag.Show_On_This_Page && !tag.Cloned && tag.Id_Search_Templates != null && tag.Id_Search_Templates != "") .ToList(); var osExtraccionTagBaseFix_List = _mainViewModel.ObjetosSimulables .OfType() .Where(tag => tag.Show_On_This_Page && !tag.Cloned && (tag.Id_Search_Templates == null || tag.Id_Search_Templates == "")) .ToList(); var osExtraccionTagCloned_List = _mainViewModel.ObjetosSimulables .OfType() .Where(tag => tag.Show_On_This_Page && tag.Cloned) .ToList(); // Add fixed tags foreach (var tag in osExtraccionTagBaseFix_List) { tag.CaptureImageAreaAndDoOCR(); MatrixItems.Add(new MatrixItem { TagName = tag.Nombre, ColumnName = tag.Collumn_name, ColumnNumber = tag.Collumn_number, Value = tag.Tag_extract, Type = "Fixed", IsCloned = false, SourceObject = tag }); } // Add grouped tags foreach (var tag in osExtraccionTagBaseGrouped_List) { tag.CaptureImageAreaAndDoOCR(); MatrixItems.Add(new MatrixItem { TagName = tag.Nombre, ColumnName = tag.Collumn_name, ColumnNumber = tag.Collumn_number, Value = tag.Tag_extract, Type = $"Grouped ({tag.Id_Search_Templates})", IsCloned = false, SourceObject = tag }); } // Add cloned tags foreach (var tag in osExtraccionTagCloned_List) { tag.CaptureImageAreaAndDoOCR(); MatrixItems.Add(new MatrixItem { TagName = tag.Nombre, ColumnName = tag.Collumn_name, ColumnNumber = tag.Collumn_number, Value = tag.Tag_extract, Type = "Cloned", IsCloned = true, SourceObject = tag }); } // Ordenar los items por número de columna var items = MatrixItems.OrderBy(x => x.ColumnNumber).ToList(); MatrixItems.Clear(); foreach (var item in items) { MatrixItems.Add(item); } ResolveColumnConflicts(); // Analizar y resolver conflictos al cargar UpdateMatrixPreview(); } partial void OnMatrixItemsChanged(ObservableCollection value) { if (value != null) { foreach (var item in value) { item.PropertyChanged += (s, e) => { if (e.PropertyName == nameof(MatrixItem.ColumnNumber) || e.PropertyName == nameof(MatrixItem.ColumnName)) { UpdateColumnHeaders(); } }; } } UpdateMatrixPreview(); } [RelayCommand] private void ApplyChanges() { // Resolver solo los conflictos reales, mantener el orden existente var conflicts = MatrixItems .GroupBy(x => x.ColumnNumber) .Where(g => g.Select(x => x.ColumnName).Distinct().Count() > 1) .Any(); if (conflicts) { ResolveColumnConflicts(); } // Validar números de columna var columnNumbers = MatrixItems.Select(x => x.ColumnNumber).OrderBy(x => x).ToList(); for (int i = 0; i < columnNumbers.Count; i++) { if (columnNumbers[i] <= 0) { MessageBox.Show("Column numbers must be greater than 0", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } } // Aplicar cambios a los objetos foreach (var item in MatrixItems) { if (item.SourceObject is osExtraccionTag tag) { tag.Collumn_name = item.ColumnName; tag.Collumn_number = item.ColumnNumber; } } _mainViewModel.HasUnsavedChanges = true; _window.Close(); } [RelayCommand] private void Close() { _window.Close(); } [RelayCommand] private void RegenerateMatrix() { ResolveColumnConflicts(); UpdateMatrixPreview(); } private void ResolveColumnConflicts() { // Paso 1: Mantener el orden actual y resolver solo los conflictos reales var columnGroups = MatrixItems .GroupBy(x => x.ColumnNumber) .Where(g => g.Select(x => x.ColumnName).Distinct().Count() > 1) .ToList(); foreach (var group in columnGroups) { var nameGroups = group .GroupBy(x => x.ColumnName) .OrderByDescending(g => g.Count()) .ToList(); // El grupo más grande mantiene su número var largestGroup = nameGroups.First(); // Solo reasignar números para grupos que tengan conflicto for (int i = 1; i < nameGroups.Count; i++) { var newColumnNumber = GetNextAvailableColumnNumber(); foreach (var item in nameGroups[i]) { item.ColumnNumber = newColumnNumber; } } } // Paso 2: Asegurarse de que los números son consecutivos sin alterar el orden relativo var orderedItems = MatrixItems .OrderBy(x => x.ColumnNumber) .GroupBy(x => x.ColumnName) .ToList(); int currentNumber = 1; foreach (var group in orderedItems) { foreach (var item in group) { item.ColumnNumber = currentNumber; } currentNumber++; } } private int GetNextAvailableColumnNumber() { var usedNumbers = MatrixItems.Select(x => x.ColumnNumber).Distinct().OrderBy(x => x).ToList(); int nextNumber = 1; foreach (var number in usedNumbers) { if (number > nextNumber) return nextNumber; nextNumber = number + 1; } return nextNumber; } } }