private async Task SaveBuildAs(BuildViewModel vm)
        {
            var build = vm.Build;
            var name  = await _dialogCoordinator.ShowValidatingInputDialogAsync(this, L10n.Message("Save as"),
                                                                                L10n.Message("Enter the new name of the build"), build.Name, s => _buildValidator.ValidateNewBuildName(s, vm.Parent));

            if (string.IsNullOrWhiteSpace(name))
            {
                return;
            }
            var newBuild = build.DeepClone();

            newBuild.Name = name;
            var newVm = new BuildViewModel(newBuild, Filter);

            var builds = vm.Parent.Children;

            if (build.CanRevert)
            {
                // The original build exists in the file system.
                build.RevertChanges();
                builds.Insert(builds.IndexOf(vm), newVm);
            }
            else
            {
                // The original build does not exist in the file system
                // It will be replaced by the new one.
                var i = builds.IndexOf(vm);
                builds.RemoveAt(i);
                builds.Insert(i, newVm);
            }

            CurrentBuild = newVm;
            await SaveBuild(newVm);
        }
        private async Task SaveBuild(BuildViewModel build)
        {
            var poeBuild = build.Build;

            if (!poeBuild.CanRevert && poeBuild.IsDirty)
            {
                // Build was created in this program run and was not yet saved.
                // Thus it needs a name.
                var name = await _dialogCoordinator.ShowValidatingInputDialogAsync(this,
                                                                                   L10n.Message("Saving new Build"),
                                                                                   L10n.Message("Enter the name of the build."),
                                                                                   poeBuild.Name,
                                                                                   s => _buildValidator.ValidateExistingFileName(s, build));

                if (string.IsNullOrEmpty(name))
                {
                    return;
                }
                poeBuild.Name = name;
            }
            poeBuild.LastUpdated = DateTime.Now;
            await SaveBuildToFile(build);

            // Save parent folder to retain ordering information when renaming
            await SaveBuildToFile(build.Parent);
        }
        public void NewBuild(IBuildFolderViewModel folder)
        {
            var name = Util.FindDistinctName(SerializationConstants.DefaultBuildName,
                                             folder.Children.Select(b => b.Build.Name));
            var build = new BuildViewModel(new PoEBuild {
                Name = name
            }, Filter);

            folder.Children.Add(build);
            CurrentBuild = build;
        }
        private async Task ImportCurrentFromClipboard()
        {
            var pasted = await PasteFromClipboard(BuildRoot);

            if (pasted == null)
            {
                return;
            }
            var build = new BuildViewModel(pasted, Filter);

            BuildRoot.Children.Add(build);
            CurrentBuild = build;
        }
        private async Task Paste(IBuildViewModel target)
        {
            var             targetFolder = target as IBuildFolderViewModel ?? target.Parent;
            IBuildViewModel pasted;

            if (CanPasteFromClipboard() && !CanPasteNonClipboard(target))
            {
                var b = await PasteFromClipboard(BuildRoot);

                if (b == null)
                {
                    return;
                }
                pasted = new BuildViewModel(b, Filter);
            }
            else if (_clipboardIsCopy)
            {
                if (!(_buildClipboard.Build is PoEBuild oldBuild))
                {
                    throw new InvalidOperationException("Can only copy builds, not folders.");
                }
                var newName  = Util.FindDistinctName(oldBuild.Name, targetFolder.Children.Select(b => b.Build.Name));
                var newBuild = PoEBuild.CreateNotRevertableCopy(oldBuild, newName);
                pasted = new BuildViewModel(newBuild, Filter);
            }
            else
            {
                pasted          = _buildClipboard;
                _buildClipboard = null;
            }
            targetFolder.Children.Add(pasted);

            // Folders and non-dirty builds need to be saved to create the new file.
            var build = pasted.Build as PoEBuild;

            if (build == null || !build.IsDirty)
            {
                await SaveBuildToFile(pasted);
            }
        }
        private async Task OpenBuild(BuildViewModel build)
        {
            if (build != CurrentBuild)
            {
                CurrentBuild = build;
                return;
            }
            if (!build.Build.IsDirty || !build.Build.CanRevert)
            {
                return;
            }

            var result = await _dialogCoordinator.ShowQuestionAsync(this,
                                                                    L10n.Message("This build is currently opened but has unsaved changes.\n")
                                                                    + L10n.Message("Do you want to discard all changes made to it since your last save?"),
                                                                    title : L10n.Message("Discard changes?"));

            if (result == MessageBoxResult.Yes)
            {
                CurrentBuild.Build.RevertChanges();
            }
        }