using System.Collections.Specialized;
using MaterialSkin;
using MaterialSkin.Controls;
using VisionBuilder.UI.Common;
using VisionBuilder.UI.Common.Services;
using VisionBuilder.UI.Common.ViewModel;
using VisionBuilder.UI.Common.ViewModel.Classes;

namespace VisionBuilder.UI.Windows.Duo
{
    public partial class Form1 : MaterialForm
    {
        private readonly MainWindowVM _mainWindowVm;
        private readonly IPasswordInputService _passwordInputService;
        private readonly UIConfiguration _uiConfiguration;
        private readonly WindowsUISettings _windowsUiSettings;
        private readonly Dictionary<string, Control> _dynamicButtonControls = new();

        public Form1(MainWindowVM mainWindowVm, IPasswordInputService passwordInputService, UIConfiguration uiConfiguration, WindowsUISettings windowsUiSettings)
        {

            _mainWindowVm = mainWindowVm;
            _passwordInputService = passwordInputService;
            _uiConfiguration = uiConfiguration;
            _windowsUiSettings = windowsUiSettings;
            MaterialSkin.MaterialSkinManager.ConfigureForInspectron();
            InitializeComponent();
            singleCameraControl1.SetViewModel(mainWindowVm.SingleCameraVms[0]);
            singleCameraControl2.SetViewModel(mainWindowVm.SingleCameraVms[1]);
            Load += Form1_Load;
            _mainWindowVm.PropertyChanged += _mainWindowVm_PropertyChanged;
            lblVersion.Text = $"v{Application.ProductVersion.Split('+')[0]}";
            if(!_uiConfiguration.ShowTestModeButton)
                flowLayoutPanel1.Controls.Remove(btnTestMode);

            _mainWindowVm.DynamicButtons.CollectionChanged += DynamicButtons_CollectionChanged;
            foreach (var btn in _mainWindowVm.DynamicButtons)
                AddDynamicButton(btn);
        }

        private void _mainWindowVm_PropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(_mainWindowVm.TestMode))
            {
                if (_mainWindowVm.TestMode)
                {
                    MaterialSkinManager.Instance.ColorScheme = new ColorScheme(Primary.Green800, Primary.Green800,
                        Primary.Green400, Accent.Green200, TextShade.WHITE);
                }
                else
                {
                    MaterialSkinManager.ConfigureForInspectron();
                }
                Refresh();
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            _mainWindowVm.OnProgramStarted();
            BringToFront();
            if (_windowsUiSettings.FullScreen)
            {
                WindowState = FormWindowState.Maximized;
            }
        }

        protected override void OnShown(EventArgs e)
        {
            base.OnShown(e);
            flowLayoutPanel1.Left = (ClientSize.Width - flowLayoutPanel1.Width) / 2;


        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            _mainWindowVm.OnProgramClosed();
            Environment.Exit(0);
        }

        protected override void OnClosed(EventArgs e)
        {
            base.OnClosed(e);
            _mainWindowVm.OnProgramClosed();
            Environment.Exit(0);
        }

        private void btnMinimize_Click(object sender, EventArgs e)
        {
            WindowState = FormWindowState.Minimized;
        }

        private async void btnSettings_Click(object sender, EventArgs e)
        {
            if (_uiConfiguration.ProtectSettingsWithPassword)
            {
                var passwordOk = await _passwordInputService.GetPasswordAsync() == _uiConfiguration.AdminPassword;
                if (!passwordOk)
                    return;
            }
            _mainWindowVm.SettingsCommand.Execute(null);
        }

        private void btnTestMode_Click(object sender, EventArgs e)
        {
            _mainWindowVm.ToggleTestModeCommand.Execute(null);
        }

        public object GetHandle()
        {
            return this;
        }

        private void DynamicButtons_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Add:
                    foreach (ButtonDefinition btn in e.NewItems!)
                        AddDynamicButton(btn);
                    break;
                case NotifyCollectionChangedAction.Remove:
                    foreach (ButtonDefinition btn in e.OldItems!)
                        RemoveDynamicButton(btn);
                    break;
                case NotifyCollectionChangedAction.Reset:
                    foreach (var ctrl in _dynamicButtonControls.Values)
                        flowLayoutPanel1.Controls.Remove(ctrl);
                    _dynamicButtonControls.Clear();
                    break;
            }
        }

        private void AddDynamicButton(ButtonDefinition buttonDef)
        {
            var btn = new MaterialRaisedButton
            {
                Text = buttonDef.Title,
                Size = new Size(176, 64),
                Font = new Font("Segoe UI Semibold", 12F, FontStyle.Bold),
                DrawBorder = true,
                Primary = buttonDef.Type == EButtonType.Toggle && buttonDef.IsToggled,
                Visible = buttonDef.IsVisible
            };

            btn.Click += (_, _) =>
            {
                buttonDef.Execute();
                if (buttonDef.Type == EButtonType.Toggle)
                    btn.Primary = buttonDef.IsToggled;
            };

            buttonDef.PropertyChanged += (_, args) =>
            {
                if (args.PropertyName == nameof(ButtonDefinition.IsVisible))
                    btn.Visible = buttonDef.IsVisible;
                else if (args.PropertyName == nameof(ButtonDefinition.IsToggled))
                    btn.Primary = buttonDef.IsToggled;
            };

            // Insert before Minimize button
            var minimizeIndex = flowLayoutPanel1.Controls.IndexOf(btnMinimize);
            if (minimizeIndex >= 0)
                flowLayoutPanel1.Controls.Add(btn);
            flowLayoutPanel1.Controls.SetChildIndex(btn, minimizeIndex >= 0 ? minimizeIndex : flowLayoutPanel1.Controls.Count - 1);
            _dynamicButtonControls[buttonDef.Key] = btn;
        }

        private void RemoveDynamicButton(ButtonDefinition buttonDef)
        {
            if (_dynamicButtonControls.TryGetValue(buttonDef.Key, out var ctrl))
            {
                flowLayoutPanel1.Controls.Remove(ctrl);
                _dynamicButtonControls.Remove(buttonDef.Key);
            }
        }
    }
}
