diff --git a/CarManagerV3/Util/CarCompletions.cs b/CarManagerV3/Util/CarCompletions.cs index 0ee8732..372e9f2 100644 --- a/CarManagerV3/Util/CarCompletions.cs +++ b/CarManagerV3/Util/CarCompletions.cs @@ -10,6 +10,14 @@ using CarManagerV3.Classes; namespace CarManagerV3.Util { + /// + /// Provides car manufacturer and model autocompletion data for the application. + /// Manages fetching, caching, and retrieval of car brand and model information from remote sources and local storage. + /// + /// + /// This class maintains a static list of car manufacturers and their models, supports fetching updated data from remote URLs, + /// and caches the data locally for offline use. It implements retry logic to prevent excessive network requests. + /// internal class CarCompletions { /// @@ -21,10 +29,28 @@ namespace CarManagerV3.Util "https://static.clsw.app/carmgm/merged-cars.json" }; + /// + /// The filename for the cached car completion data in the user's data directory. + /// private static readonly string carCompletionDataFileName = "car_data.json"; + + /// + /// The timestamp of the last fetch attempt for car completion data. + /// Used to implement retry throttling to prevent excessive network requests. + /// private static DateTime lastFetchAttempt = Properties.Settings.Default.LastFetchedAutoCompletions; + + /// + /// The minimum time interval that must elapse between fetch attempts. + /// Prevents excessive retry attempts when the remote source is unavailable. + /// private static readonly TimeSpan fetchRetryInterval = Properties.Settings.Default.FetchAutoCompletionsInterval; // Minimum interval between fetch attempts + /// + /// Gets the full file path for the car completion data file. + /// Ensures that the user data directory exists before returning the path. + /// + /// The full file path to the car completion data file in the user's data directory. private static string getCarCompletionDataFilePath() { var userDataDir = Properties.Settings.Default.DataLocation; @@ -32,6 +58,10 @@ namespace CarManagerV3.Util return Path.Combine(userDataDir, carCompletionDataFileName); } + /// + /// The static list of car manufacturers and their available models. + /// This list serves as the default data and is updated when fetching from remote sources or local cache. + /// public static List carBrands = new List { new CarManufacturer("Toyota") { Models = new List { "Camry", "Corolla", "RAV4" } }, @@ -48,22 +78,45 @@ namespace CarManagerV3.Util new CarManufacturer("Skoda") { Models = new List { "Octavia", "Fabia", "Kodiaq" } }, }; + /// + /// Gets the full list of car brands. + /// + /// A list of strings containing all available car manufacturer names. public static List GetCarBrands() { return carBrands.Select(c => c.Name).ToList(); } + /// + /// Retrieves the list of car models for a specified brand. + /// The search is case-insensitive. + /// + /// The name of the car brand to search for. + /// A list of car models for the specified brand, or an empty list if the brand is not found. public static List GetCarModels(string brand) { var manufacturer = carBrands.FirstOrDefault(c => c.Name.Equals(brand, StringComparison.OrdinalIgnoreCase)); return manufacturer != null ? manufacturer.Models : new List(); } + /// + /// A predefined list of common car colors for autocompletion purposes. + /// Provides standard color options that are frequently used in vehicle descriptions. + /// public static List CommonColors = new List { "Black", "White", "Gray", "Silver", "Red", "Blue", "Green", "Yellow", "Brown", "Orange" }; + /// + /// Reads car completion data from an embedded resource file. + /// This method is intended to populate the carBrands list from a JSON resource embedded in the project. + /// + /// + /// The expected resource format is a JSON object where keys are car brand names and values are lists of model names. + /// Resource name: CarCompleteData (JSON file format). + /// Currently not implemented. + /// public static void ReadFromResourceFile() { // Read the json file from the projects resources and populate the carBrands list @@ -77,7 +130,12 @@ namespace CarManagerV3.Util /// /// Fetches the car data from urls asynchronous and saves it in the users data directory for offline use. /// - /// + /// A task representing the asynchronous operation. + /// + /// This method implements retry throttling using the to prevent excessive network requests. + /// It attempts to fetch data from each URL in in order until successful or all URLs are exhausted. + /// The fetched data is saved to the local file system for offline access. + /// public static async Task FetchCarCompletionDataFromUrlsAsync() { if(DateTime.Now - lastFetchAttempt < fetchRetryInterval) @@ -97,11 +155,10 @@ namespace CarManagerV3.Util var response = await httpClient.GetAsync(url); response.EnsureSuccessStatusCode(); var jsonData = await response.Content.ReadAsStringAsync(); - // Save the json data to a file in the user's data directory for offline use + // Saves the json data to a file in the user's data directory for offline use var filePath = getCarCompletionDataFilePath(); await File.WriteAllTextAsync(filePath, jsonData); System.Diagnostics.Debug.WriteLine($"Successfully fetched car data from {url} and saved to {filePath}"); - // Optionally, you can also parse the json data and populate the carBrands list here break; // Exit the loop if data is successfully fetched } catch (Exception ex) @@ -115,14 +172,29 @@ namespace CarManagerV3.Util /// /// Fetches the car data from urls and saves it in the users data directory for offline use. + /// This is a synchronous wrapper that blocks until the asynchronous fetch operation completes. /// - /// + /// A task representing the synchronous operation. + /// + /// This method wraps and runs it synchronously. + /// Consider using the async version directly when possible to avoid blocking the thread. + /// public static Task FetchCarCompletionDataFromUrls() { // Run synchronously return Task.Run(() => FetchCarCompletionDataFromUrlsAsync().Wait()); } + /// + /// Loads car manufacturer data from the locally cached file. + /// Optionally fetches updated data from remote sources before loading from file. + /// + /// If true, skips fetching data from remote sources and only reads from the local cache. Default is false. + /// A list of objects populated from the cached file, or an empty list if the file doesn't exist or an error occurs. + /// + /// The expected file format is a JSON object where keys are car brand names and values are lists of model names. + /// If the file doesn't exist or cannot be read, an error message is logged and an empty list is returned. + /// public static List GetFromFile(bool skipOnlineUpdate = false) { if (!skipOnlineUpdate) FetchCarCompletionDataFromUrls(); @@ -151,6 +223,15 @@ namespace CarManagerV3.Util return new List(); } + /// + /// Updates the static list with data from the local cache file. + /// Only updates the list if the cached file contains valid data. + /// + /// If true, skips fetching data from remote sources before updating. Default is false. + /// + /// This method calls and updates only if the returned list is not empty. + /// If no data is retrieved, the existing list remains unchanged. + /// public static void UpdateCarCompletionData(bool skipOnlineUpdate = false) { var updatedCarBrands = GetFromFile(skipOnlineUpdate); @@ -160,6 +241,15 @@ namespace CarManagerV3.Util } } + /// + /// Asynchronously updates the car completion data by fetching from remote sources and updating the local cache. + /// This is the recommended method for refreshing car data in the application. + /// + /// A task representing the asynchronous update operation. + /// + /// This method first attempts to fetch updated data from remote URLs using , + /// then updates the static list from the local cache using . + /// public static async Task UpdateCarCompletionDataAsync() { await FetchCarCompletionDataFromUrlsAsync();