protected void SetupPlaylistsWithSongs(int playlistCount, int songCount)
        {
            BeatSaberQuestomConfig config = null;

            using (var fp = GetProvider())
            {
                var q = GetQaeConfig(fp);
                using (QuestomAssetsEngine qae = new QuestomAssetsEngine(q))
                {
                    config = qae.GetCurrentConfig();

                    for (int p = 0; p < playlistCount; p++)
                    {
                        var playlist = new BeatSaberPlaylist()
                        {
                            PlaylistID   = string.Format(PlaylistIDFormat, p),
                            PlaylistName = string.Format(PlaylistNameFormat, p)
                        };
                        for (int i = 0; i < songCount; i++)
                        {
                            var song = new BeatSaberSong()
                            {
                                SongID         = string.Format(SongIDFormat, p, i),
                                CustomSongPath = MakeTestSongDir()
                            };

                            playlist.SongList.Add(song);
                        }
                        config.Playlists.Add(playlist);
                    }
                    qae.UpdateConfig(config);
                    qae.Save();
                }
            }
        }
        public void BasicDeleteSongOpWorks()
        {
            SetupPlaylistsWithSongs(5, 5);
            using (var fp = GetProvider())
            {
                var q = GetQaeConfig(fp);
                using (QuestomAssetsEngine qae = new QuestomAssetsEngine(q))
                {
                    bool calledStatusChangeStarted  = false;
                    bool calledStatusChangeComplete = false;
                    var  deleteSongOp = new DeleteSongOp(string.Format(SongIDFormat, 2, 2));
                    qae.OpManager.OpStatusChanged += (sender, op) =>
                    {
                        if (op.Status == OpStatus.Started)
                        {
                            calledStatusChangeStarted = true;
                        }
                        if (op.Status == OpStatus.Complete)
                        {
                            calledStatusChangeComplete = true;
                        }
                    };
                    qae.OpManager.QueueOp(deleteSongOp);
                    while (qae.OpManager.IsProcessing)
                    {
                        System.Threading.Thread.Sleep(100);
                    }
                    Assert.IsTrue(calledStatusChangeStarted, "Did not get OpStatusChanged event for status Started!");
                    Assert.IsTrue(calledStatusChangeComplete, "Did not get OpStatusChanged event for status Complete!");
                    qae.Save();
                }
                using (QuestomAssetsEngine qae = new QuestomAssetsEngine(q))
                {
                    var cfg = qae.GetCurrentConfig();

                    Assert.AreEqual(5, cfg.Playlists.Count, "Playlist count is incorrect after song delete");
                    Assert.AreEqual(5, cfg.Playlists[0].SongList.Count, "Song came out of the wrong playlist");
                    Assert.AreEqual(5, cfg.Playlists[1].SongList.Count, "Song came out of the wrong playlist");
                    Assert.AreEqual(4, cfg.Playlists[2].SongList.Count, "Song did not come out of the right playlist");
                    Assert.AreEqual(5, cfg.Playlists[3].SongList.Count, "Song came out of the wrong playlist");
                    Assert.AreEqual(5, cfg.Playlists[4].SongList.Count, "Song came out of the wrong playlist");

                    var pl = cfg.Playlists[2];
                    Assert.IsFalse(pl.SongList.Any(x => x.SongID == string.Format(SongIDFormat, 2, 2)), "Expected target song to be deleted.");

                    //todo: more tests on this
                }
                Assert.Pass();
            }
        }
        public void BasicAddNewSongOpWorks()
        {
            SetupPlaylistsWithSongs(1, 1);

            using (var fp = GetProvider())
            {
                var q = GetQaeConfig(fp);
                using (QuestomAssetsEngine qae = new QuestomAssetsEngine(q))
                {
                    var song = new BeatSaberSong()
                    {
                        SongID         = "TESTSONG2",
                        CustomSongPath = MakeTestSongDir()
                    };
                    bool calledStatusChangeStarted  = false;
                    bool calledStatusChangeComplete = false;
                    var  newSongOp = new AddNewSongToPlaylistOp(song, "someplaylist0", false);
                    qae.OpManager.OpStatusChanged += (sender, op) =>
                    {
                        if (op.Status == OpStatus.Started)
                        {
                            calledStatusChangeStarted = true;
                        }
                        if (op.Status == OpStatus.Complete)
                        {
                            calledStatusChangeComplete = true;
                        }
                    };
                    qae.OpManager.QueueOp(newSongOp);
                    while (qae.OpManager.IsProcessing)
                    {
                        System.Threading.Thread.Sleep(100);
                    }
                    //give it an extra bit of time to make sure events get fired
                    System.Threading.Thread.Sleep(200);
                    Assert.IsTrue(calledStatusChangeStarted, "Did not get OpStatusChanged event for status Started!");
                    Assert.IsTrue(calledStatusChangeComplete, "Did not get OpStatusChanged event for status Complete!");
                    qae.Save();
                }
                using (QuestomAssetsEngine qae = new QuestomAssetsEngine(q))
                {
                    var cfg = qae.GetCurrentConfig();

                    var song = cfg.Playlists.FirstOrDefault(x => x.PlaylistID == "someplaylist0")?.SongList?.FirstOrDefault(x => x.SongID == "TESTSONG2");
                    Assert.NotNull(song, "Couldn't find the song the op was supposed to add!");
                    //todo: more tests on this
                }
                Assert.Pass();
            }
        }
        public void BasicAddPlaylistOpWorks()
        {
            using (var fp = GetProvider())
            {
                var q = GetQaeConfig(fp);
                using (QuestomAssetsEngine qae = new QuestomAssetsEngine(q))
                {
                    var newPlaylist = new BeatSaberPlaylist()
                    {
                        PlaylistID   = "TESTPLAYLIST1",
                        PlaylistName = "Test Playlist 1"
                    };

                    bool calledStatusChangeStarted  = false;
                    bool calledStatusChangeComplete = false;
                    var  newSongOp = new AddOrUpdatePlaylistOp(newPlaylist);
                    qae.OpManager.OpStatusChanged += (sender, op) =>
                    {
                        if (op.Status == OpStatus.Started)
                        {
                            calledStatusChangeStarted = true;
                        }
                        if (op.Status == OpStatus.Complete)
                        {
                            calledStatusChangeComplete = true;
                        }
                    };
                    qae.OpManager.QueueOp(newSongOp);
                    while (qae.OpManager.IsProcessing)
                    {
                        System.Threading.Thread.Sleep(100);
                    }
                    Assert.IsTrue(calledStatusChangeStarted, "Did not get OpStatusChanged event for status Started!");
                    Assert.IsTrue(calledStatusChangeComplete, "Did not get OpStatusChanged event for status Complete!");
                    qae.Save();
                }
                using (QuestomAssetsEngine qae = new QuestomAssetsEngine(q))
                {
                    var cfg = qae.GetCurrentConfig();

                    var playlist = cfg.Playlists.FirstOrDefault(x => x.PlaylistID == "TESTPLAYLIST1");
                    Assert.NotNull(playlist, "Couldn't find the song the op was supposed to add!");
                    Assert.AreEqual("Test Playlist 1", playlist.PlaylistName, "Playlist name was not set correctly!");
                    //todo: more tests on this
                }
                Assert.Pass();
            }
        }
        public void MovesSongToNewPlaylist()
        {
            SetupPlaylistsWithSongs(2, 2);
            BeatSaberQuestomConfig oldConfig = null;

            using (var fp = GetProvider())
            {
                var q = GetQaeConfig(fp);
                using (QuestomAssetsEngine qae = new QuestomAssetsEngine(q))
                {
                    oldConfig = qae.GetCurrentConfig();
                    var config = CopyIDs(oldConfig);
                    var song   = config.Playlists[0].SongList[0];
                    config.Playlists[1].SongList.Add(song);
                    config.Playlists[0].SongList.Remove(song);
                    qae.UpdateConfig(config);
                    qae.Save();
                }
            }
            using (var fp = GetProvider())
            {
                var q = GetQaeConfig(fp);
                using (QuestomAssetsEngine qae = new QuestomAssetsEngine(q))
                {
                    var testConfig = qae.GetCurrentConfig();
                    Assert.AreEqual(2, testConfig.Playlists.Count);
                    Assert.AreEqual(1, testConfig.Playlists[0].SongList.Count());
                    Assert.AreEqual(3, testConfig.Playlists[1].SongList.Count());
                    Assert.AreEqual(string.Format(SongIDFormat, 0, 1), testConfig.Playlists[0].SongList[0].SongID);
                    Assert.AreEqual(string.Format(SongIDFormat, 1, 0), testConfig.Playlists[1].SongList[0].SongID);
                    Assert.AreEqual(string.Format(SongIDFormat, 1, 1), testConfig.Playlists[1].SongList[1].SongID);
                    Assert.AreEqual(string.Format(SongIDFormat, 0, 0), testConfig.Playlists[1].SongList[2].SongID);
                    Assert.AreEqual(oldConfig.Playlists[0].PlaylistName, testConfig.Playlists[0].PlaylistName);
                    Assert.AreEqual(oldConfig.Playlists[1].PlaylistName, testConfig.Playlists[1].PlaylistName);
                }
            }
            Assert.Pass();
        }
        public void loadlots()
        {
            QuestomAssets.Utils.ImageUtils.Instance = new ImageUtilsWin();

            try
            {
                QaeConfig cfg2 = new QaeConfig()
                {
                    AssetsPath       = "Data",
                    RootFileProvider = new FolderFileProvider(@"C:\Users\VR\Desktop\platform-tools_r28.0.3-windows\perftest", false),
                    SongsPath        = "customsongs",
                    SongFileProvider = new FolderFileProvider(@"C:\Users\VR\Desktop\platform-tools_r28.0.3-windows\perftest", false)
                };

                var qae2    = new QuestomAssetsEngine(cfg2);
                var config  = qae2.GetCurrentConfig();
                var folders = GetCustomSongsFromPath(@"C:\Users\VR\Desktop\platform-tools_r28.0.3-windows\perftest\customsongs");
                if (folders.Count < 1)
                {
                    Log.LogErr("Request to reload songs folder, but didn't find any songs!");
                    //not found probably isn't the right response code for this, but meh

                    return;
                }
                Log.LogMsg($"Starting to reload custom songs from folders.  Found {folders.Count} folders to evaluate");
                //todo: probably don't just grab this one
                var playlist = config.Playlists.FirstOrDefault(x => x.PlaylistID == "CustomSongs");
                if (playlist == null)
                {
                    playlist = new BeatSaberPlaylist()
                    {
                        PlaylistID   = "CustomSongs",
                        PlaylistName = "Custom Songs"
                    };
                    config.Playlists.Add(playlist);
                }
                int addedCtr = 0;

                foreach (var folder in folders)
                {
                    string songId = folder.Replace("/", "");
                    songId = songId.Replace(" ", "");
                    if (config.Playlists.SelectMany(x => x.SongList).Any(x => x.SongID?.ToLower() == songId.ToLower()))
                    {
                        //SendStatusMessage($"Folder {folder} already loaded");
                        Log.LogMsg($"Custom song in folder {folder} appears to already be loaded, skipping it.");
                        continue;
                    }
                    //safety check to make sure we aren't importing one with the same ID as a beatsaber song.  It could be re-ID'ed, but this is a stopgap
                    if (BSConst.KnownLevelIDs.Contains(songId))
                    {
                        Log.LogErr($"Song in path {folder} would conflict with a built in songID and will be skipped");
                        continue;
                    }
                    // SendStatusMessage($"Adding song in {folder}");
                    Log.LogMsg($"Adding custom song in folder {folder} to playlist ID {playlist.PlaylistID}");
                    playlist.SongList.Add(new BeatSaberSong()
                    {
                        SongID         = songId,
                        CustomSongPath = Path.Combine(cfg2.SongsPath, folder)
                    });
                    addedCtr++;
                    //maybe limit how many
                    //if (addedCtr > 200)
                    //{
                    //    ShowToast("Too Many Songs", "That's too many at once.  After these finish and you 'Sync to Beat Saber', then try 'Reload Songs Folder' again to load more.", ToastType.Warning, 10);
                    //    break;
                    //}
                }
                if (addedCtr > 0)
                {
                    Log.LogMsg("Updating config with loaded song folders");

                    qae2.UpdateConfig(config);
                }
                qae2.Save();
            }
            finally
            {
            }
            QaeConfig cfg3 = new QaeConfig()
            {
                AssetsPath       = "Data",
                RootFileProvider = new FolderFileProvider(@"C:\Users\VR\Desktop\platform-tools_r28.0.3-windows\perftest\Data", false),
                SongsPath        = "customsongs",
                SongFileProvider = new FolderFileProvider(@"C:\Users\VR\Desktop\platform-tools_r28.0.3-windows\perftest\Data\customsongs", false)
            };

            var qae3 = new QuestomAssetsEngine(cfg3);

            Assert.Pass();
        }