using Common.Database;
using Common.Model;
using System.Drawing.Imaging;
using System.ComponentModel;

namespace Administration
{
    public partial class ProductAdd : Form
    {
        private readonly IDatabase database;

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Product? Product { get; set; } = null;

        public ProductAdd(IDatabase db)
        {
            this.database = db;

            InitializeComponent();

            expirationDate.MinDate = packagingDate.Value;
            expirationDate.Value = packagingDate.Value.AddDays(90);
            packagingDate.MaxDate = DateTime.Today;

            packagingDate.ValueChanged += (sender, e) =>
            {
                expirationDate.MinDate = packagingDate.Value;
            };

            string separator = string.Empty;
            var codecs = ImageCodecInfo.GetImageEncoders();
            foreach (var c in codecs)
            {
                string codecName = c.CodecName[8..].Replace("Codec", "Files").Trim();
                openFileDialog.Filter = String.Format("{0}{1}{2} ({3})|{3}", openFileDialog.Filter, separator, codecName, c.FilenameExtension);
                separator = "|";
            }
        }

        private void ValidatePrice(object sender, EventArgs e)
        {
            if (price.Text.Length > 0 && !float.TryParse(price.Text, out var _))
                errorProvider.SetError(price, $"{price.Text} is not valid numerical value for HUF currency!");
            else
                errorProvider.SetError(price, string.Empty);
        }

        private void OpenFile(object sender, EventArgs e)
        {
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                pictureBox.Image = Image.FromFile(openFileDialog.FileName);
            }
        }

        private void SaveProduct(object sender, EventArgs e)
        {
            errorProvider.Clear();

            string productName = name.Text;
            string productDescription = description.Text;

            var productPackaged = packagingDate.Value.Date;
            var productExpires = expirationDate.Value.Date;
            var productImage = pictureBox.Image;

            if (productName.Length == 0)
                errorProvider.SetError(name, "Name is required");

            if (productDescription.Length == 0)
                errorProvider.SetError(description, "Description is required");

            float productPrice = 0;
            if (price.Text.Length == 0)
                errorProvider.SetError(price, "Will this product be free?");
            else if (!float.TryParse(price.Text, out productPrice))
                errorProvider.SetError(price, $"{price.Text} is not valid numerical value for HUF currency!");

            if (productImage == null)
                errorProvider.SetError(pictureBox, "Easier to sell products with images!");

            if (errorProvider.HasErrors)
                return;

            Action<Product> action = (Product == null) ? database.Store : database.Update;
            Product ??= new Product(); // compound assignment

            Product.Name = productName;
            Product.Description = productDescription;
            Product.Price = productPrice;
            Product.PackagingDate = productPackaged;
            Product.ExpirationDate = productExpires;
            Product.Image = productImage;

            action(Product);

            DialogResult = DialogResult.OK;
        }

        private void Loaded(object sender, EventArgs e)
        {
            if (Product != null)
            {
                name.Text = Product.Name;
                description.Text = Product.Description;
                price.Text = Product.Price.ToString();

                packagingDate.Value = Product.PackagingDate;
                expirationDate.Value = Product.ExpirationDate;
                pictureBox.Image = Product.Image;

                buttonDelete.Visible = true;
            }
        }

        private void DeleteProduct(object sender, EventArgs e)
        {
            // Assuming that the product is not null here, since the button is
            // only visible if the stage is editing.
            database.Delete<Product>(Product.ID);

            DialogResult = DialogResult.OK;
        }
    }
}
