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 } }