<commit_before>﻿using Playnite.Controllers;
using Playnite.Input;
using Playnite.SDK;
using Playnite.Plugins;
using Playnite.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Diagnostics;
using Playnite.Database;
using Playnite.API;
using TheArtOfDev.HtmlRenderer;
using Playnite.Services;
using System.Windows.Input;
using System.Windows.Interop;
using System.Reflection;
using System.IO;
using Playnite.Common;
using System.ComponentModel;
using Playnite.Windows;
using Polly;
using System.Windows.Media;
using Playnite.SDK.Events;
using System.Windows.Threading;
using System.Net;
using Playnite.Common.Web;
using System.ServiceProcess;

namespace Playnite
{
    public abstract class PlayniteApplication : ObservableObject, IPlayniteApplication
    {
        private ILogger logger = LogManager.GetLogger();
        private const string instanceMuxet = "PlayniteInstaceMutex";
        private Mutex appMutex;
        private bool resourcesReleased = false;
        private PipeService pipeService;
        private PipeServer pipeServer;
        private XInputDevice xdevice;
        private System.Threading.Timer updateCheckTimer;
        private bool installingAddon = false;
        private AddonLoadError themeLoadError = AddonLoadError.None;
        private ThemeManifest customTheme;

        private bool isActive;
        public bool IsActive
        {
            get => isActive;
            set
            {
                isActive = value;
                OnPropertyChanged();
            }
        }

        public System.Version CurrentVersion
        {
            get => Updater.CurrentVersion;
        }

        public event EventHandler ExtensionsLoaded;
        public ApplicationMode Mode { get; }
        public IDialogsFactory Dialogs { get; set; }
        public PlayniteSettings AppSettings { get; set; }
        public GamesEditor GamesEditor { get; set; }
        public ExtensionFactory Extensions { get; set; }
        public GameDatabase Database { get; set; }
        public PlayniteAPI Api { get; set; }
        public GameControllerFactory Controllers { get; set; }
        public CmdLineOptions CmdLine { get; set; }
        public DpiScale DpiScale { get; set; } = new DpiScale(1, 1);
        public ComputerScreen CurrentScreen { get; set; } = Computer.GetPrimaryScreen();
        public DiscordManager Discord { get; set; }
        public SynchronizationContext SyncContext { get; private set; }
        public Action<PlayniteUriEventArgs> AppUriHandler { get; set; }
        public static Application CurrentNative { get; private set; }
        public static PlayniteApplication Current { get; private set; }
        public ServicesClient ServicesClient { get; private set; }
        public static bool SoundsEnabled { get; set; } = true;
        public MainViewModelBase MainModelBase { get; set; }
        public List<ExtensionInstallResult> ExtensionsInstallResult { get; set; }

        private ExtensionsStatusBinder extensionsStatusBinder = new ExtensionsStatusBinder();
        public ExtensionsStatusBinder ExtensionsStatusBinder { get => extensionsStatusBinder; set => SetValue(ref extensionsStatusBinder, value); }

        public PlayniteApplication()
        {
        }

        public PlayniteApplication(
            Func<Application> appInitializer,
            ApplicationMode mode,
            string defaultThemeName,
            CmdLineOptions cmdLine)
        {
            if (Current != null)
            {
                throw new Exception("Only one application instance is allowed.");
            }

            // TODO: remove after switch to .NET 5
            // Fixes various network issues on 2004+ Win10 if TLS 1.3 is forced via registry.
            if (Computer.IsTLS13SystemWideEnabled())
            {
                logger.Warn("System wide TLS 1.3 is enabled, forcing 1.2.");
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
            }

            CmdLine = cmdLine;
            Mode = mode;
            Current = this;

            if (!Debugger.IsAttached)
            {
                AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            }

            if (!CmdLine.MasterInstance)
            {
                if (CheckOtherInstances() || CmdLine.Shutdown)
                {
                    resourcesReleased = true;
                    Environment.Exit(0);
                    return;
                }
            }

            if (FileSystem.FileExists(PlaynitePaths.SafeStartupFlagFile))
            {
                if (MessageBox.Show(
                    "Playnite closed unexpectedly while starting. This is usually caused by 3rd party theme or extension. Do you want to start in safe mode with all 3rd party add-ons disabled?",
                    "Startup Error",
                    MessageBoxButton.YesNo,
                    MessageBoxImage.Warning) == MessageBoxResult.Yes)
                {
                    cmdLine.SafeStartup = true;
                }
            }
            else
            {
                FileSystem.CreateFile(PlaynitePaths.SafeStartupFlagFile);
            }

            // All code above has to be called before we create instance of WPF app,
            // because MessageBox forces WPF to initialize and fire startup app events.
            CurrentNative = appInitializer();
            CurrentNative.ShutdownMode = ShutdownMode.OnExplicitShutdown;
            SyncContext = new DispatcherSynchronizationContext(CurrentNative.Dispatcher);
            SynchronizationContext.SetSynchronizationContext(SyncContext);
            appMutex = new Mutex(true, instanceMuxet);

            try
            {
                // This can fail in rare cases when switching application modes
                // if an old instance fails to clean after itself or if it gets stuck on exit.
                Policy.Handle<Exception>()<commit_msg>Don't show safe startup warning when running in DEBUG mode<commit_after>﻿using Playnite.Controllers;
using Playnite.Input;
using Playnite.SDK;
using Playnite.Plugins;
using Playnite.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Diagnostics;
using Playnite.Database;
using Playnite.API;
using TheArtOfDev.HtmlRenderer;
using Playnite.Services;
using System.Windows.Input;
using System.Windows.Interop;
using System.Reflection;
using System.IO;
using Playnite.Common;
using System.ComponentModel;
using Playnite.Windows;
using Polly;
using System.Windows.Media;
using Playnite.SDK.Events;
using System.Windows.Threading;
using System.Net;
using Playnite.Common.Web;
using System.ServiceProcess;

namespace Playnite
{
    public abstract class PlayniteApplication : ObservableObject, IPlayniteApplication
    {
        private ILogger logger = LogManager.GetLogger();
        private const string instanceMuxet = "PlayniteInstaceMutex";
        private Mutex appMutex;
        private bool resourcesReleased = false;
        private PipeService pipeService;
        private PipeServer pipeServer;
        private XInputDevice xdevice;
        private System.Threading.Timer updateCheckTimer;
        private bool installingAddon = false;
        private AddonLoadError themeLoadError = AddonLoadError.None;
        private ThemeManifest customTheme;

        private bool isActive;
        public bool IsActive
        {
            get => isActive;
            set
            {
                isActive = value;
                OnPropertyChanged();
            }
        }

        public System.Version CurrentVersion
        {
            get => Updater.CurrentVersion;
        }

        public event EventHandler ExtensionsLoaded;
        public ApplicationMode Mode { get; }
        public IDialogsFactory Dialogs { get; set; }
        public PlayniteSettings AppSettings { get; set; }
        public GamesEditor GamesEditor { get; set; }
        public ExtensionFactory Extensions { get; set; }
        public GameDatabase Database { get; set; }
        public PlayniteAPI Api { get; set; }
        public GameControllerFactory Controllers { get; set; }
        public CmdLineOptions CmdLine { get; set; }
        public DpiScale DpiScale { get; set; } = new DpiScale(1, 1);
        public ComputerScreen CurrentScreen { get; set; } = Computer.GetPrimaryScreen();
        public DiscordManager Discord { get; set; }
        public SynchronizationContext SyncContext { get; private set; }
        public Action<PlayniteUriEventArgs> AppUriHandler { get; set; }
        public static Application CurrentNative { get; private set; }
        public static PlayniteApplication Current { get; private set; }
        public ServicesClient ServicesClient { get; private set; }
        public static bool SoundsEnabled { get; set; } = true;
        public MainViewModelBase MainModelBase { get; set; }
        public List<ExtensionInstallResult> ExtensionsInstallResult { get; set; }

        private ExtensionsStatusBinder extensionsStatusBinder = new ExtensionsStatusBinder();
        public ExtensionsStatusBinder ExtensionsStatusBinder { get => extensionsStatusBinder; set => SetValue(ref extensionsStatusBinder, value); }

        public PlayniteApplication()
        {
        }

        public PlayniteApplication(
            Func<Application> appInitializer,
            ApplicationMode mode,
            string defaultThemeName,
            CmdLineOptions cmdLine)
        {
            if (Current != null)
            {
                throw new Exception("Only one application instance is allowed.");
            }

            // TODO: remove after switch to .NET 5
            // Fixes various network issues on 2004+ Win10 if TLS 1.3 is forced via registry.
            if (Computer.IsTLS13SystemWideEnabled())
            {
                logger.Warn("System wide TLS 1.3 is enabled, forcing 1.2.");
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
            }

            CmdLine = cmdLine;
            Mode = mode;
            Current = this;

            if (!Debugger.IsAttached)
            {
                AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            }

            if (!CmdLine.MasterInstance)
            {
                if (CheckOtherInstances() || CmdLine.Shutdown)
                {
                    resourcesReleased = true;
                    Environment.Exit(0);
                    return;
                }
            }

#if !DEBUG
            if (FileSystem.FileExists(PlaynitePaths.SafeStartupFlagFile))
            {
                if (MessageBox.Show(
                    "Playnite closed unexpectedly while starting. This is usually caused by 3rd party theme or extension. Do you want to start in safe mode with all 3rd party add-ons disabled?",
                    "Startup Error",
                    MessageBoxButton.YesNo,
                    MessageBoxImage.Warning) == MessageBoxResult.Yes)
                {
                    cmdLine.SafeStartup = true;
                }
            }
            else
            {
                FileSystem.CreateFile(PlaynitePaths.SafeStartupFlagFile);
            }
#endif

            // All code above has to be called before we create instance of WPF app,
            // because MessageBox forces WPF to initialize and fire startup app events.
            CurrentNative = appInitializer();
            CurrentNative.ShutdownMode = ShutdownMode.OnExplicitShutdown;
            SyncContext = new DispatcherSynchronizationContext(CurrentNative.Dispatcher);
            SynchronizationContext.SetSynchronizationContext(SyncContext);
            appMutex = new Mutex(true, instanceMuxet);

            try
            {
                // This can fail in rare cases when switching application modes
                // if an old instance fails to clean after itself or if it gets stuck on exit.
                Policy.Handle<Exception>()
{'fraction_non_alphanumeric': 0.0662498985142486, 'fraction_numerical': 0.0038970528537793296, 'mean_word_length': 2.1739242463282658, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2390156', 'n_tokens_mistral': 3066, 'n_tokens_neox': 2967, 'n_words': 885}