using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.DependencyInjection;
using PSCHelpdesk.Services;
using PSCHelpdesk.Shared.Menu;
using PSCHelpdesk.Shared.Service;
using PSCHelpdesk.Shared.Tasks;
using PSCHelpdesk.Shared.ViewModels;
using PSCHelpdesk.Tasks;
using PSCHelpdesk.Toasts;
using PSCHelpdesk.Toasts.Display;
using ReactiveUI;

namespace PSCHelpdesk.ViewModels;

public class MainWindowViewModel : ViewModelBase, IViewModelBase
{
    private MenuService MenuService;
    public ToastHolderViewModel ToastHolderManager { get; private set; }
    public TaskManager TaskManager { get; private set; }
    
    private bool _isReconnecting;
    public ReactiveCommand<string, Unit> ClickMenu { get; }
    
    public ReactiveCommand<Unit,Unit> OpenPlugins { get; }
    
    private ObservableCollection<TabItemViewModel> _tabItems;
    private TabItemViewModel _selectedTabItem;
    public ObservableCollection<TabItemViewModel> TabItems
    {
        get => _tabItems;
        set => SetAndRaisePropertyChanged(ref _tabItems, value);
    }
    public TabItemViewModel SelectedTabItem
    {
        get => _selectedTabItem;
        set => SetAndRaisePropertyChanged(ref _selectedTabItem, value);
    }

    private List<Item> _menuItems;
    public List<Item> MenuItems
    {
        get => _menuItems;
        set => SetAndRaisePropertyChanged(ref _menuItems, value);
    }
    public bool IsReconnecting
    {
        get => this._isReconnecting;
        private set => SetAndRaisePropertyChanged(ref _isReconnecting, value);
    }
    
    public MainWindowViewModel()
    {
        IsReconnecting = true;
        Startup.RegisterServices();
        ClickMenu = ReactiveCommand.Create<string>(SelectMenu);
        OpenPlugins = ReactiveCommand.Create(openPlugins);
        TabItems = new ObservableCollection<TabItemViewModel>();
        this.MenuItems = new List<Item>();
        MenuService = (MenuService)Ioc.Default.GetService(typeof(IMenuService));
        MenuService.MenuChanged += delegate(object? sender, EventArgs args)
        {
            foreach (var menuServiceMenuItem in MenuService.MenuItems)
            {
                if (!this.MenuItems.Contains(menuServiceMenuItem))
                {
                    menuServiceMenuItem.Command = this.ClickMenu;
                    this.MenuItems.Add(menuServiceMenuItem);
                }

                if (TabItems.Count == 0)
                {
                    TabItems.Add(new TabItemViewModel(MenuItems.Last().Header, MenuItems.Last().CommandParameter));    
                }
            }
            
            foreach (var menuServiceMenuItem in MenuService.MenuOptionItems)
            {
                if (!this.MenuItems.Contains(menuServiceMenuItem))
                {
                    menuServiceMenuItem.Command = this.ClickMenu;
                    this.MenuItems.Add(menuServiceMenuItem);
                }
            }
        };
            
        this.InitializeClient();
    }
    
    private void InitializeClient()
    {
        this.MenuService.CreateMenu();
        this.ToastHolderManager = new ToastHolderViewModel();
        this.TaskManager = (TaskManager)Ioc.Default.GetService<ITaskManager>();
        this.TaskManager.TaskCountChanged += this.TaskManager_TaskCountChanged;
    }
    
    private void TaskManager_TaskCountChanged(object sender, EventArgs e)
    {
        Avalonia.Threading.Dispatcher.UIThread.Post(() =>
        {
            this.IsReconnecting = this.TaskManager.RunningTasks.Count > 0;
        });
    }
    
    public void SelectMenu(string parameter)
    {
        var obj = this.MenuService.MenuItems.FirstOrDefault(menuItem => menuItem.Header == parameter.ToString(), null);
        if (obj != null)
        {
            if (TabItems.Count(x => x.Header == obj.Header) == 0)
            {
                TabItems.Add(new TabItemViewModel(obj.Header, obj.CommandParameter));
                SelectedTabItem = TabItems.Last();
            }
        }
    }

    void openPlugins()
    {
        if (TabItems.Count(x => x.Header == "Plugins") == 0)
            TabItems.Add(new TabItemViewModel("Plugins",
                new PluginListViewModel()));
           SelectedTabItem = TabItems.Last();
    }
    
}