<commit_before>﻿using Playnite.Common;
using Playnite.Controls;
using Playnite.Native;
using Playnite.SDK;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;

namespace Playnite.Windows
{
    public interface IWindowFactory
    {
        bool WasClosed { get; }

        bool? CreateAndOpenDialog(object dataContext);

        void Show(object dataContext);

        void RestoreWindow();

        void Close();

        void Close(bool? resutl);

        WindowBase Window { get; }
    }

    public abstract class WindowFactory : IWindowFactory
    {
        private static ILogger logger = LogManager.GetLogger();
        private readonly SynchronizationContext context;
        private bool asDialog = false;
        public bool WasClosed { get; private set; } = false;

        public WindowBase Window
        {
            get;
            private set;
        }

        public abstract WindowBase CreateNewWindowInstance();

        public WindowFactory()
        {
            context = SynchronizationContext.Current ?? PlayniteApplication.Current.SyncContext;
        }

        public bool? CreateAndOpenDialog(object dataContext)
        {
            bool? result = null;
            context.Send((a) =>
            {
                Window = CreateNewWindowInstance();
                Window.Closed += Window_Closed;
                Window.DataContext = dataContext;
                logger.Debug($"Show dialog window {GetType()}: {Window.Id}");

                var currentWindow = WindowManager.CurrentWindow;
                if (currentWindow != null && Window != currentWindow)
                {
                    if (typeof(WindowBase).IsAssignableFrom(currentWindow.GetType()) && ((WindowBase)currentWindow).IsShown)
                    {
                        Window.Owner = currentWindow;
                    }
                }

                if (Window.Owner == null)
                {
                    Window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
                    Window.ShowInTaskbar = true;
                }

                asDialog = true;
                WasClosed = false;
                result = Window.ShowDialog();
            }, null);

            return result;
        }

        public void Show(object dataContext)
        {
            context.Send((a) =>
            {
                asDialog = false;
                if (WasClosed)
                {
                    logger.Debug($"Opening window that was closed previously {GetType()}, old Id: {Window.Id}");
                    Window = CreateNewWindowInstance();
                    Window.Closed += Window_Closed;
                }

                if (Window == null)
                {
                    Window = CreateNewWindowInstance();
                    Window.Closed += Window_Closed;
                }

                logger.Debug($"Show window {GetType()}: {Window.Id}");
                Window.DataContext = dataContext;
                WasClosed = false;
                Window.Show();
            }, null);
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            WasClosed = true;
            Window.Closed -= Window_Closed;
        }

        public void RestoreWindow()
        {
            context.Send((a) =>
            {
                WindowUtils.RestoreWindow(Window);
            }, null);
        }

        public void Close()
        {
            Close(null);
        }

        public void Close(bool? result)
        {
            logger.Debug($"Closing window {GetType()}: {Window.Id}, {result}");
            context.Send(async (_) =>
            {
                // This is a workaround for WPF bug which causes deadlock in ShowDialog
                // if parent of modal window is closed before the child window itself is closed.
                // To prevent this we need to make sure that window parenting other windows is only
                // closed after all children are closed.
                // https://github.com/dotnet/wpf/issues/277
                // https://stackoverflow.com/questions/40304161/showdialog-method-hangs-without-showing-the-window-deadlock#48208699
                while (Window.GetHasChild())
                {
                    await Task.Delay(100);<commit_msg>Potential deadlock with global progress dialogs<commit_after>﻿using Playnite.Common;
using Playnite.Controls;
using Playnite.Native;
using Playnite.SDK;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;

namespace Playnite.Windows
{
    public interface IWindowFactory
    {
        bool WasClosed { get; }

        bool? CreateAndOpenDialog(object dataContext);

        void Show(object dataContext);

        void RestoreWindow();

        void Close();

        void Close(bool? resutl);

        WindowBase Window { get; }
    }

    public abstract class WindowFactory : IWindowFactory
    {
        private static ILogger logger = LogManager.GetLogger();
        private readonly SynchronizationContext context;
        private bool asDialog = false;
        private AutoResetEvent initFinishedEvent { get; } = new AutoResetEvent(false);
        public bool WasClosed { get; private set; } = false;

        public WindowBase Window
        {
            get;
            private set;
        }

        public abstract WindowBase CreateNewWindowInstance();

        public WindowFactory()
        {
            context = SynchronizationContext.Current ?? PlayniteApplication.Current.SyncContext;
        }

        public bool? CreateAndOpenDialog(object dataContext)
        {
            bool? result = null;
            context.Send((a) =>
            {
                Window = CreateNewWindowInstance();
                Window.Closed += Window_Closed;
                Window.DataContext = dataContext;
                logger.Debug($"Show dialog window {GetType()}: {Window.Id}");

                var currentWindow = WindowManager.CurrentWindow;
                if (currentWindow != null && Window != currentWindow)
                {
                    if (typeof(WindowBase).IsAssignableFrom(currentWindow.GetType()) && ((WindowBase)currentWindow).IsShown)
                    {
                        Window.Owner = currentWindow;
                    }
                }

                if (Window.Owner == null)
                {
                    Window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
                    Window.ShowInTaskbar = true;
                }

                asDialog = true;
                WasClosed = false;
                initFinishedEvent.Set();
                result = Window.ShowDialog();
            }, null);

            return result;
        }

        public void Show(object dataContext)
        {
            context.Send((a) =>
            {
                asDialog = false;
                if (WasClosed)
                {
                    logger.Debug($"Opening window that was closed previously {GetType()}, old Id: {Window.Id}");
                    Window = CreateNewWindowInstance();
                    Window.Closed += Window_Closed;
                }

                if (Window == null)
                {
                    Window = CreateNewWindowInstance();
                    Window.Closed += Window_Closed;
                }

                logger.Debug($"Show window {GetType()}: {Window.Id}");
                Window.DataContext = dataContext;
                WasClosed = false;
                initFinishedEvent.Set();
                Window.Show();
            }, null);
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            WasClosed = true;
            Window.Closed -= Window_Closed;
        }

        public void RestoreWindow()
        {
            context.Send((a) =>
            {
                WindowUtils.RestoreWindow(Window);
            }, null);
        }

        public void Close()
        {
            Close(null);
        }

        public void Close(bool? result)
        {
            // This needs to be here in case Close is called too early.
            // This can happen in async scenarios like with ProgressViewViewModel and progress dialogs if progress code is too fast to complete.
            initFinishedEvent.WaitOne();

            logger.Debug($"Closing window {GetType()}: {Window.Id}, {result}");
            context.Send(async (_) =>
            {
                // This is a workaround for WPF bug which causes deadlock in ShowDialog
                // if parent of modal window is closed before the child window itself is closed.
                // To prevent this we need to make sure that window parenting other windows is only
                // closed after all children are closed.
                // https://github.com/dotnet/wpf/issues/277
                // https://stackoverflow.com/questions/40304161/showdialog-method-hangs-without-showing-the-window-deadlock#48208699
                while (Window.GetHasChild())
                {
                    await Task.Delay(100);
{'fraction_non_alphanumeric': 0.08610755441741358, 'fraction_numerical': 0.004694835680751174, 'mean_word_length': 1.5332432432432432, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 4, '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': '1070448', 'n_tokens_mistral': 2349, 'n_tokens_neox': 2153, 'n_words': 563}