using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.SignalR; using xAiModels.Constants; using xAiModels.Interfaces; using xAiModels.Interfaces.Dtos; using xAiModels.Models.Dtos; using xAiModels.Providers.Hubs; using xCommons.Configurations; using xCommons.Extensions; using xExceptions.Constants; using xModels.Dtos; using xStringService.Interfaces; namespace xAiModels.Providers { /// /// All Data Manipulation Requirements ... /// public class XAiDataProvider : IXAiDataProvider { private readonly IXStringProvider stringProvider; private readonly XAppConfiguration appConfiguration; private readonly IHubContext hub; private readonly IXAiMessageRepositoryService messageRepositoryService; private readonly IXAiProjectRepositoryService projectRepositoryService; private readonly IXAiProjectTitleResourceProvider projectTitleResourceProvider; private readonly IXAiConversationRepositoryService conversationRepositoryService; private readonly IXAiConversationTitleResourceProvider conversationTitleResourceProvider; private readonly IXAiProjectDescriptionResourceProvider projectDescriptionResourceProvider; public XAiDataProvider( IXStringProvider stringProvider, XAppConfiguration appConfiguration, IHubContext hub, IXAiMessageRepositoryService messageRepositoryService, IXAiProjectRepositoryService projectRepositoryService, IXAiProjectTitleResourceProvider projectTitleResourceProvider, IXAiConversationRepositoryService conversationRepositoryService, IXAiConversationTitleResourceProvider conversationTitleResourceProvider, IXAiProjectDescriptionResourceProvider projectDescriptionResourceProvider ) { this.hub = hub; this.stringProvider = stringProvider; this.appConfiguration = appConfiguration; this.messageRepositoryService = messageRepositoryService; this.projectRepositoryService = projectRepositoryService; this.projectTitleResourceProvider = projectTitleResourceProvider; this.conversationRepositoryService = conversationRepositoryService; this.conversationTitleResourceProvider = conversationTitleResourceProvider; this.projectDescriptionResourceProvider = projectDescriptionResourceProvider; } // #region Actions ... #endregion // #region Private ... /// /// Check Default Project Exists or not ... /// /// /// /// private async Task HasDefaultProject( string ownerId, CancellationToken cancellationToken = default ) { // // Validate Args ... var result = !ownerId.IsNullOrEmpty(); if (!result) { return result; } // // Check Default Owner Exists or not ... result = !(await stringProvider.FindOne( cancellationToken: cancellationToken, predicate: x => x.ResourceTitle .ToNormalString() .Contains(ownerId.ToNormalString()) && x.ResourceTitle .ToNormalString() .Contains(XAiModelsConstants.XAiProjectTitleIdentifier .ToNormalString()) && x.TranslatedValue .ToNormalString() .Contains(XAiDataProviderConstants.XDefaultAiProjectSuffix) )) .IsNullOrDefault(); return result; } /// /// Retrieve Default Project of Specified Owner ... /// Create it if not Handled ... /// /// /// /// /// private async Task GetDefaultProject( string ownerId, string connectionId = null, CancellationToken cancellationToken = default ) { // // Check Default Project Exists or noit ... var isExists = await HasDefaultProject( ownerId: ownerId, cancellationToken: cancellationToken ); if (!isExists) { // await CreateDefaultProject( ownerId: ownerId, connectionId: connectionId, cancellationToken: cancellationToken ); } // var resource = await stringProvider.FindOne( cancellationToken: cancellationToken, predicate: x => x.ResourceTitle .ToNormalString() .Contains(ownerId.ToNormalString()) && x.ResourceTitle .ToNormalString() .Contains(XAiModelsConstants.XAiProjectTitleIdentifier .ToNormalString()) && x.TranslatedValue .ToNormalString() .Contains(XAiDataProviderConstants.XDefaultAiProjectSuffix) ); if (resource.IsNullOrDefault()) { XException.NotFound.Throw(); } // var result = await projectRepositoryService.FindOneAsync( cancellationToken: cancellationToken, predicate: x => x.Title .Equals( resource.ResourceTitle, StringComparison.InvariantCultureIgnoreCase ) ); if (result.IsNullOrDefault()) { XException.NotFound.Throw(); } // return result; } /// /// Create Default Project for Specified Owner ... /// /// /// /// /// private async Task CreateDefaultProject( string ownerId, string connectionId = null, CancellationToken cancellationToken = default ) { // if (ownerId.IsNullOrEmpty()) { return; } // var defaultLang = appConfiguration.DefaultLanguage; // // Check Default Owner Exists or not ... var isExists = await HasDefaultProject( ownerId: ownerId, cancellationToken: cancellationToken ); if (isExists) { return; } // // Create Default ... var item = new XAiProjectDto() { OwnerId = ownerId, CreatedOn = DateTime.UtcNow, Title = Guid.NewGuid().ToString(), Description = Guid.NewGuid().ToString(), }; item = await projectRepositoryService.AddAsync( item: item, saveChanges: true, cancellationToken: cancellationToken ); // // Prepare Tile and Description Resource Ids ... var titleResource = await projectTitleResourceProvider.AddOrUpdateLocale( owner: ownerId, identifier: item.Id, locale: new XLocaleResourceDto { Language = defaultLang, Value = XAiDataProviderConstants.XDefaultAiProjectSuffix }, cancellationToken: cancellationToken ); var descriptionResource = await projectDescriptionResourceProvider.AddOrUpdateLocale( owner: ownerId, identifier: item.Id, new XLocaleResourceDto { Language = defaultLang, Value = XAiDataProviderConstants.XDefaultAiProjectSuffix }, cancellationToken: cancellationToken ); if (titleResource.IsNullOrDefault() || descriptionResource.IsNullOrDefault() ) { return; } // // Update Project Resources ... item.Title = titleResource.Resource; item.Description = descriptionResource.Resource; item = await projectRepositoryService.UpdateAsync( id: item.Id, item: item, saveChanges: true, cancellationToken: cancellationToken ); // // Sending Push ... if (!connectionId.IsNullOrEmpty()) { // await SendPush( connectionId: connectionId, cancellationToken: cancellationToken, payLoad: item.ToJSON(camelCase: true), action: XAiDataProviderHubActions.ProjectCreated.GetStringValue() ); } } /// /// Check Default Conversation Exists or not ... /// /// /// /// private async Task HasDefaultConversation( string ownerId, CancellationToken cancellationToken = default ) { // // Validate Args ... var result = !ownerId.IsNullOrEmpty(); if (!result) { return result; } // // Check Default Owner Exists or not ... result = !(await stringProvider.FindOne( cancellationToken: cancellationToken, predicate: x => x.ResourceTitle .ToNormalString() .Contains(ownerId.ToNormalString()) && x.ResourceTitle .ToNormalString() .Contains(XAiModelsConstants.XAiConversationTitleIdentifier .ToNormalString()) && x.TranslatedValue .ToNormalString() .Contains(XAiDataProviderConstants.XDefaultAiConversationSuffix) )) .IsNullOrDefault(); return result; } /// /// Check Default Conversation Exists or not ... /// /// /// /// /// private async Task CreateDefaultConversation( string ownerId, string connectionId = null, CancellationToken cancellationToken = default ) { // // Validate Args ... var isValid = !ownerId.IsNullOrEmpty(); if (!isValid) { return; } // var defaultLang = appConfiguration.DefaultLanguage; // // Handle Default Project ... var project = await GetDefaultProject( ownerId: ownerId, connectionId: connectionId, cancellationToken: cancellationToken ); // // Check Default Owner Exists or not ... isValid = await HasDefaultConversation( ownerId: ownerId, cancellationToken: cancellationToken ); if (isValid) { return; } // // Create Default Conversation ... var item = new XAiConversationDto { OwnerId = ownerId, ProjectId = project.Id, CreatedOn = DateTime.UtcNow, Title = Guid.NewGuid().ToString() }; item = await conversationRepositoryService.AddAsync( item: item, saveChanges: true, cancellationToken: cancellationToken ); // // Prepare Title Resource Ids ... var titleResource = await conversationTitleResourceProvider.AddOrUpdateLocale( owner: ownerId, identifier: item.Id, locale: new XLocaleResourceDto { Language = defaultLang, Value = XAiDataProviderConstants.XDefaultAiConversationSuffix }, cancellationToken: cancellationToken ); if (titleResource.IsNullOrDefault()) { return; } // // Update Conversation Resources ... item.Title = titleResource.Resource; item = await conversationRepositoryService.UpdateAsync( item: item, id: item.Id, saveChanges: true, cancellationToken: cancellationToken ); // // Sending Push ... if (!connectionId.IsNullOrEmpty()) { // await SendPush( connectionId: connectionId, cancellationToken: cancellationToken, payLoad: item.ToJSON(camelCase: true), action: XAiDataProviderHubActions.ConversationCreated.GetStringValue() ); } } /// /// Retrieve Default Conversation of Specified Owner ... /// Create it if not Handled ... /// /// /// /// /// private async Task GetDefaultConversation( string ownerId, string connectionId = null, CancellationToken cancellationToken = default ) { // // Check Default Conversation Exists or noit ... var isExists = await HasDefaultConversation( ownerId: ownerId, cancellationToken: cancellationToken ); if (!isExists) { // await CreateDefaultConversation( ownerId: ownerId, connectionId: connectionId, cancellationToken: cancellationToken ); } // var resource = await stringProvider.FindOne( cancellationToken: cancellationToken, predicate: x => x.ResourceTitle .ToNormalString() .Contains(ownerId.ToNormalString()) && x.ResourceTitle .ToNormalString() .Contains(XAiModelsConstants.XAiProjectTitleIdentifier .ToNormalString()) && x.TranslatedValue .ToNormalString() .Contains(XAiDataProviderConstants.XDefaultAiProjectSuffix) ); if (resource.IsNullOrDefault()) { XException.NotFound.Throw(); } // var result = await conversationRepositoryService.FindOneAsync( cancellationToken: cancellationToken, predicate: x => x.Title .Equals( resource.ResourceTitle, StringComparison.InvariantCultureIgnoreCase ) ); if (result.IsNullOrDefault()) { XException.NotFound.Throw(); } // return result; } /// /// Send Custom Push Message ... /// /// /// /// /// /// public async Task SendPush( string action, string payLoad, string connectionId = null, CancellationToken cancellationToken = default ) { // try { // // Collect Allowed Actions ... var actions = new List { XAiDataProviderHubActions.ProjectCreated.GetStringValue(), XAiDataProviderHubActions.ProjectUpdated.GetStringValue(), XAiDataProviderHubActions.ProjectRemoved.GetStringValue(), XAiDataProviderHubActions.MessageCreated.GetStringValue(), XAiDataProviderHubActions.MessageUpdated.GetStringValue(), XAiDataProviderHubActions.MessageRemoved.GetStringValue(), XAiDataProviderHubActions.ConversationCreated.GetStringValue(), XAiDataProviderHubActions.ConversationUpdated.GetStringValue(), XAiDataProviderHubActions.ConversationRemoved.GetStringValue(), }; // // Validate Args ... var isValid = !action.IsNullOrEmpty() && actions.Contains(action); if (!isValid) { return; } // // Retrieve Connection Id ... var clients = hub.Clients.All; if (!connectionId.IsNullOrEmpty()) { clients = hub.Clients.AllExcept(connectionId); } // await clients.SendAsync( action, payLoad, connectionId, cancellationToken ); } catch { } } #endregion } }