// Add code to be executed when game is preparing to be started.
        public override void OnGameStopped(OnGameStoppedEventArgs args)
        {
            try
            {
                var TaskGameStopped = Task.Run(() =>
                {
                    try
                    {
                        GameSettings gameSettings = PluginDatabase.GetGameSettings(args.Game.Id);
                        if (gameSettings != null)
                        {
                            PluginDatabase.SetDataFromSettings(gameSettings);
                        }
                    }
                    catch (Exception ex)
                    {
                        Common.LogError(ex, false, true, PluginDatabase.PluginName);
                    }

                    if (args.Game.Id == PluginDatabase.GameContext.Id)
                    {
                        PluginDatabase.SetThemesResources(PluginDatabase.GameContext);
                    }
                });
            }
            catch (Exception ex)
            {
                Common.LogError(ex, false, true, PluginDatabase.PluginName);
            }
        }
        public override void OnGameSelected(OnGameSelectedEventArgs args)
        {
            try
            {
                if (args.NewValue?.Count == 1 && PluginDatabase.IsLoaded)
                {
                    PluginDatabase.GameContext = args.NewValue[0];
                    PluginDatabase.SetThemesResources(PluginDatabase.GameContext);
                }
                else
                {
                    Task.Run(() =>
                    {
                        System.Threading.SpinWait.SpinUntil(() => PluginDatabase.IsLoaded, -1);

                        Application.Current.Dispatcher.BeginInvoke((Action) delegate
                        {
                            if (args.NewValue?.Count == 1)
                            {
                                PluginDatabase.GameContext = args.NewValue[0];
                                PluginDatabase.SetThemesResources(PluginDatabase.GameContext);
                            }
                        });
                    });
                }
            }
            catch (Exception ex)
            {
                Common.LogError(ex, false, true, PluginDatabase.PluginName);
            }
        }
        // To add new game menu items override GetGameMenuItems
        public override IEnumerable <GameMenuItem> GetGameMenuItems(GetGameMenuItemsArgs args)
        {
            var GameMenu = args.Games.First();

            List <GameMenuItem> gameMenuItems = new List <GameMenuItem>();

            if (PluginSettings.Settings.EnableBackgroundImage)
            {
                gameMenuItems.Add(new GameMenuItem
                {
                    // Manage game background
                    MenuSection = resources.GetString("LOCBc"),
                    Description = resources.GetString("LOCBcManageBackground"),
                    Action      = (gameMenuItem) =>
                    {
                        var ViewExtension      = new ImagesManager(PlayniteApi, PluginDatabase.Get(GameMenu), false);
                        Window windowExtension = PlayniteUiHelper.CreateExtensionWindow(PlayniteApi, resources.GetString("LOCBc") + " - " + resources.GetString("LOCGameBackgroundTitle"), ViewExtension);
                        windowExtension.ShowDialog();
                    }
                });
            }

            if (PluginSettings.Settings.EnableCoverImage)
            {
                gameMenuItems.Add(new GameMenuItem
                {
                    // Manage game cover
                    MenuSection = resources.GetString("LOCBc"),
                    Description = resources.GetString("LOCBcManageCover"),
                    Action      = (gameMenuItem) =>
                    {
                        var ViewExtension      = new ImagesManager(PlayniteApi, PluginDatabase.Get(GameMenu), true);
                        Window windowExtension = PlayniteUiHelper.CreateExtensionWindow(PlayniteApi, resources.GetString("LOCBc") + " - " + resources.GetString("LOCGameCoverImageTitle"), ViewExtension);
                        windowExtension.ShowDialog();
                    }
                });
            }

#if DEBUG
            gameMenuItems.Add(new GameMenuItem
            {
                MenuSection = resources.GetString("LOCBc"),
                Description = "-"
            });
            gameMenuItems.Add(new GameMenuItem
            {
                MenuSection = resources.GetString("LOCBc"),
                Description = "Test",
                Action      = (mainMenuItem) =>
                {
                }
            });
#endif

            return(gameMenuItems);
        }
 /// <summary>
 /// Get Config and Achivements for a game.
 /// </summary>
 /// <param name="id"></param>
 /// <returns></returns>
 public GameAchievements Get(Guid id)
 {
     if (PluginDatabase.TryGetValue(id, out var item))
     {
         return(item);
     }
     else
     {
         return(null);
     }
 }
        /// <summary>
        /// Initialize database / create directory.
        /// </summary>
        /// <param name="PlayniteApi"></param>
        /// <param name="PluginUserDataPath"></param>
        public void Initialize()
        {
            ListErrors = new CumulErrors();

            Parallel.ForEach(Directory.EnumerateFiles(PluginDatabasePath, "*.json"), (objectFile) =>
            {
                try
                {
                    // Get game achievements.
                    Guid gameId = Guid.Parse(objectFile.Replace(PluginDatabasePath, "").Replace(".json", ""));

                    bool IncludeGame = true;
                    if (!Settings.IncludeHiddenGames)
                    {
                        Game tempGame = PlayniteApi.Database.Games.Get(gameId);

                        if (tempGame != null)
                        {
                            IncludeGame = !tempGame.Hidden;
                        }
                        else
                        {
                            IncludeGame = false;
                            logger.Info($"SuccessStory - {gameId} is null");
                        }
                    }

                    if (IncludeGame)
                    {
                        GameAchievements objGameAchievements = JsonConvert.DeserializeObject <GameAchievements>(File.ReadAllText(objectFile));

                        // Set game achievements in database.
                        PluginDatabase.TryAdd(gameId, objGameAchievements);
                    }
                }
                catch (Exception ex)
                {
                    Common.LogError(ex, "SuccessStory", $"Failed to load item from { objectFile}");
                    ListErrors.Add($"SuccessStory - Failed to load item from {objectFile}");
                }
            });

            if (ListErrors.Get() != "")
            {
                PlayniteApi.Dialogs.ShowErrorMessage(ListErrors.Get(), "SuccessStory errors");
            }

            ListErrors = new CumulErrors();
        }
 private static void EnsurePackageDataIsEmpty(PluginDatabase db, string testPackageA)
 {
     if (String.IsNullOrEmpty(db.GetRequestToken(testPackageA)))
     {
         throw new Exception("invalid request token");
     }
     if (db.GetAccessToken(testPackageA) != null)
     {
         throw new Exception("invalid access token!");
     }
     if (db.GetPluginScopes(testPackageA).Count > 0)
     {
         throw new Exception("Unexpected scopes!");
     }
 }
 public override void OnGameSelected(OnGameSelectedEventArgs args)
 {
     try
     {
         if (args.NewValue != null && args.NewValue.Count == 1)
         {
             PluginDatabase.GameContext = args.NewValue[0];
             PluginDatabase.SetThemesResources(PluginDatabase.GameContext);
         }
     }
     catch (Exception ex)
     {
         Common.LogError(ex, false, true, "BackgroundChanger");
     }
 }
        /// <summary>
        /// Remove game achievements in database for a game.
        /// </summary>
        /// <param name="GameRemoved"></param>
        public void Remove(Game GameRemoved)
        {
            Guid   GameId = GameRemoved.Id;
            string PluginDatabaseGamePath = PluginDatabasePath + GameId.ToString() + ".json";

            try
            {
                if (File.Exists(PluginDatabaseGamePath))
                {
                    File.Delete(PluginDatabaseGamePath);
                    PluginDatabase.TryRemove(GameRemoved.Id, out var value);
                }
            }
            catch
            {
            }
        }
 public void Filter(bool ignore = true)
 {
     if (_settings.EnableRetroAchievementsView && !ignore)
     {
         if (_isRetroachievements)
         {
             var a = PluginDatabase.Where(x => IsEmulatedGame(x));
             var b = a.ToDictionary(x => x.Key, x => x.Value);
             PluginDatabase = ToConcurrent(b);
         }
         else
         {
             var a = PluginDatabase.Where(x => !IsEmulatedGame(x));
             var b = a.ToDictionary(x => x.Key, x => x.Value);
             PluginDatabase = ToConcurrent(b);
         }
     }
 }
 private void EnsurePackageHasUnacceptedScope(PluginDatabase db, string plugin, string scope)
 {
     if (String.IsNullOrEmpty(db.GetRequestToken(plugin)))
     {
         throw new Exception("invalid request token");
     }
     if (db.GetAccessToken(plugin) != null)
     {
         throw new Exception("invalid access token!");
     }
     if (db.GetPluginScopes(plugin).Count != 1)
     {
         throw new Exception("Unexpected scopes!");
     }
     if (db.GetPluginScopes(plugin).First() != scope)
     {
         throw new Exception("Unexpected scope in db!");
     }
 }
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);

            // Set our view from the "main" layout resource
            SetContentView(Resource.Layout.Main);

            // Get our button from the layout resource,
            // and attach an event to it
            Button button = FindViewById <Button>(Resource.Id.MyButton);

            button.Click += delegate { PluginHost.TriggerRequests(this); };

            FindViewById <Button>(Resource.Id.managePluginsButton).Click += delegate(object sender, EventArgs args)
            {
                StartActivity(new Intent(this, typeof(PluginListActivity)));
            };
            FindViewById <Button>(Resource.Id.entryviewButton).Click += delegate
            {
                StartActivity(new Intent(this, typeof(EntryActivity)));
            };

            FindViewById <Button>(Resource.Id.testDbButton).Click += delegate
            {
                string message = "ok. ";
                try
                {
                    Stopwatch sw = new Stopwatch();
                    sw.Start();
                    PluginDatabase db = new PluginDatabase(this);
                    db.Clear();


                    if (db.GetAllPluginPackages().Count() != 0)
                    {
                        throw new Exception("db not empty!");
                    }

                    const string testPackageA = "test.package.a";
                    const string testPackageB = "test.package.b";
                    db.ClearPlugin(testPackageA);
                    db.ClearPlugin(testPackageB);
                    EnsurePackageDataIsEmpty(db, testPackageA);
                    EnsurePackageDataIsEmpty(db, testPackageB);

                    string[] requestedScopes =
                    {
                        Strings.ScopeDatabaseActions
                    };
                    db.StorePlugin(testPackageA, null, requestedScopes);
                    EnsurePackageDataIsEmpty(db, testPackageB);
                    EnsurePackageDataIsEmpty(new PluginDatabase(this), testPackageB);
                    db.StorePlugin(testPackageB, null, requestedScopes);
                    EnsurePackageHasUnacceptedScope(db, testPackageA, Strings.ScopeDatabaseActions);
                    EnsurePackageHasUnacceptedScope(db, testPackageB, Strings.ScopeDatabaseActions);
                    EnsurePackageHasUnacceptedScope(new PluginDatabase(this), testPackageA, Strings.ScopeDatabaseActions);

                    if (db.GetAllPluginPackages().Count() != 2)
                    {
                        throw new Exception("wrong count of plugins");
                    }
                    if (db.GetPluginsWithAcceptedScope(Strings.ScopeDatabaseActions).Any())
                    {
                        throw new Exception("wrong count of accepted plugins");
                    }
                    if (new PluginDatabase(this).GetPluginsWithAcceptedScope(Strings.ScopeDatabaseActions).Any())
                    {
                        throw new Exception("wrong count of accepted plugins");
                    }

                    db.SetEnabled(testPackageA, true);
                    if (db.GetPluginsWithAcceptedScope(Strings.ScopeDatabaseActions).Single() != testPackageA)
                    {
                        throw new Exception("wrong plugin");
                    }
                    if (new PluginDatabase(this).GetPluginsWithAcceptedScope(Strings.ScopeDatabaseActions).Single() != testPackageA)
                    {
                        throw new Exception("wrong plugin");
                    }
                    if (db.GetPluginsWithAcceptedScope("somescope").Any())
                    {
                        throw new Exception("wrong count of accepted plugins");
                    }
                    var accessTokenA = db.GetAccessToken(testPackageA);
                    if (String.IsNullOrEmpty(accessTokenA))
                    {
                        throw new Exception("expected access token!");
                    }
                    if (!db.IsEnabled(testPackageA))
                    {
                        throw new Exception("plugin not enabled!");
                    }
                    if (db.IsEnabled(testPackageB))
                    {
                        throw new Exception("plugin enabled!");
                    }
                    if (!db.IsValidAccessToken(testPackageA, accessTokenA, Strings.ScopeDatabaseActions))
                    {
                        throw new Exception("invalid token!");
                    }
                    db.SetEnabled(testPackageA, false);
                    if (db.IsValidAccessToken(testPackageA, accessTokenA, Strings.ScopeDatabaseActions))
                    {
                        throw new Exception("valid token?!");
                    }
                    if (db.GetPluginsWithAcceptedScope(Strings.ScopeDatabaseActions).Any())
                    {
                        throw new Exception("unexpected!");
                    }


                    new PluginDatabase(this).SetEnabled(testPackageB, true);
                    if (!db.IsEnabled(testPackageB))
                    {
                        throw new Exception("plugin not enabled!");
                    }

                    db.SetEnabled(testPackageA, true);
                    accessTokenA = db.GetAccessToken(testPackageA);

                    message += sw.ElapsedMilliseconds + "ms";

                    Stopwatch swQuery = new Stopwatch();
                    swQuery.Start();
                    int n = 3;
                    for (int i = 0; i < n; i++)
                    {
                        if (db.GetPluginsWithAcceptedScope(Strings.ScopeDatabaseActions).Count() != 2)
                        {
                            throw new Exception("wrong plugin");
                        }
                        if (!db.IsValidAccessToken(testPackageA, accessTokenA, Strings.ScopeDatabaseActions))
                        {
                            throw new Exception("invalid token");
                        }
                    }
                    message += "/ " + swQuery.ElapsedMilliseconds / (double)n / 2.0 + "ms for query";
                }
                catch (Exception exception)
                {
                    message = exception.ToString();
                }
                Toast.MakeText(this, message, ToastLength.Long).Show();
            };
        }
        // To add new main menu items override GetMainMenuItems
        public override IEnumerable <MainMenuItem> GetMainMenuItems(GetMainMenuItemsArgs args)
        {
            string MenuInExtensions = string.Empty;

            if (PluginSettings.Settings.MenuInExtensions)
            {
                MenuInExtensions = "@";
            }

            List <MainMenuItem> mainMenuItems = new List <MainMenuItem>();

            mainMenuItems.Add(new MainMenuItem
            {
                MenuSection = MenuInExtensions + resources.GetString("LOCSsv"),
                Description = resources.GetString("LOCCommonRefreshAllData"),
                Action      = (mainMenuItem) =>
                {
                    PluginDatabase.RefreshDataAll();
                }
            });

            if (PluginDatabase.PluginSettings.Settings.EnableTag)
            {
                mainMenuItems.Add(new MainMenuItem
                {
                    MenuSection = MenuInExtensions + resources.GetString("LOCSsv"),
                    Description = "-"
                });

                // Add tag for selected game in database if data exists
                mainMenuItems.Add(new MainMenuItem
                {
                    MenuSection = MenuInExtensions + resources.GetString("LOCSsv"),
                    Description = resources.GetString("LOCCommonAddTPlugin"),
                    Action      = (mainMenuItem) =>
                    {
                        PluginDatabase.AddTagSelectData();
                    }
                });
                // Add tag for all games
                mainMenuItems.Add(new MainMenuItem
                {
                    MenuSection = MenuInExtensions + resources.GetString("LOCSsv"),
                    Description = resources.GetString("LOCCommonAddAllTags"),
                    Action      = (mainMenuItem) =>
                    {
                        PluginDatabase.AddTagAllGame();
                    }
                });
                // Remove tag for all game in database
                mainMenuItems.Add(new MainMenuItem
                {
                    MenuSection = MenuInExtensions + resources.GetString("LOCSsv"),
                    Description = resources.GetString("LOCCommonRemoveAllTags"),
                    Action      = (mainMenuItem) =>
                    {
                        PluginDatabase.RemoveTagAllGame();
                    }
                });
            }

            if (PluginDatabase.PluginSettings.Settings.EnableFolderToSave)
            {
                mainMenuItems.Add(new MainMenuItem
                {
                    MenuSection = MenuInExtensions + resources.GetString("LOCSsv"),
                    Description = "-"
                });

                mainMenuItems.Add(new MainMenuItem
                {
                    MenuSection = MenuInExtensions + resources.GetString("LOCSsv"),
                    Description = resources.GetString("LOCSsvMoveToSave"),
                    Action      = (gameMenuItem) =>
                    {
                        var dialogResult = PlayniteApi.Dialogs.ShowMessage(resources.GetString("LOCSsvWarningToMove"), resources.GetString("LOCSsv"), MessageBoxButton.YesNo);
                        if (dialogResult == MessageBoxResult.Yes)
                        {
                            if (PluginSettings.Settings.FolderToSave.IsNullOrEmpty() || PluginSettings.Settings.FileSavePattern.IsNullOrEmpty())
                            {
                                logger.Error("No settings to use folder to save");
                                PlayniteApi.Notifications.Add(new NotificationMessage(
                                                                  $"{PluginDatabase.PluginName}-MoveToFolderToSave-Errors",
                                                                  $"{PluginDatabase.PluginName}\r\n" + resources.GetString("LOCSsvMoveToFolderToSaveError"),
                                                                  NotificationType.Error,
                                                                  () => this.OpenSettingsView()
                                                                  ));
                            }
                            else
                            {
                                PluginDatabase.MoveToFolderToSaveAll();
                            }
                        }
                    }
                });
            }


#if DEBUG
            mainMenuItems.Add(new MainMenuItem
            {
                MenuSection = MenuInExtensions + resources.GetString("LOCSsv"),
                Description = "-"
            });
            mainMenuItems.Add(new MainMenuItem
            {
                MenuSection = MenuInExtensions + resources.GetString("LOCSsv"),
                Description = "Test",
                Action      = (mainMenuItem) => { }
            });
#endif

            return(mainMenuItems);
        }
        // To add new game menu items override GetGameMenuItems
        public override IEnumerable <GameMenuItem> GetGameMenuItems(GetGameMenuItemsArgs args)
        {
            Game            GameMenu        = args.Games.First();
            List <Guid>     Ids             = args.Games.Select(x => x.Id).ToList();
            GameScreenshots gameScreenshots = PluginDatabase.Get(GameMenu);

            List <GameMenuItem> gameMenuItems = new List <GameMenuItem>();

            if (gameScreenshots.HasData)
            {
                gameMenuItems.Add(new GameMenuItem
                {
                    // Delete & download localizations data for the selected game
                    MenuSection = resources.GetString("LOCSsv"),
                    Description = resources.GetString("LOCSsvViewScreenshots"),
                    Action      = (gameMenuItem) =>
                    {
                        WindowOptions windowOptions = new WindowOptions
                        {
                            ShowMinimizeButton = false,
                            ShowMaximizeButton = true,
                            ShowCloseButton    = true
                        };

                        var ViewExtension          = new SsvScreenshotsView(PluginDatabase.GameContext);
                        Window windowExtension     = PlayniteUiHelper.CreateExtensionWindow(PlayniteApi, resources.GetString("LOCSsvTitle"), ViewExtension, windowOptions);
                        windowExtension.ResizeMode = ResizeMode.CanResize;
                        windowExtension.ShowDialog();
                    }
                });

                if (gameScreenshots.ScreenshotsFolders != null && gameScreenshots.ScreenshotsFolders.Count != 0 && gameScreenshots.FoldersExist)
                {
                    gameMenuItems.Add(new GameMenuItem
                    {
                        // Open directory
                        MenuSection = resources.GetString("LOCSsv"),
                        Description = resources.GetString("LOCSsvOpenScreenshotsDirectory"),
                        Action      = (gameMenuItem) =>
                        {
                            foreach (string Folder in gameScreenshots.ScreenshotsFolders)
                            {
                                Process.Start(Folder);
                            }
                        }
                    });
                }

                if (gameScreenshots.Items.Count > 0 && PluginDatabase.PluginSettings.Settings.EnableFolderToSave)
                {
                    gameMenuItems.Add(new GameMenuItem
                    {
                        MenuSection = resources.GetString("LOCSsv"),
                        Description = resources.GetString("LOCSsvMoveToSave"),
                        Action      = (gameMenuItem) =>
                        {
                            if (Ids.Count == 1)
                            {
                                PluginDatabase.MoveToFolderToSave(GameMenu);
                            }
                            else
                            {
                                PluginDatabase.MoveToFolderToSave(Ids);
                            }
                        }
                    });
                }

                if (gameScreenshots.Items.Count > 0)
                {
                    gameMenuItems.Add(new GameMenuItem
                    {
                        MenuSection = resources.GetString("LOCSsv"),
                        Description = resources.GetString("LOCSsvConvertToJPG"),
                        Action      = (gameMenuItem) =>
                        {
                            GlobalProgressOptions globalProgressOptions = new GlobalProgressOptions(
                                $"{PluginDatabase.PluginName} - {resources.GetString("LOCCommonConverting")}",
                                true
                                );
                            globalProgressOptions.IsIndeterminate = Ids.Count == 1;

                            PlayniteApi.Dialogs.ActivateGlobalProgress((activateGlobalProgress) =>
                            {
                                Stopwatch stopWatch = new Stopwatch();
                                stopWatch.Start();

                                string CancelText = string.Empty;
                                if (Ids.Count > 1)
                                {
                                    activateGlobalProgress.ProgressMaxValue = Ids.Count;
                                }

                                try
                                {
                                    Ids.ForEach(y =>
                                    {
                                        GameScreenshots data = PluginDatabase.Get(y);
                                        if (data.HasData)
                                        {
                                            bool HasConvert = false;
                                            data.Items.ForEach(x =>
                                            {
                                                if (activateGlobalProgress.CancelToken.IsCancellationRequested)
                                                {
                                                    CancelText = " canceled";
                                                    return;
                                                }

                                                if (!x.IsVideo)
                                                {
                                                    string oldFile = x.FileName;
                                                    string newFile = ImageTools.ConvertToJpg(oldFile, PluginDatabase.PluginSettings.Settings.JpgQuality);

                                                    if (!newFile.IsNullOrEmpty())
                                                    {
                                                        DateTime dt = File.GetLastWriteTime(oldFile);
                                                        File.SetLastWriteTime(newFile, dt);
                                                        FileSystem.DeleteFileSafe(oldFile);
                                                        HasConvert = true;
                                                    }
                                                }
                                            });

                                            if (HasConvert)
                                            {
                                                GameSettings gameSettings = PluginDatabase.GetGameSettings(y);
                                                if (gameSettings != null)
                                                {
                                                    PluginDatabase.SetDataFromSettings(gameSettings);
                                                }
                                            }

                                            if (activateGlobalProgress.CancelToken.IsCancellationRequested)
                                            {
                                                CancelText = " canceled";
                                                return;
                                            }

                                            if (Ids.Count > 1)
                                            {
                                                activateGlobalProgress.CurrentProgressValue++;
                                            }
                                        }
                                    });
                                }
                                catch (Exception ex)
                                {
                                    Common.LogError(ex, false, true, PluginDatabase.PluginName);
                                }

                                stopWatch.Stop();
                                TimeSpan ts = stopWatch.Elapsed;
                                logger.Info($"Task RefreshData(){CancelText} - {string.Format("{0:00}:{1:00}.{2:00}", ts.Minutes, ts.Seconds, ts.Milliseconds / 10)} for {activateGlobalProgress.CurrentProgressValue}/{Ids.Count} items");
                            }, globalProgressOptions);
                        }
                    });
                }

                gameMenuItems.Add(new GameMenuItem
                {
                    MenuSection = resources.GetString("LOCSsv"),
                    Description = "-"
                });
            }

            gameMenuItems.Add(new GameMenuItem
            {
                // Refresh data
                MenuSection = resources.GetString("LOCSsv"),
                Description = resources.GetString("LOCCommonRefreshGameData"),
                Action      = (gameMenuItem) =>
                {
                    if (Ids.Count == 1)
                    {
                        PluginDatabase.RefreshData(GameMenu);
                    }
                    else
                    {
                        PluginDatabase.RefreshData(Ids);
                    }
                }
            });

#if DEBUG
            gameMenuItems.Add(new GameMenuItem
            {
                MenuSection = resources.GetString("LOCSsv"),
                Description = "-"
            });
            gameMenuItems.Add(new GameMenuItem
            {
                MenuSection = resources.GetString("LOCSsv"),
                Description = "Test",
                Action      = (mainMenuItem) =>
                {
                }
            });
#endif

            return(gameMenuItems);
        }