//
// MainWindowViewModel.cs
//
// Copyright (c) František Boháček. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using System.Reflection;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Dock.Model.Controls;
using Dock.Model.Core;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NosSmooth.Comms.Local.Extensions;
using NosSmooth.Core.Extensions;
using NosSmooth.PacketSerializer.Abstractions.Attributes;
using NosSmooth.PacketSerializer.Extensions;
using NosSmooth.PacketSerializer.Packets;
using PacketLogger.Models;
using PacketLogger.Models.Packets;
using PacketLogger.Views;
using ReactiveUI;
namespace PacketLogger.ViewModels;
///
public class MainWindowViewModel : ViewModelBase, INotifyPropertyChanged
{
private readonly DockFactory _factory;
private readonly NostaleProcesses _processes;
///
/// Initializes a new instance of the class.
///
public MainWindowViewModel()
{
var services = new ServiceCollection()
.AddLogging(b => b.ClearProviders().AddConsole())
.AddSingleton()
.AddSingleton()
.AddNostaleCore()
.AddStatefulInjector()
.AddStatefulEntity()
.AddLocalComms()
.AddPacketResponder()
.BuildServiceProvider();
_processes = services.GetRequiredService();
var packetTypes = services.GetRequiredService();
var result = packetTypes.AddDefaultPackets();
if (!result.IsSuccess)
{
Console.WriteLine(result.ToFullString());
}
_factory = services.GetRequiredService();
Layout = _factory.CreateLayout();
if (Layout is { })
{
_factory.InitLayout(Layout);
if (Layout is { } root)
{
root.Navigate.Execute("Home");
}
}
SaveAll = ReactiveCommand.CreateFromTask
(
async () =>
{
if (Layout?.FocusedDockable is PacketLogDocumentViewModel activeDocument && activeDocument.Loaded
&& activeDocument.LogViewModel is not null)
{
var mainWindow = (App.Current!.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)
?.MainWindow;
var result = await new SaveFileDialog()
{
DefaultExtension = ".log",
InitialFileName = Assembly.GetEntryAssembly()?.GetModules().FirstOrDefault()?.FullyQualifiedName
}.ShowAsync(mainWindow!);
if (result is null)
{
return;
}
using var file = File.OpenWrite(result);
using var streamWriter = new StreamWriter(file);
foreach (var packet in activeDocument.LogViewModel.Provider.Packets.Items)
{
await streamWriter.WriteLineAsync
(
$"[{packet.Date:HH:mm:ss}]\t[{(packet.Source == PacketSource.Server ? "Recv" : "Send")}]\t{packet.PacketString.Trim()}"
);
}
}
}
);
SaveFiltered = ReactiveCommand.CreateFromTask
(
async () =>
{
if (Layout?.FocusedDockable is PacketLogDocumentViewModel activeDocument && activeDocument.Loaded
&& activeDocument.LogViewModel is not null)
{
var mainWindow = (App.Current!.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)
?.MainWindow;
var result = await new SaveFileDialog()
{
DefaultExtension = ".log",
}.ShowAsync(mainWindow!);
if (result is null)
{
return;
}
using var file = File.OpenWrite(result);
using var streamWriter = new StreamWriter(file);
foreach (var packet in activeDocument.LogViewModel.FilteredPackets)
{
await streamWriter.WriteLineAsync
(
$"[{packet.Date:HH:mm:ss}]\t[{(packet.Source == PacketSource.Server ? "Recv" : "Send")}]\t{packet.PacketString.Trim()}"
);
}
}
}
);
OpenFile = ReactiveCommand.Create
(() => _factory.CreateLoadedDocument(doc => doc.OpenFile.Execute(Unit.Default)));
OpenEmpty = ReactiveCommand.Create
(() => _factory.CreateLoadedDocument(doc => doc.OpenDummy.Execute(Unit.Default)));
Connect = ReactiveCommand.Create
(process => _factory.CreateLoadedDocument(doc => doc.OpenProcess.Execute((NostaleProcess)process[0]!)));
NewTab = ReactiveCommand.Create
(() => _factory.DocumentDock.CreateDocument?.Execute(null));
QuitApplication = ReactiveCommand.Create
(() => (Application.Current?.ApplicationLifetime as IControlledApplicationLifetime)?.Shutdown());
}
///
/// Gets the nostale processes.
///
public ObservableCollection Processes => _processes.Processes;
///
/// Gets or sets the layout.
///
public IRootDock? Layout { get; set; }
///
/// Gets a command that quits the application.
///
public ReactiveCommand QuitApplication { get; }
///
/// Gets a command that saves all packets.
///
public ReactiveCommand SaveAll { get; }
///
/// Gets a command that saves filtered packets.
///
public ReactiveCommand SaveFiltered { get; }
///
/// Gets the comamnd that opens a file.
///
public ReactiveCommand OpenFile { get; }
///
/// Gets the command that opens empty logger.
///
public ReactiveCommand OpenEmpty { get; }
///
/// Gets the command that opens empty logger.
///
public ReactiveCommand Connect { get; }
///
/// Gets the command that opens a new tab.
///
public ReactiveCommand NewTab { get; }
}