using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Windows.Forms; namespace CarManagerV3 { /// /// Handles safe reading and writing of car data to files. /// internal class SafeManager { /// /// The path of the txt file that contains recently opened file paths. /// private static readonly string recentPathsFile = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\CarManagerV3\\recent_paths.txt"; /// /// Initializes a file at a specified path if it does not already exist. /// /// The path of the file. public static void InitializeFile(string path) { try { if (!File.Exists(@path)) { using (StreamWriter writer = new StreamWriter(@path)) { // Create the file, empty //writer.WriteLine(); writer.Close(); } } } catch (Exception ex) { Console.Error.WriteLine($"Error initializing file: {ex.Message}"); } } /// /// Initializes a file and its parent folders at a specified path if they do not already exist. /// /// The path of the file. public static void initializeFileAndFolders(string path) { try { string directory = Path.GetDirectoryName(path); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } InitializeFile(path); } catch (Exception ex) { Console.Error.WriteLine($"Error initializing file and folders: {ex.Message}"); } } /// /// Reads cars from a specified file path. /// /// The path. /// /// A containing the cars read from the file. /// public static List ReadCars(string path) { List cars = new List(); List failedLines = new List(); bool isLegacy = false; try { using (StreamReader reader = new StreamReader(@path)) { string line; while ((line = reader.ReadLine()) != null) { // Process the line if (line == "") continue; if (Car.isLegacyCsvString(line)) { if (!StateManager.askForMigration()) { MessageBox.Show("The file you are trying to open is in an old format that is no longer supported. Please select a different file.", "Unsupported Format", MessageBoxButtons.OK, MessageBoxIcon.Error); throw new LegacyException(); //Environment.Exit(0); } else { isLegacy = true; } } Car tmp = Car.FromCsvString(line); if (tmp == null) { failedLines.Add(line); continue; } cars.Add(tmp); } reader.Close(); } } catch (LegacyException ex) { throw ex; } catch (Exception ex) { Console.Error.WriteLine($"Error reading cars from file: {ex.Message}"); } if (failedLines.Count > 0) { Console.Error.WriteLine($"Warning: {failedLines.Count} lines could not be parsed and were skipped."); foreach (string failedLine in failedLines) { Console.Error.WriteLine($"Failed line: {failedLine}"); } MessageBox.Show($"Warning: {failedLines.Count} lines in the file could not be parsed and were skipped. Check the console for details.", "Parsing Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); } cars = StateManager.normalizeOrders(cars); cars = cars.OrderBy(c => c.Order).ToList(); if (isLegacy) { SafeManager.SaveCars(path, cars); } return cars; } /// /// Saves the cars to a specified file path. /// /// The path. /// A containing all cars to save. public static void SaveCars(string path, List cars) { try { using (StreamWriter writer = new StreamWriter(@path)) { foreach (Car car in cars) { writer.WriteLine(car.ToCsvString()); } writer.Close(); } } catch (Exception ex) { Console.Error.WriteLine($"Error saving cars to file: {ex.Message}"); MessageBox.Show($"Error saving cars to file: {ex.Message}", "Save Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } /// /// Adds a file path to the recent paths list. /// If a path is already in the list, it is moved to the top. /// Otherwise, it is added to the top. /// Keeps only the 5 most recent paths. /// /// The path. public static void AddRecentPath(string path) { List paths = new List(); try { paths = GetRecentPaths(); paths.Remove(path); paths.Insert(0, path); if (paths.Count > 5) { paths = paths.Take(5).ToList(); } using (StreamWriter writer = new StreamWriter(recentPathsFile)) { foreach (string p in paths) { writer.WriteLine(p); } writer.Close(); } } catch (Exception ex) { Console.Error.WriteLine($"Error managing recent paths: {ex.Message}"); } } /// /// Gets the recently opened file paths. /// /// /// A containing the recent file paths. /// public static List GetRecentPaths() { List paths = new List(); try { initializeFileAndFolders(recentPathsFile); if (File.Exists(recentPathsFile)) //TODO: Remove { using (StreamReader reader = new StreamReader(recentPathsFile)) { string line; while ((line = reader.ReadLine()) != null) { paths.Add(line); } reader.Close(); } } } catch (Exception ex) { Console.Error.WriteLine($"Error reading recent paths: {ex.Message}"); } return paths; } /// /// Gets the folder of the most recently opened file. /// /// /// The folder path of the most recently opened file, or the users documents folder if no recent files. /// public static string getRecentFolder() { List recentPaths = GetRecentPaths(); if (recentPaths.Count > 0) { string recentFile = recentPaths[0]; if (File.Exists(recentFile)) { return Path.GetDirectoryName(recentFile); } } return Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); } /// /// Clears the recently opened file paths list by deleting the recent paths file. /// public static void ClearRecentPaths() { try { if (File.Exists(recentPathsFile)) { File.Delete(recentPathsFile); } } catch (Exception ex) { Console.Error.WriteLine($"Error clearing recent paths: {ex.Message}"); } } } }