using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Threading;
using System.Windows.Forms;

namespace MaterialSkin.Controls
{
    public partial class MaterialCancellableLoader : MaterialForm
    {
        private readonly Dictionary<string, (MaterialProgressBar ProgressBar, Label Label, MaterialFlatButton CancelButton, CancellationTokenSource CancellationTokenSource)> _loadingProcesses;
        public event EventHandler<string> LoadingCancelled;

        public MaterialCancellableLoader()
        {
            InitializeComponent();
            RemoveMessageFilter();
            _loadingProcesses = new Dictionary<string, (MaterialProgressBar, Label, MaterialFlatButton, CancellationTokenSource)>();
            this.MaximizeBox = false;
            this.MinimizeBox = false;
            this.StartPosition = FormStartPosition.CenterScreen;
            this.Width = 450;
            
        }

        public CancellationToken StartLoading(string title)
        {
            if (_loadingProcesses.ContainsKey(title))
            {
                return _loadingProcesses[title].CancellationTokenSource.Token;
            }

            var cancellationTokenSource = new CancellationTokenSource();

            var progressBar = new MaterialProgressBar
            {
                Width = this.ClientSize.Width - 120, // Leave space for cancel button
                Height = 20,
                Top = 50 + (_loadingProcesses.Count * 60),
                Left = 10,
                Style = ProgressBarStyle.Marquee,
                MarqueeAnimationSpeed = 30,
                Value = 50,
                BackColor = Color.White
            };

            var label = new Label
            {
                Text = title,
                AutoSize = true,
                Top = progressBar.Top - 20,
                Left = progressBar.Left,
                BackColor = Color.White,
                ForeColor = SkinManager.GetPrimaryTextColor()
            };

            var cancelButton = new MaterialFlatButton
            {
                Text = "Cancel",
                Width = 80,
                Height = 30,
                Top = progressBar.Top - 5,
                Left = progressBar.Right + 10,
                UseVisualStyleBackColor = true
            };

            // Capture the title in the closure properly
            var capturedTitle = title;
            cancelButton.Click += (sender, e) =>
            {
                CancelLoading(capturedTitle);
            };

            _loadingProcesses[title] = (progressBar, label, cancelButton, cancellationTokenSource);
            
            this.Controls.Add(label);
            this.Controls.Add(progressBar);
            this.Controls.Add(cancelButton);
            
            
            
            if (!this.Visible)
            {
                this.Show();
            }

            this.Refresh();
            return cancellationTokenSource.Token;
        }

        public void FinishLoading(string title)
        {
            if (_loadingProcesses.TryGetValue(title, out var components))
            {
                this.Controls.Remove(components.ProgressBar);
                this.Controls.Remove(components.Label);
                this.Controls.Remove(components.CancelButton);
                components.CancellationTokenSource.Dispose();
                _loadingProcesses.Remove(title);
                RearrangeControls();
            }

            if (_loadingProcesses.Count == 0)
            {
                this.Hide();
            }
        }

        public void CancelLoading(string title)
        {
            if (_loadingProcesses.TryGetValue(title, out var components))
            {
                components.CancellationTokenSource.Cancel();
                LoadingCancelled?.Invoke(this, title);
                FinishLoading(title);
            }
        }

        public void CancelAllLoading()
        {
            var titles = _loadingProcesses.Keys.ToList();
            foreach (var title in titles)
            {
                CancelLoading(title);
            }
        }

        public bool IsLoading(string title)
        {
            return _loadingProcesses.ContainsKey(title);
        }

        public bool HasActiveLoading => _loadingProcesses.Count > 0;

        public IEnumerable<string> ActiveLoadingTitles => _loadingProcesses.Keys.ToList();

        private void RearrangeControls()
        {
            int index = 0;
            foreach (var components in _loadingProcesses.Values)
            {
                var newTop = 50 + (index * 60);
                components.ProgressBar.Top = newTop;
                components.Label.Top = newTop - 20;
                components.CancelButton.Top = newTop - 5;
                index++;
            }

            
        }



        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            // Don't allow closing if there are active loading processes
            if (_loadingProcesses.Count > 0)
            {
                e.Cancel = true;
                return;
            }
            
            base.OnFormClosing(e);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                // Cancel all ongoing operations and dispose resources
                foreach (var components in _loadingProcesses.Values)
                {
                    components.CancellationTokenSource?.Dispose();
                }
                _loadingProcesses.Clear();
            }
            base.Dispose(disposing);
        }
    }
}