public SolutionExplorerViewModel(ISolutionItemNameRegistry itemNameRegistry,
                                         ISolutionManager solutionManager,
                                         IEventAggregator ea,
                                         ISolutionSqlService solutionSqlService,
                                         INewItemService newItemService,
                                         ISolutionTasksService solutionTasksService,
                                         IStatusBar statusBar,
                                         ISolutionItemIconRegistry solutionItemIconRegistry,
                                         ISolutionItemProvideService provider)
        {
            this.itemNameRegistry = itemNameRegistry;
            this.solutionManager  = solutionManager;
            this.ea        = ea;
            this.statusBar = statusBar;
            this.solutionItemIconRegistry = solutionItemIconRegistry;

            Root            = new ObservableCollection <SolutionItemViewModel>();
            itemToViewmodel = new Dictionary <ISolutionItem, SolutionItemViewModel>();

            foreach (ISolutionItem item in this.solutionManager.Items)
            {
                AddItemToRoot(item);
            }

            this.solutionManager.Items.CollectionChanged += (sender, args) =>
            {
                if (args.NewItems != null)
                {
                    var i = 0;
                    foreach (ISolutionItem obj in args.NewItems)
                    {
                        AddItemToRoot(obj, args.NewStartingIndex + i);
                        i++;
                    }
                }

                if (args.OldItems != null)
                {
                    foreach (ISolutionItem obj in args.OldItems)
                    {
                        ISolutionItem solutionItem = obj;
                        Root.Remove(itemToViewmodel[solutionItem]);
                        itemToViewmodel.Remove(solutionItem);
                    }
                }
            };

            solutionManager.RefreshRequest += item =>
            {
                foreach (var root in Root)
                {
                    root.Refresh();
                }
            };

            Dictionary <string, AddItemCategoryMenuViewModel> byNameCategories = new();
            Func <ISolutionItemProvider, Task> insertItemCommand = async provider =>
            {
                var item = await provider.CreateSolutionItem();

                if (item != null)
                {
                    DoAddItem(item);
                }
            };

            foreach (var item in provider.AllCompatible)
            {
                if (item is INamedSolutionItemProvider)
                {
                    continue;
                }

                if (!byNameCategories.TryGetValue(item.GetGroupName(), out var category))
                {
                    category = new AddItemCategoryMenuViewModel(item.GetGroupName());
                    byNameCategories.Add(category.Name, category);
                    AddItems.Add(category);
                }

                category.Items.Add(new SolutionItemMenuViewModel(item, insertItemCommand));
            }

            AddItem = new DelegateCommand(async() =>
            {
                ISolutionItem?item = await newItemService.GetNewSolutionItem();
                if (item != null)
                {
                    DoAddItem(item);
                }
            }, () => (SelectedItem == null || SelectedItem.IsContainer) && SelectedItems.Count <= 1)
                      .ObservesProperty(() => SelectedItem)
                      .ObservesProperty(() => SelectedItems.Count);

            RemoveItem = new DelegateCommand(() =>
            {
                if (SelectedItems.Count > 0)
                {
                    foreach (var item in SelectedItems.ToList())
                    {
                        DeleteSolutionItem(item);
                    }
                    SelectedItems.Clear();
                }
                else if (selected != null)
                {
                    DeleteSolutionItem(selected);
                }
            }, () => SelectedItem != null || SelectedItems.Count > 0)
                         .ObservesProperty(() => SelectedItem)
                         .ObservesProperty(() => SelectedItems.Count);

            SelectedItemChangedCommand = new DelegateCommand <SolutionItemViewModel>(ob => { selected = ob; });

            RequestOpenItem = new DelegateCommand <SolutionItemViewModel>(item =>
            {
                if (item != null && !item.IsContainer)
                {
                    this.ea.GetEvent <EventRequestOpenItem>().Publish(item.Item);
                }
            });

            GenerateSQL = new DelegateCommand(() =>
            {
                if (selected != null)
                {
                    solutionSqlService.OpenDocumentWithSqlFor(selected.Item);
                }
            });

            UpdateDatabase = new DelegateCommand(() =>
            {
                if (selected != null)
                {
                    solutionTasksService.SaveSolutionToDatabaseTask(selected.Item);
                }
            }, () => solutionTasksService.CanSaveToDatabase);

            ExportToServer = new DelegateCommand(() =>
            {
                if (selected != null)
                {
                    solutionTasksService.SaveAndReloadSolutionTask(selected.Item);
                }
            }, () => solutionTasksService.CanSaveAndReloadRemotely);

            ExportToServerItem = new DelegateCommand <SolutionItemViewModel>(item =>
            {
                if (item != null)
                {
                    solutionTasksService.SaveAndReloadSolutionTask(item.Item);
                }
            }, item => solutionTasksService.CanSaveAndReloadRemotely);
        }
        public SolutionExplorerViewModel(ISolutionItemNameRegistry itemNameRegistry,
                                         ISolutionManager solutionManager,
                                         IEventAggregator ea,
                                         ISolutionSqlService solutionSqlService,
                                         INewItemService newItemService,
                                         ISolutionTasksService solutionTasksService,
                                         IStatusBar statusBar,
                                         ISolutionItemIconRegistry solutionItemIconRegistry,
                                         ISolutionItemProvideService provider,
                                         IInputBoxService inputBoxService,
                                         IMessageBoxService messageBoxService)
        {
            this.itemNameRegistry = itemNameRegistry;
            this.solutionManager  = solutionManager;
            this.ea        = ea;
            this.statusBar = statusBar;
            this.solutionItemIconRegistry = solutionItemIconRegistry;
            this.inputBoxService          = inputBoxService;

            Root            = new ObservableCollection <SolutionItemViewModel>();
            itemToViewmodel = new Dictionary <ISolutionItem, SolutionItemViewModel>();

            foreach (ISolutionItem item in this.solutionManager.Items)
            {
                AddItemToRoot(item);
            }

            this.solutionManager.Items.CollectionChanged += (sender, args) =>
            {
                if (args.NewItems != null)
                {
                    var i = 0;
                    foreach (ISolutionItem obj in args.NewItems)
                    {
                        AddItemToRoot(obj, args.NewStartingIndex + i);
                        i++;
                    }
                }

                if (args.OldItems != null)
                {
                    foreach (ISolutionItem obj in args.OldItems)
                    {
                        ISolutionItem solutionItem = obj;
                        Root.Remove(itemToViewmodel[solutionItem]);
                        itemToViewmodel.Remove(solutionItem);
                    }
                }
            };

            solutionManager.RefreshRequest += item =>
            {
                foreach (var root in Root)
                {
                    root.Refresh();
                }
            };

            Dictionary <string, AddItemCategoryMenuViewModel> byNameCategories = new();
            Func <ISolutionItemProvider, Task> insertItemCommand = async provider =>
            {
                ISolutionItem?item = null;
                if (provider is INamedSolutionItemProvider namedProvider)
                {
                    var name = await this.inputBoxService.GetString("New",
                                                                    "Please provide a name for " + namedProvider.GetName(), "");

                    if (name == null || name.Length < 3)
                    {
                        await messageBoxService.ShowDialog(new MessageBoxFactory <bool>()
                                                           .SetTitle("New")
                                                           .SetMainInstruction("Name is too short")
                                                           .SetContent("Name can't be shorter than 3 characters")
                                                           .WithOkButton(true)
                                                           .Build());

                        return;
                    }

                    item = await namedProvider.CreateSolutionItem(name);
                }
                else
                {
                    item = await provider.CreateSolutionItem();
                }
                if (item != null)
                {
                    DoAddItem(item);
                }
            };

            foreach (var item in provider.AllCompatible)
            {
                if (!byNameCategories.TryGetValue(item.GetGroupName(), out var category))
                {
                    category = new AddItemCategoryMenuViewModel(item.GetGroupName());
                    byNameCategories.Add(category.Name, category);
                    AddItems.Add(category);
                }

                category.Items.Add(new SolutionItemMenuViewModel(item, insertItemCommand));
            }

            AddItem = new DelegateCommand(async() =>
            {
                ISolutionItem?item = await newItemService.GetNewSolutionItem();
                if (item != null)
                {
                    DoAddItem(item);
                }
            }, () => (SelectedItem == null || SelectedItem.IsContainer) && SelectedItems.Count <= 1)
                      .ObservesProperty(() => SelectedItem)
                      .ObservesProperty(() => SelectedItems.Count);

            RemoveItem = new DelegateCommand <SolutionItemViewModel>(vm =>
            {
                if (SelectedItems.Count > 0)
                {
                    foreach (var item in SelectedItems.ToList())
                    {
                        DeleteSolutionItem(item);
                    }
                    SelectedItems.Clear();
                }
                else if (vm != null)
                {
                    DeleteSolutionItem(vm);
                }
            }, vm => vm != null || SelectedItems.Count > 0)
                         .ObservesProperty(() => SelectedItems.Count);

            RenameItem = new AsyncAutoCommand <SolutionItemViewModel>(async vm =>
            {
                if (vm.Item is IRenameableSolutionItem renameable)
                {
                    var newName = await inputBoxService.GetString("Rename", "Please provide a new name", vm.Name);
                    if (newName != null)
                    {
                        if (newName.Length < 3)
                        {
                            await messageBoxService.ShowDialog(new MessageBoxFactory <bool>()
                                                               .SetTitle("Rename")
                                                               .SetMainInstruction("Name too short")
                                                               .SetContent("The name can't be shorter than 3 characters")
                                                               .SetIcon(MessageBoxIcon.Warning)
                                                               .WithOkButton(true)
                                                               .Build());
                            return;
                        }
                        renameable.Rename(newName);
                        solutionManager.Refresh(vm.Item);
                    }
                }
            }, o => o is SolutionItemViewModel vm && vm.Item is IRenameableSolutionItem);

            SelectedItemChangedCommand = new DelegateCommand <SolutionItemViewModel>(ob => { selected = ob; });

            RequestOpenItem = new DelegateCommand <SolutionItemViewModel>(item =>
            {
                if (item != null && !item.IsContainer)
                {
                    this.ea.GetEvent <EventRequestOpenItem>().Publish(item.Item);
                }
            });

            GenerateSQL = new DelegateCommand <SolutionItemViewModel>(vm =>
            {
                if (vm != null)
                {
                    solutionSqlService.OpenDocumentWithSqlFor(vm.Item);
                }
            }, vm => vm != null);

            UpdateDatabase = new DelegateCommand <SolutionItemViewModel>(vm =>
            {
                if (vm != null)
                {
                    solutionTasksService.SaveSolutionToDatabaseTask(vm.Item);
                }
            }, vm => vm != null && solutionTasksService.CanSaveToDatabase);

            ExportToServer = new DelegateCommand <SolutionItemViewModel>(vm =>
            {
                if (vm != null)
                {
                    solutionTasksService.SaveAndReloadSolutionTask(vm.Item);
                }
            }, vm => vm != null && solutionTasksService.CanSaveAndReloadRemotely);

            ExportToServerItem = new DelegateCommand <object>(item =>
            {
                if (item is SolutionItemViewModel si)
                {
                    solutionTasksService.SaveAndReloadSolutionTask(si.Item);
                }
            }, item => solutionTasksService.CanSaveAndReloadRemotely);
        }