using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.AccessControl;
using System.Text;
using System.Threading.Tasks;
using gehGassi.Core.Interfaces;
using gehGassi.Domain.Common;
using gehGassi.Domain.Messages;
using gehGassi.Domain.News;
using Microsoft.EntityFrameworkCore;
namespace gehGassi.Core.Services
{
///
/// Service der die Verwaltung von Konversationen und Nachrichten realisiert
///
public class MessageService : ServiceBase, IMessageService
{
private readonly IRepository _conversationRepository;
private readonly IRepository _conversationNamesRepository;
private readonly IRepository _copyRepository;
///
/// Erstellt eine Instanz
///
/// Instanz eines IUnitOfWork
public MessageService(IUnitOfWork unitOfWork) : base(unitOfWork)
{
_conversationRepository = unitOfWork.GetRepository();
_conversationNamesRepository = unitOfWork.GetRepository();
_copyRepository = unitOfWork.GetRepository();
}
///
/// Gibt eine Liste der Konversationen eines Benutzers zurück
///
/// Id des Senders
/// /// Letztes Update
/// Liste der Konversationen
public async Task> GetConversationsAsync(string senderId, DateTimeOffset? lastUpdate)
{
var query = _conversationRepository.Query(c => c.SenderId == senderId || c.ReceiverId == senderId);
if (lastUpdate.HasValue)
query = query.Where(c => c.UpdatedAt > lastUpdate);
return await query.ToListAsync().ConfigureAwait(false);
}
///
/// Gibt eine Liste der Konversationen mit Namen aufgelöst eines Benutzers zurück
///
/// Id des Senders
/// Liste der Konversationen
public async Task> GetConversationsWithNamesAsync(string senderId)
{
var query = _conversationNamesRepository.Query(c => c.SenderId == senderId || c.ReceiverId == senderId);
return await query.ToListAsync().ConfigureAwait(false);
}
///
/// Gibt eine Liste der Konversationen eines Benutzers zurück
///
/// Id des Senders
/// Filter der in Namen gesucht werden soll
/// Letztes Update
/// Liste der Konversationen
public async Task> GetConversationsAsync(string senderId, string filter, DateTimeOffset? lastUpdate)
{
var query = _conversationRepository.Query(c => c.SenderId == senderId || c.ReceiverId == senderId);
if (lastUpdate.HasValue)
query = query.Where(c => c.UpdatedAt > lastUpdate);
return await query.ToListAsync().ConfigureAwait(false);
}
///
/// Gibt eine Konversation anhand der Teilnehmer zurück
///
/// Id des Senders
/// Id des Empfängers
/// Konversation oder null wenn nicht gefunden
public async Task GetConversationAsync(string senderId, string receiverId)
{
var query = _conversationRepository.Query(c => (c.SenderId == senderId && c.ReceiverId == receiverId) || (c.SenderId == receiverId && c.ReceiverId == senderId));
var found = await query.FirstOrDefaultAsync().ConfigureAwait(false);
return found;
}
///
/// Gibt eine gefilterte Liste von Konversationen mit Namen zurück
///
/// Filterbegriff der in bestimmten Feldern gesucht wird
/// List betroffener Konversationen
public IQueryable FilterConversationsWithNames(string filter)
{
return _conversationNamesRepository.QueryView(c => c.SenderName.Contains(filter) || c.ReceiverName.Contains(filter));
}
///
/// Hinzufügen einer Konversation
///
/// Id des Senders
/// Id des Empfängers
/// Benutzer der die Änderung vornimmt
/// Konversation
public async Task AddConversationAsync(string senderId, string receiverId, string userName)
{
var conversation = new Conversation()
{
Id = Guid.NewGuid().ToString("N"),
Created = DateTimeOffset.UtcNow,
UpdatedAt = DateTimeOffset.UtcNow,
SenderId = senderId,
ReceiverId = receiverId,
LastMessage = null,
MessageCount = 0
};
_conversationRepository.Add(conversation);
await CommitAsync(userName).ConfigureAwait(false);
return conversation;
}
///
/// Hinzufügen einer Konversation
///
/// Id des Konversation
/// Id des Senders
/// Id des Empfängers
/// Benutzer der die Änderung vornimmt
/// Konversation
public async Task AddConversationAsync(string id, string senderId, string receiverId, string userName)
{
var conversation = new Conversation()
{
Id = id,
Created = DateTimeOffset.UtcNow,
UpdatedAt = DateTimeOffset.UtcNow,
SenderId = senderId,
ReceiverId = receiverId,
LastMessage = null,
MessageCount = 0
};
_conversationRepository.Add(conversation);
await CommitAsync(userName).ConfigureAwait(false);
return conversation;
}
///
/// Entfernen einer Konversation
///
/// Id der Konversation
/// Benutzer der die Änderung vornimmt
public async Task RemoveConversationAsync(string id, string userName)
{
var conversation = await _conversationRepository.FirstOrDefaultAsync(c => c.Id == id).ConfigureAwait(false);
if (conversation != null)
{
_conversationRepository.Remove(conversation);
await CommitAsync(userName).ConfigureAwait(false);
return true;
}
return false;
}
///
/// Entfernen einer Konversation nach AppUser
///
/// Id des AppUsers
/// Anzahl Konversationen
public async Task RemoveConversationByAppUserAsync(string appUserId)
{
var conversations = await Repository.FindAsync(c => c.ReceiverId == appUserId || c.SenderId == appUserId).ConfigureAwait(false);
foreach (var conversation in conversations)
{
Repository.Remove(conversation);
}
return conversations.Count();
}
///
/// Gibt eine Liste noch nicht zugestellter Nachrichten für einen Benutzer zurück.
///
/// Id des Users - wird als Receiver gesucht
/// Letztes Update
/// Liste nicht erhaltener Nachrichten
public async Task> GetMessagesAsync(string senderId, DateTimeOffset? lastUpdate)
{
var query = Repository.Query(c => c.ReceiverId == senderId);
if (lastUpdate.HasValue)
query = query.Where(c => c.UpdatedAt > lastUpdate);
return await query.ToListAsync().ConfigureAwait(false);
}
///
/// Gibt eine Liste noch nicht zugestellter Nachrichten in einer Konversation für einen Benutzer zurück.
///
/// Id des Users - wird als Receiver gesucht
/// Id der Konversation
/// Letztes Update
/// Liste nicht erhaltener Nachrichten
public async Task> GetMessagesAsync(string senderId, string conversationId, DateTimeOffset? lastUpdate)
{
var query = Repository.Query(c => c.ReceiverId == senderId && c.ConversationId == conversationId);
if (lastUpdate.HasValue)
query = query.Where(c => c.UpdatedAt > lastUpdate);
return await query.ToListAsync().ConfigureAwait(false);
}
///
/// Berstätigen des Erhaltes von Nachrichten für einen Benutzer. Alle die älter als das UpdateDatum sind werden gelöscht
///
/// Id des Users - wird als Receiver gesucht
/// Letztes Update
/// Benutzer der die Änderung vornimmt
/// true wenn erfolgreich, false sonst
public async Task ConfirmMessagesAsync(string senderId, DateTimeOffset lastUpdate, string userName)
{
var query = Repository.Query(c => c.ReceiverId == senderId && c.UpdatedAt <= lastUpdate);
var list = await query.ToListAsync().ConfigureAwait(false);
if (list.Any())
{
await SetMessageCopiesRead(list, DateTimeOffset.UtcNow).ConfigureAwait(false);
Repository.RemoveRange(list);
await CommitAsync(userName).ConfigureAwait(false);
}
return true;
}
///
/// Berstätigen des Erhaltes von Nachrichten für eine Konversation für einen Benutzer. Alle die älter als das UpdateDatum sind werden gelöscht
///
/// Id des Users - wird als Receiver gesucht
/// Id der Konversation
/// Letztes Update
/// Benutzer der die Änderung vornimmt
/// true wenn erfolgreich, false sonst
public async Task ConfirmMessagesAsync(string senderId, string conversationId, DateTimeOffset lastUpdate, string userName)
{
var query = Repository.Query(c => c.ReceiverId == senderId && c.ConversationId == conversationId && c.UpdatedAt <= lastUpdate);
var list = await query.ToListAsync().ConfigureAwait(false);
if (list.Any())
{
await SetMessageCopiesRead(list, DateTimeOffset.UtcNow).ConfigureAwait(false);
Repository.RemoveRange(list);
await CommitAsync(userName).ConfigureAwait(false);
}
return true;
}
///
/// Hinzufügen einer Nachricht
///
/// Nachricht
/// Benutzer der die Änderung vornimmt
/// Angelegte Nachricht
public async Task AddMessageAsync(Message message, string userName)
{
Repository.Add(message);
var copy = new MessageCopy()
{
Id = message.Id,
Version = message.Version,
UpdatedAt = message.UpdatedAt,
Deleted = message.Deleted,
ConversationId = message.ConversationId,
SenderId = message.SenderId,
ReceiverId = message.ReceiverId,
Content = message.Content,
Read = false,
ReadDate = null
};
_copyRepository.Add(copy);
await CommitAsync(userName).ConfigureAwait(false);
return message;
}
///
/// Neusetzen des UpdatedAt Datums falls sich das foto eines Benutzers geändert hat
///
///
///
///
///
public async Task SetUpdatedAtAsync(string appUserId, DateTimeOffset updatedAt, string userName)
{
var conversations = await _conversationRepository.FindAsync(c => (c.ReceiverId == appUserId || c.SenderId == appUserId )&& c.Deleted == false).ConfigureAwait(false);
foreach (var conversation in conversations)
{
conversation.UpdatedAt = updatedAt;
}
await CommitAsync(userName).ConfigureAwait(false);
return conversations.Count();
}
///
/// Gibt die Anzahl der noch nicht gelesenen Nachrichten für einen Benutzer zurück
///
/// Id des Empfängers
/// Id der Konversation
/// Anzahl ungelesene Nachrichten
public async Task CountOpenMessagesAsync(string receiverId, string conversationId)
{
var messageCount = await Repository.Query(m => m.ReceiverId == receiverId && m.ConversationId == conversationId).CountAsync().ConfigureAwait(false);
return messageCount;
}
///
/// Entfernt Nachrichten die in einem bestimmten Zeitraum nicht gelesen wurden
///
/// Nachricht muss älter als dieses Datum sein
/// Anzahl gelöschte Nachrichten
public async Task RemoveUnreadMessagesAsync(DateTimeOffset olderThanDate)
{
var messages = await Repository.FindAsync(c => c.UpdatedAt < olderThanDate);
foreach (var message in messages)
{
Repository.Remove(message);
}
return messages.Count();
}
///
/// Entfernt Nachrichten-Kopien die alter als ein Datum sind
///
/// Nachricht muss älter als dieses Datum sein
/// Anzahl gelöschte Nachrichten
public async Task RemoveMessageCopiesAsync(DateTimeOffset olderThanDate)
{
var messages = await _copyRepository.FindAsync(c => c.UpdatedAt < olderThanDate);
foreach (var message in messages)
{
_copyRepository.Remove(message);
}
return messages.Count();
}
///
/// Gibt die Nachrichten-Kopien einer Konversation zurück
///
/// Id der Konversation
/// Liste nicht erhaltener Nachrichten
public async Task> GetMessageCopiesAsync(string conversationId)
{
var messages = (await _copyRepository.FindAsync(c => c.ConversationId == conversationId).ConfigureAwait(false)).OrderBy(c => c.UpdatedAt).ToList();
return messages;
}
#region private
///
/// Setzt die Kopiene einer Liste von Nachrichten auf gelesen
///
/// Liste der Nachrichten
/// Datum gelesen
/// Task
private async Task SetMessageCopiesRead(List messages, DateTimeOffset readDate)
{
foreach (var message in messages)
{
var copy = await _copyRepository.GetAsync(message.Id);
if (copy != null)
{
copy.Read = true;
copy.ReadDate = readDate;
}
}
}
#endregion
}
}