using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace CarManagerV2 { public partial class MainForm : Form { List cars = new List(); public MainForm() { InitializeComponent(); SafeManager.InitializeFile("cars.csv"); List _cars = SafeManager.ReadCars("cars.csv"); refreshCars(_cars); } private async void refreshCars(List _cars, bool updateGlobal = true) { // Sort by Car.Order. If equal, sort by ID _cars = _cars.Count > 0 ? _cars.OrderBy(c => c.Order).ThenBy(c => c.Id).ToList() : _cars; if (updateGlobal) { cars = _cars; } foreach (Car car in _cars) { // not in list? add it bool isNew = flpCars.Controls.OfType().All(c => c.Car.Id != car.Id); // existing but changed? update it CarCard card = new CarCard(); if (!isNew) { CarCard existing = flpCars.Controls.OfType().First(c => c.Car.Id == car.Id); Car existingCar = existing.Car; if (existing == null) { Console.Error.WriteLine($"[L] Error: Existing car card not found for car ID: {car.Id}"); continue; } // compare details Console.WriteLine($"[L] Checking car: {car.Id} | Car Color: {car.Color} | Ex Color: {existingCar.Color}"); if (existingCar.IsChanged(car)) { Console.WriteLine($"[L] Updating car: {car.Id}"); // changes card = existing; } else { // no changes Console.WriteLine($"[L] No changes for car: {car.Id}"); flpCars.Controls.SetChildIndex(existing, _cars.IndexOf(car)); continue; } } card.CarName = $"{car.Make} {car.Model}"; card.CarDetails = $"{car.Year}, {car.Mileage} km, ${car.Price}"; card.Car = car.Clone(); card.LoadImage(); // clear existing event handlers to prevent multiple subscriptions card.ClearCardClickedHandlers(); card.CardClicked += (s, e) => { Console.WriteLine($"Card clicked: {car.Id}"); CarDetailsForm detailsForm = new CarDetailsForm(car); detailsForm.FormClosed += async (s2, e2) => { Console.WriteLine("Car details form closed."); // refresh cars Console.WriteLine("Refreshing cars..."); List __cars = await Task.Run(() => SafeManager.ReadCars("cars.csv")); if(tbxSearch.Text.Length > 0) { Console.WriteLine("Search box has text, applying search filter."); cars = __cars; searchList(tbxSearch.Text); return; } refreshCars(__cars); }; detailsForm.ShowDialog(); }; if (isNew) { flpCars.Controls.Add(card); } flpCars.Controls.SetChildIndex(card, _cars.IndexOf(car)); } // Remove cards that are no longer in _cars var carIds = _cars.Select(c => c.Id).ToList(); var cardsToRemove = flpCars.Controls.OfType().Where(c => !carIds.Contains(c.Car.Id)).ToList(); foreach (var card in cardsToRemove) { flpCars.Controls.Remove(card); } flpCars.Refresh(); flpCars.Invalidate(); flpCars.Update(); } private void btnNewCar_Click(object sender, EventArgs e) { Car foocar = StateManager.CreateCar("New", "Car", 2020, "White", 0, 20000); CarDetailsForm detailsForm = new CarDetailsForm(foocar); detailsForm.FormClosed += (s2, e2) => { // refresh cars Console.WriteLine("Refreshing cars..."); List cars_ = SafeManager.ReadCars("cars.csv"); refreshCars(cars_, false); }; detailsForm.ShowDialog(); } List filterCarsByQuery(string query) { List results = new List(); foreach (Car car in cars) { if (car.Make.ToLower().Contains(query.ToLower()) || car.Model.ToLower().Contains(query.ToLower()) || car.Year.ToString().Contains(query) || car.Mileage.ToString().Contains(query) || car.Price.ToString().Contains(query)) { results.Add(car); } } return results; } void searchList(string query) { List results = filterCarsByQuery(query); refreshCars(results, false); } private async void tbxSearch_TextChanged(object sender, EventArgs e) { string query = tbxSearch.Text; await Task.Delay(100); // debounce if(query != tbxSearch.Text) return; // text changed during delay //flpCars.Controls.Clear(); if (string.IsNullOrWhiteSpace(query)) { refreshCars(cars); } else { searchList(query); } } } }