using System;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CarManagerV3
{
    public partial class CarDetailsForm : Form
    {

        public Car car;

        public CarDetailsForm(Car car)
        {
            InitializeComponent();
            this.car = car;
            tbxMake.Text = car.Make;
            tbxModel.Text = car.Model;
            nudYear.Value = car.Year;
            tbxColor.Text = car.Color;
            nudMileage.Value = car.Mileage;
            nudPrice.Value = car.Price;
            tbxAge.Text = car.AgeString;
            pbxCarImage.Image = ImageManager.GetImage(car);
            if (car.Id == "0")
            {
                lblID.Text = "New Car";
            }
            else
            {
                lblID.Text = $"ID: {car.Id}";
            }
        }

        /// <summary>
        /// Updates a car property safely by executing the update action and reverting it if an exception occurs.
        /// </summary>
        /// <param name="updateAction">The update action.</param>
        /// <param name="revertAction">The action to perform when the update fails.</param>
        private void SafeUpdate(Action updateAction, Action revertAction)
        {
            try
            {
                updateAction();
            }
            catch (ArgumentException ex)
            {
                MessageBox.Show(ex.Message, "Invalid Input", MessageBoxButtons.OK, MessageBoxIcon.Error);
                revertAction();
            }
        }

        //private string ValueOrFormer(string newValue, string oldValue)
        //{
        //    return string.IsNullOrWhiteSpace(newValue) ? oldValue : newValue;
        //}

        private T ValueOrFormer<T>(T newValue, T oldValue)
        {
            if (newValue is string str)
            {
                return string.IsNullOrWhiteSpace(str) ? oldValue : newValue;
            }
            return newValue;
        }

        private void tbxMake_TextChanged(object sender, EventArgs e)
        {
            SafeUpdate(
                () => car.Make = ValueOrFormer(tbxMake.Text, car.Make),
                () => tbxMake.Text = car.Make
            );
        }

        private void tbxModel_TextChanged(object sender, EventArgs e)
        {
            SafeUpdate(
                () => car.Model = ValueOrFormer(tbxModel.Text, car.Model),
                () => tbxModel.Text = car.Model
            );
        }

        private void nudYear_ValueChanged(object sender, EventArgs e)
        {
            SafeUpdate(
                () =>
                {
                    car.Year = (int)ValueOrFormer(nudYear.Value, car.Year);
                    tbxAge.Text = car.AgeString;
                },
                () => nudYear.Value = car.Year
            );
        }

        private void tbxColor_TextChanged(object sender, EventArgs e)
        {
            SafeUpdate(
                () => car.Color = ValueOrFormer(tbxColor.Text, car.Color),
                () => tbxColor.Text = car.Color
            );
        }

        private void nudMileage_ValueChanged(object sender, EventArgs e)
        {
            SafeUpdate(
                () => car.Mileage = (int)nudMileage.Value, 
                () => nudMileage.Value = car.Mileage
            );
        }

        private void nudPrice_ValueChanged(object sender, EventArgs e)
        {
            SafeUpdate(
                () => car.Price = nudPrice.Value, 
                () => nudPrice.Value = car.Price
            );
        }

        private async void btnSave_Click(object sender, EventArgs e)
        {
            // save car to cars.csv and close form
            //saving car... popuo
            btnSave.Enabled = false;
            btnDelete.Enabled = false;
            var msgbox = new PleaseWait();
            msgbox.Show();
            await Task.Run(() =>
            {
                if(car.Id == "0") {
                    car = StateManager.CreateCar(car.Make, car.Model, car.Year, car.Color, car.Mileage, car.Price);
                }
                else { 
                    StateManager.UpdateCar(car);
                }
                Console.WriteLine("Saved car: " + car.Id);
            });
            Console.WriteLine("Car saved. " + car.Id);
            btnSave.Enabled = true;
            btnDelete.Enabled = true;
            this.Close();
            msgbox.Close();
            


        }

        private void btnDelete_Click(object sender, EventArgs e)
        {
            if(car.Id == "0")
            {
                //just close form if car is not saved yet
                this.Close();
                return;
            }
            //are you sure?
            var result = MessageBox.Show("Are you sure you want to delete this car?", "Delete Car", MessageBoxButtons.YesNo, MessageBoxIcon.Warning);
            if (result == DialogResult.Yes)
            {
                Console.WriteLine("Deleting car: " + car.Id);
                StateManager.RemoveCar(car);
                this.Close();
            }
        }

        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (keyData == Keys.Enter)
            {
                btnSave.PerformClick();
                return true; // Indicate that the key has been handled
            }
            if (keyData == Keys.Escape)
            {
                this.Close();
                return true; // Indicate that the key has been handled
            }
            if (keyData == Keys.Delete)
            {
                btnDelete.PerformClick();
                return true; // Indicate that the key has been handled
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }

        private void tbxMake_Leave(object sender, EventArgs e)
        {
            tbxMake.Text = ValueOrFormer(tbxMake.Text, car.Make);
        }

        private void tbxModel_Leave(object sender, EventArgs e)
        {
            tbxModel.Text = ValueOrFormer(tbxModel.Text, car.Model);
        }

        private void tbxColor_Leave(object sender, EventArgs e)
        {
            tbxColor.Text = ValueOrFormer(tbxColor.Text, car.Color);
        }


    }
}
