using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.Messaging;
using gehGassi.Dto;
using gehGassi.Dto.Messages;
using gehGassiApp.Core.Interfaces;
using gehGassiApp.Core.Interfaces.Synchronization;
using gehGassiApp.Core.Messaging;
using Microsoft.AspNetCore.SignalR.Client;
namespace gehGassiApp.Core.Services
{
///
/// Service der Daten vom AppHub des Servers empfangen kann
///
public class AppHubService : IAppHubService
{
private string _baseAddress;
private HubConnection _connection;
///
/// Erstellt eine Instanz
///
/// Basis-Adresse des Servers
public AppHubService(string baseAddress)
{
_baseAddress = baseAddress;
if (_baseAddress.EndsWith("/"))
_baseAddress = _baseAddress.Substring(0, _baseAddress.Length - 1);
}
///
/// Connection zum Hub erstellen
///
private void CreateConnection(string accessToken)
{
_connection = new HubConnectionBuilder().WithUrl($"{_baseAddress}/appHub", o =>
{
o.AccessTokenProvider = () => Task.FromResult(accessToken);
o.HttpMessageHandlerFactory = (message) =>
{
#if DEBUG
// bypass SSL certificate
if (message is HttpClientHandler clientHandler)
{
clientHandler.ServerCertificateCustomValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;
}
#endif
return message;
};
}).WithAutomaticReconnect().Build();
}
///
/// Setzen der Basis-Adresse des Servers
///
/// Basis-Adresse
public async Task SetBaseAddressAsync(string baseAddress)
{
_baseAddress = baseAddress;
if (_baseAddress.EndsWith("/"))
_baseAddress = _baseAddress.Substring(0, _baseAddress.Length - 1);
await DisconnectAsync();
}
public async Task ConnectAsync(string accessToken)
{
if (_connection != null && _connection.State == HubConnectionState.Connected) return;
if (_connection != null && _connection.State == HubConnectionState.Connecting) return;
if (_connection != null && _connection.State == HubConnectionState.Reconnecting) return;
//Buchen der Nachrichten
CreateConnection(accessToken);
_connection.On("AppUserChanged", async () => await AppUserChangedAsync());
_connection.On("NewsCategoriesChanged", async () => await NewsCategoriesChangedAsync());
_connection.On("ConversationMessageAdded", async (MessageDto messageDto) => await ConversationMessageAddedAsync(messageDto));
_connection.On("MessageAdded", async () => await MessageAddedAsync());
_connection.On("SystemMessageAdded", async () => await SystemMessageAddedAsync());
_connection.On("Logout", async () => await LogoutAsync());
try
{
await _connection.StartAsync().ConfigureAwait(false);
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
}
///
/// Verbindung trennen
///
/// Task
public async Task DisconnectAsync()
{
if (_connection != null)
{
try
{
await _connection.StopAsync();
await _connection.DisposeAsync();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
}
}
//CreateConnection();
}
///
/// Gibt zurück ob eine SignalR Verbindung besteht
///
/// true wenn ja oder reconnecting, false sonst
public bool IsConnected()
{
if (_connection == null)
return false;
return _connection.State != HubConnectionState.Disconnected;
}
///
/// Buchen der Events eines App-Users
///
/// Id des AppUsers
/// Task
public async Task JoinAppUserAsync(string appUserId)
{
if(_connection == null || string.IsNullOrWhiteSpace(appUserId))
return;
if (_connection is { State: HubConnectionState.Connected })
{
await _connection.SendAsync("JoinAppUser", appUserId);
}
}
///
/// Abbestellen der Events eines App-Users
///
/// Id des AppUsers
/// Task
public async Task LeaveAppUserAsync(string appUserId)
{
if (_connection == null || string.IsNullOrWhiteSpace(appUserId))
return;
if (_connection is { State: HubConnectionState.Connected })
{
await _connection.SendAsync("LeaveAppUser", appUserId);
}
}
///
/// Buchen der Events einer Konversation
///
/// Id der Konversation
/// Id des AppUsers
/// Task
public async Task JoinConversationAsync(string conversationId, string appUserId)
{
if (_connection == null || string.IsNullOrWhiteSpace(appUserId) || string.IsNullOrWhiteSpace(conversationId))
return;
if (_connection is { State: HubConnectionState.Connected })
{
await _connection.SendAsync("JoinConversation", conversationId, appUserId);
}
}
///
/// Abbestellen der Events einer Konversation
///
/// Id der Konversation
/// Id des AppUsers
/// Task
public async Task LeaveConversationAsync(string conversationId, string appUserId)
{
if (_connection == null || string.IsNullOrWhiteSpace(appUserId) || string.IsNullOrWhiteSpace(conversationId))
return;
if (_connection is { State: HubConnectionState.Connected })
{
await _connection.SendAsync("LeaveConversation", conversationId, appUserId);
}
}
#region EventHandler
///
/// Handler wenn sich der App-User geändert hat
///
/// Task
private async Task AppUserChangedAsync()
{
await Task.Delay(1);
WeakReferenceMessenger.Default.Send(new SignalRAppUserChangedMessage());
}
///
/// Handler wenn sich News-Kategorien geändert haben
///
/// Task
private async Task NewsCategoriesChangedAsync()
{
await Task.Delay(1);
WeakReferenceMessenger.Default.Send(new SignalRNewsCategoriesChangedMessage());
}
///
/// Handler wenn zu einer Konversation eine Nachricht hinzugefügt wurde
///
///
///
private async Task ConversationMessageAddedAsync(MessageDto message)
{
await Task.Delay(1);
WeakReferenceMessenger.Default.Send(new SignalRConversationMessageAddedMessage(message.ConversationId));
}
///
/// Handler wenn neue Nachrichten für einen Benutzer da sind
///
/// Task
private async Task MessageAddedAsync()
{
await Task.Delay(1);
WeakReferenceMessenger.Default.Send(new MessagesChangedMessage());
}
///
/// Handler wenn neue SystemNachrichten für einen Benutzer da sind
///
/// Task
private async Task SystemMessageAddedAsync()
{
await Task.Delay(1);
WeakReferenceMessenger.Default.Send(new SignalRSystemMessagesChangedMessage());
}
///
/// Handler wenn der Benutzer abgemeldet werden soll
///
/// Task
private async Task LogoutAsync()
{
await Task.Delay(1);
WeakReferenceMessenger.Default.Send(new LogoutMessage());
}
#endregion
}
}