using System;
using System.ComponentModel;
using System.Windows;
using Microsoft.Extensions.DependencyInjection;
using Pf2e.Scrapper.Helpers;
using Pf2e.Scrapper.Processors;
using Pf2e.Scrapper.Processors.Collection;
using Pf2e.Scrapper.WPF.EntityViewer;
using Pf2e.Scrapper.WPF.ProgressForm;
using Pf2e.Scrapper.WPF.StartForm;
using Pf2e.Database;
using Slugify;
namespace Pf2e.Scrapper;
internal sealed class ImportApplication : Application
{
public ImportApplication(
IServiceProvider serviceProvider,
ApplicationSettings settings,
ProcessorCollection processors
)
{
ServiceProvider = serviceProvider;
Settings = settings;
Processors = processors;
CurrentStage = ApplicationStage.InitialSettings;
//CurrentStage = ApplicationStage.Viewer;
}
#region "Поля"
///
/// Текущий этап выполнения программы.
///
public ApplicationStage CurrentStage
{
get => _currentStage;
set
{
ApplicationStage oldValue = _currentStage;
_currentStage = value;
CloseStage(oldValue);
StartStage(_currentStage);
}
}
private ApplicationStage _currentStage = ApplicationStage.BootUp;
#endregion
#region "Жизненный цикл"
private StartForm? _startFormWpf;
private ProgressForm? _progressFormWpf;
private EntityForm? _entityForm;
private Window? CurrentWpfForm { get; set; }
public delegate void ApplicationStateChangeDelegate(object sender, ApplicationStage nextStage);
private void StartStage(ApplicationStage stage)
{
switch (stage)
{
case ApplicationStage.BootUp:
throw new(
$"{CurrentStage} никогда не должен быть установлен через поле \"CurrentStage\"."
);
case ApplicationStage.InitialSettings:
_startFormWpf = ActivatorUtilities.CreateInstance(ServiceProvider);
_startFormWpf.WindowStartupLocation = WindowStartupLocation.CenterScreen;
_startFormWpf.Closing += Wpf_HandleFormClosing;
_startFormWpf.ApplicationStateChange += ApplicationStateChange;
_startFormWpf.Show();
CurrentWpfForm = _startFormWpf;
break;
case ApplicationStage.ImportProcess:
ProcessorExecutor executor = ActivatorUtilities.CreateInstance(
ServiceProvider
);
_progressFormWpf = ActivatorUtilities.CreateInstance(ServiceProvider);
_progressFormWpf.WindowStartupLocation = WindowStartupLocation.CenterScreen;
_progressFormWpf.Closing += Wpf_HandleFormClosing;
_progressFormWpf.ApplicationStateChange += ApplicationStateChange;
_progressFormWpf.Show();
CurrentWpfForm = _progressFormWpf;
executor.Start();
break;
case ApplicationStage.Viewer:
_entityForm = ActivatorUtilities.CreateInstance(ServiceProvider);
_entityForm.WindowStartupLocation = WindowStartupLocation.CenterScreen;
_entityForm.Closing += Wpf_HandleFormClosing;
_entityForm.ApplicationStateChange += ApplicationStateChange;
_entityForm.Show();
CurrentWpfForm = _entityForm;
break;
default:
throw new ArgumentOutOfRangeException();
}
}
private void CloseStage(ApplicationStage stage)
{
CurrentWpfForm = null;
switch (stage)
{
case ApplicationStage.BootUp:
// Нечего закрывать
break;
case ApplicationStage.InitialSettings:
_startFormWpf!.Hide();
_startFormWpf!.Close();
_startFormWpf = null;
break;
case ApplicationStage.ImportProcess:
_progressFormWpf!.Hide();
_progressFormWpf!.Close();
_progressFormWpf = null;
break;
case ApplicationStage.Viewer:
_entityForm!.Hide();
_entityForm!.Close();
_entityForm = null;
break;
default:
throw new ArgumentOutOfRangeException(nameof(stage));
}
}
#endregion
#region "События"
public void ApplicationStateChange(object sender, ApplicationStage nextStage)
{
if (sender?.Equals(CurrentWpfForm) ?? false)
{
CurrentStage = nextStage;
}
}
private void Wpf_HandleFormClosing(object? sender, CancelEventArgs e)
{
if (sender?.Equals(CurrentWpfForm) ?? false)
{
Shutdown();
}
else
{
e.Cancel = true;
}
}
#endregion
#region "Внедрение зависимостей"
public IServiceProvider ServiceProvider { get; }
public ApplicationSettings Settings { get; }
public ProcessorCollection Processors { get; }
public static void RegisterServices(IServiceCollection services)
{
// Контекст базы данных
services.AddEntityFrameworkNpgsql();
services.AddDbContext();
//services.AddDbContextPool(options =>
//{
// options.Us
//});
// Основная программа
services.AddSingleton();
// Настройки программы
services.AddSingleton();
// Набор процессоров
services.AddSingleton();
// Помощник идентификации базы данных
services.AddSingleton();
// Помощник создание URL-совместимых названий
services.AddTransient();
// Счётчик прогресса
services.AddSingleton();
}
#endregion
}
internal enum ApplicationStage
{
BootUp,
InitialSettings,
ImportProcess,
Viewer,
Rules,
}