using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using DirectoryCreator.Models; using DirectoryCreator.ViewModels; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Text.Json; using System.Windows; namespace DirectoryCreator { /// /// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); DataContext = new MainWindowViewModel(); } } } namespace DirectoryCreator.ViewModels { public partial class MainWindowViewModel : ObservableObject { private readonly string configDirectory = "Configurations"; private FolderConfig currentConfig; [ObservableProperty] private string lastProjectNumber; [ObservableProperty] private string newProjectName; [ObservableProperty] private string basePath; [ObservableProperty] private ObservableCollection availableConfigurations; [ObservableProperty] private FolderConfig selectedConfiguration; public MainWindowViewModel() { IsDarkTheme = Properties.Settings.Default.IsDarkTheme; ThemeManager.SetTheme(IsDarkTheme); AvailableConfigurations = new ObservableCollection(); LoadConfigurations(); } private void LoadConfigurations() { try { // Asegurar que existe el directorio de configuraciones if (!Directory.Exists(configDirectory)) { Directory.CreateDirectory(configDirectory); // Si no existe, mover el archivo de configuración por defecto if (File.Exists("folderConfig.json")) { File.Move("folderConfig.json", Path.Combine(configDirectory, "default.json")); } } // Cargar todas las configuraciones var jsonFiles = Directory.GetFiles(configDirectory, "*.json"); if (jsonFiles.Length == 0) { MessageBox.Show("No se encontraron archivos de configuración.", "Advertencia", MessageBoxButton.OK, MessageBoxImage.Warning); return; } var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true, AllowTrailingCommas = true }; AvailableConfigurations.Clear(); foreach (var jsonFile in jsonFiles) { var jsonString = File.ReadAllText(jsonFile); var config = JsonSerializer.Deserialize(jsonString, options); if (config != null) { // Si no tiene descripción, usar el nombre del archivo if (string.IsNullOrEmpty(config.Description)) { config.Description = Path.GetFileNameWithoutExtension(jsonFile); } AvailableConfigurations.Add(config); } } // Seleccionar la primera configuración por defecto if (AvailableConfigurations.Count > 0) { SelectedConfiguration = AvailableConfigurations[0]; } } catch (Exception ex) { MessageBox.Show($"Error al cargar las configuraciones: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); } } [RelayCommand] private void OpenBaseFolder() { try { if (Directory.Exists(BasePath)) { Process.Start("explorer.exe", BasePath); } else { MessageBox.Show($"La carpeta base no existe: {BasePath}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); } } catch (Exception ex) { MessageBox.Show($"Error al abrir la carpeta base: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); } } private void LoadLastProjectNumber() { try { if (string.IsNullOrEmpty(BasePath) || !Directory.Exists(BasePath)) { NewProjectName = "001 - "; return; } var directories = Directory.GetDirectories(BasePath) .Select(d => new DirectoryInfo(d).Name) .ToList(); var regex = new System.Text.RegularExpressions.Regex(@"^(\d{1,3})\s-\s"); var projectNumbers = new HashSet(); foreach (var dirName in directories) { var match = regex.Match(dirName); if (match.Success && int.TryParse(match.Groups[1].Value, out int number)) { projectNumbers.Add(number); } } var sortedNumbers = projectNumbers.OrderByDescending(n => n).ToList(); int lastValidNumber = -1; string lastProject = ""; foreach (int number in sortedNumbers) { if (projectNumbers.Contains(number - 1) && projectNumbers.Contains(number - 2)) { lastValidNumber = number; lastProject = directories.First(d => regex.Match(d).Success && int.Parse(regex.Match(d).Groups[1].Value) == number); break; } } LastProjectNumber = lastProject; NewProjectName = lastValidNumber >= 0 ? $"{(lastValidNumber + 1):00} - " : "01 - "; if (lastValidNumber < 0) { MessageBox.Show("No se encontró una secuencia válida de al menos 3 números consecutivos.\nSe iniciará desde 01.", "Información", MessageBoxButton.OK, MessageBoxImage.Information); } } catch (Exception ex) { MessageBox.Show($"Error al cargar el último proyecto: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); NewProjectName = "001 - "; } } [RelayCommand] private void EditConfigurations() { var window = new ConfigEditorWindow { Owner = System.Windows.Application.Current.MainWindow }; if (SelectedConfiguration != null) { var configPath = Directory.GetFiles(configDirectory, "*.json") .FirstOrDefault(f => { var config = JsonSerializer.Deserialize( File.ReadAllText(f), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); return config?.Description == SelectedConfiguration.Description; }); window.DataContext = new ConfigEditorViewModel(window, SelectedConfiguration, configPath); } else { window.DataContext = new ConfigEditorViewModel(window); } if (window.ShowDialog() == true) { LoadConfigurations(); } } [ObservableProperty] private bool isDarkTheme; partial void OnIsDarkThemeChanged(bool value) { ThemeManager.SetTheme(value); // Opcional: Guardar la preferencia del usuario Properties.Settings.Default.IsDarkTheme = value; Properties.Settings.Default.Save(); } [ObservableProperty] private ObservableCollection existingProjects = new(); [ObservableProperty] private string selectedProject; private void LoadExistingProjects() { try { if (string.IsNullOrEmpty(BasePath) || !Directory.Exists(BasePath)) { ExistingProjects = new ObservableCollection(); return; } var directories = Directory.GetDirectories(BasePath) .Select(d => new DirectoryInfo(d).Name) .OrderByDescending(name => name) .ToList(); ExistingProjects = new ObservableCollection(directories); // Seleccionar el LastProjectNumber si existe if (ExistingProjects.Count > 0) { if (!string.IsNullOrEmpty(LastProjectNumber) && ExistingProjects.Contains(LastProjectNumber)) { SelectedProject = LastProjectNumber; } else { SelectedProject = ExistingProjects[0]; } } } catch (Exception ex) { MessageBox.Show($"Error al cargar proyectos existentes: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); ExistingProjects = new ObservableCollection(); } } partial void OnSelectedConfigurationChanged(FolderConfig value) { if (value != null) { currentConfig = value; BasePath = value.BasePath; LoadLastProjectNumber(); LoadExistingProjects(); // Cargar proyectos existentes cuando cambia la configuración } } [RelayCommand] private async Task RenameProject() { if (string.IsNullOrEmpty(SelectedProject)) { MessageBox.Show("Por favor seleccione un proyecto para renombrar", "Advertencia", MessageBoxButton.OK, MessageBoxImage.Warning); return; } var result = Microsoft.Windows.Controls.InputDialog.Show( "Renombrar Proyecto", "Ingrese el nuevo nombre del proyecto:", SelectedProject); if (result.IsOk) { string newName = result.Result; if (string.IsNullOrWhiteSpace(newName)) { MessageBox.Show("El nombre no puede estar vacío", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } try { foreach (var structure in currentConfig.FolderStructures) { var basePath = structure.BasePath.Replace("{year}", DateTime.Now.Year.ToString()); var oldPath = Path.Combine(basePath, SelectedProject); var newPath = Path.Combine(basePath, newName); if (Directory.Exists(oldPath)) { if (Directory.Exists(newPath)) { MessageBox.Show($"Ya existe un directorio con el nombre: {newName}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } Directory.Move(oldPath, newPath); } } MessageBox.Show("Proyecto renombrado exitosamente!", "Éxito", MessageBoxButton.OK, MessageBoxImage.Information); LoadExistingProjects(); // Recargar la lista de proyectos SelectedProject = newName; } catch (Exception ex) { MessageBox.Show($"Error al renombrar el proyecto: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); } } } // Agregar este método en la clase MainWindowViewModel [RelayCommand] private void DeleteProject() { if (string.IsNullOrEmpty(SelectedProject)) { MessageBox.Show("Por favor seleccione un proyecto para eliminar", "Advertencia", MessageBoxButton.OK, MessageBoxImage.Warning); return; } try { // Recopilar todos los directorios a verificar List directoriesToCheck = new List(); List nonEmptyDirectories = new List(); // Primero encontrar todos los directorios del proyecto foreach (var structure in currentConfig.FolderStructures) { var basePath = structure.BasePath.Replace("{year}", DateTime.Now.Year.ToString()); var projectPath = Path.Combine(basePath, SelectedProject); if (Directory.Exists(projectPath)) { directoriesToCheck.Add(projectPath); } } if (!directoriesToCheck.Any()) { MessageBox.Show("No se encontraron directorios para eliminar.", "Información", MessageBoxButton.OK, MessageBoxImage.Information); return; } // Verificar que todos los directorios estén vacíos foreach (var directory in directoriesToCheck) { if (!IsDirectoryEmpty(directory)) { nonEmptyDirectories.Add(directory); } } // Si hay directorios con contenido, mostrar mensaje y cancelar if (nonEmptyDirectories.Any()) { string message = "Los siguientes directorios contienen archivos y no pueden ser eliminados:\n\n"; message += string.Join("\n", nonEmptyDirectories); message += "\n\nDebe vaciar estos directorios antes de poder eliminar el proyecto."; MessageBox.Show(message, "Directorios no vacíos", MessageBoxButton.OK, MessageBoxImage.Warning); return; } // Si todos están vacíos, pedir confirmación var result = MessageBox.Show( $"Se eliminarán los siguientes directorios:\n\n{string.Join("\n", directoriesToCheck)}\n\n¿Está seguro que desea continuar?", "Confirmar eliminación", MessageBoxButton.YesNo, MessageBoxImage.Warning); if (result == MessageBoxResult.Yes) { // Eliminar todos los directorios foreach (var directory in directoriesToCheck) { if (Directory.Exists(directory)) { Directory.Delete(directory, false); // false porque ya sabemos que están vacíos } } MessageBox.Show("Proyecto eliminado exitosamente!", "Éxito", MessageBoxButton.OK, MessageBoxImage.Information); LoadExistingProjects(); // Recargar la lista de proyectos SelectedProject = null; } } catch (Exception ex) { MessageBox.Show($"Error al eliminar el proyecto: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); } } private bool IsDirectoryEmpty(string path) { try { return !Directory.EnumerateFileSystemEntries(path, "*", SearchOption.AllDirectories).Any(); } catch (Exception) { return false; } } [RelayCommand] private void CreateDirectories() { if (string.IsNullOrEmpty(NewProjectName)) { MessageBox.Show("Por favor ingrese un nombre de proyecto!", "Advertencia", MessageBoxButton.OK, MessageBoxImage.Warning); return; } if (currentConfig == null) { MessageBox.Show("Por favor seleccione una configuración!", "Advertencia", MessageBoxButton.OK, MessageBoxImage.Warning); return; } try { foreach (var structure in currentConfig.FolderStructures) { var basePath = structure.BasePath.Replace("{year}", DateTime.Now.Year.ToString()); var projectPath = Path.Combine(basePath, NewProjectName); if (Directory.Exists(projectPath)) { MessageBox.Show($"El directorio ya existe: {projectPath}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } Directory.CreateDirectory(projectPath); foreach (var subfolder in structure.Subfolders) { var subfolderPath = Path.Combine(projectPath, subfolder); Directory.CreateDirectory(subfolderPath); } } Process.Start("explorer.exe", Path.Combine(BasePath, NewProjectName)); MessageBox.Show("Directorios creados exitosamente!", "Éxito", MessageBoxButton.OK, MessageBoxImage.Information); LoadLastProjectNumber(); } catch (Exception ex) { MessageBox.Show($"Error al crear directorios: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error); } } } }