protected void CheckComponentsSetup(IBotApiComponentsLocator botApiComponentsLocator)
 {
     CheckAllComponentsHaveDescriptorSpecified(botApiComponentsLocator);
     CheckAllComponentsHaveNoConflictsWithinGroup(botApiComponentsLocator);
     CheckAllComponentGroupsIncludeComponentsManager(botApiComponentsLocator);
     // todo: check that components set can be used at least by one "management strategy" (when Strategies will be implemented)?
 }
 protected virtual async Task ApplyUnregisterManagersComponentsAsync(
     IEnumerable <IBotApiComponentsManager> botApiComponentsManagers,
     IBotApiComponentsLocator botApiComponentsLocator)
 {
     foreach (var componentsManager in botApiComponentsManagers)
     {
         await componentsManager.UnregisterComponentsAsync(botApiComponentsLocator);
     }
 }
        protected void CheckAllComponentsHaveDescriptorSpecified(IBotApiComponentsLocator botApiComponentsLocator)
        {
            var componentsNames = GetInconsistentComponentsHavingDescriptorUnspecified(botApiComponentsLocator)
                                  .Select(_ => _.GetType().Name)
                                  .ToList();

            if (componentsNames.Any())
            {
                throw new InvalidOperationException($"The following Bot API Component(s) have unspecified Descriptor: {componentsNames.BarEnumerableToStrFmt()}.");
            }
        }
        protected void CheckAllComponentGroupsIncludeComponentsManager(IBotApiComponentsLocator botApiComponentsLocator)
        {
            var descriptorsNames = GetDescriptorsMissingComponentsManagerWithinGroup(botApiComponentsLocator)
                                   .Select(_ => _.ToString())
                                   .ToList();

            if (descriptorsNames.Any())
            {
                throw new InvalidOperationException($"The following Bot API Component group(s) do not include Bot API Components Manager: {descriptorsNames.BarEnumerableToStrFmt()}.");
            }
        }
        protected void CheckAllComponentsHaveNoConflictsWithinGroup(IBotApiComponentsLocator botApiComponentsLocator)
        {
            var componentGroupsNames = GetInconsistentComponentsConflictingWithinGroup(botApiComponentsLocator)
                                       .GroupBy(_ => _.ComponentDescriptor, _ => _.GetType().Name)
                                       .Select(_ => $"{_.Key} ({string.Join(", ", _)})")
                                       .ToList();

            if (componentGroupsNames.Any())
            {
                throw new InvalidOperationException($"The following Bot API Component group(s) have conflicting Components: {componentGroupsNames.BarEnumerableToStrFmt()}.");
            }
        }
        public async Task UnregisterComponentsAsync(IBotApiComponentsLocator botApiComponentsLocator)
        {
            var botApiClient   = botApiComponentsLocator.GetComponentByDescriptor <FakeBotApiClient>(ComponentDescriptor);
            var botApiEndpoint = botApiComponentsLocator.GetComponentByDescriptor <IBotApiEndpoint>(ComponentDescriptor);
            var botApiWebhook  = botApiComponentsLocator.GetComponentByDescriptor <FakeBotApiWebhook>(ComponentDescriptor);
            var botApiPoller   = botApiComponentsLocator.GetComponentByDescriptor <FakeBotApiPoller>(ComponentDescriptor);

            botApiPoller.UnregisterPoller();
            await botApiWebhook.UnregisterWebhookAsync();

            botApiEndpoint.UnregisterEndpoint();
            await botApiClient.UnregisterClientAsync();

            _logger.LogDebug(GetComponentsDetailsString("FakeBotApiComponentsManager UnregisterComponentsAsync completed", botApiClient, botApiEndpoint, botApiWebhook, botApiPoller));
        }
        public async Task RegisterComponentsAsync(IBotApiComponentsLocator botApiComponentsLocator)
        {
            // todo: implement components management via Strategy pattern

            var botApiClient   = botApiComponentsLocator.GetComponentByDescriptor <FakeBotApiClient>(ComponentDescriptor);
            var botApiEndpoint = botApiComponentsLocator.GetComponentByDescriptor <IBotApiEndpoint>(ComponentDescriptor);
            var botApiWebhook  = botApiComponentsLocator.GetComponentByDescriptor <FakeBotApiWebhook>(ComponentDescriptor);
            var botApiPoller   = botApiComponentsLocator.GetComponentByDescriptor <FakeBotApiPoller>(ComponentDescriptor);

            await botApiClient.RegisterClientAsync();

            botApiEndpoint.RegisterEndpoint();
            await botApiWebhook.RegisterWebhookAsync();

            botApiPoller.RegisterPoller();

            _logger.LogDebug(GetComponentsDetailsString("FakeBotApiComponentsManager RegisterComponentsAsync completed", botApiClient, botApiEndpoint, botApiWebhook, botApiPoller));
        }
 protected override Task ApplyUnregisterManagersComponentsAsync(IEnumerable <IBotApiComponentsManager> botApiComponentsManagers, IBotApiComponentsLocator botApiComponentsLocator)
 {
     try
     {
         return(base.ApplyUnregisterManagersComponentsAsync(botApiComponentsManagers, botApiComponentsLocator));
     }
     catch (Exception e)
     {
         _logger.LogError($"Bot API Components Lifetime Manager components unregistration failed, an exception has occurred.{Environment.NewLine}{e}");
         return(Task.CompletedTask);
     }
 }
        private IEnumerable <IBotApiComponent> GetInconsistentComponentsConflictingWithinGroup(IBotApiComponentsLocator botApiComponentsLocator)
        {
            var conflictingComponentsSet = new HashSet <IBotApiComponent>();

            foreach (var descriptor in IBotApiComponent.ApplicableComponentDescriptors)
            {
                var encounteredInterfacesSignaturesDictionary = new Dictionary <string, IBotApiComponent>();
                foreach (var component in botApiComponentsLocator.GetAllComponentsByDescriptor(descriptor))
                {
                    var interfacesOrdered = component.GetType()
                                            .GetInterfaces()
                                            .Where(_ => _.IsAssignableTo(typeof(IBotApiComponent)))
                                            .Select(_ => _.Name)
                                            .OrderBy(_ => _);
                    var interfacesSignature = string.Join('_', interfacesOrdered);

                    if (encounteredInterfacesSignaturesDictionary.TryAdd(interfacesSignature, component))
                    {
                        continue;
                    }

                    encounteredInterfacesSignaturesDictionary.TryGetValue(interfacesSignature, out var alreadyStoredComponent);
                    conflictingComponentsSet.Add(alreadyStoredComponent);
                    conflictingComponentsSet.Add(component);
                }
            }
            return(conflictingComponentsSet);
        }
 private IEnumerable <IBotApiComponent> GetInconsistentComponentsHavingDescriptorUnspecified(IBotApiComponentsLocator botApiComponentsLocator) =>
 botApiComponentsLocator.GetAllComponentsByDescriptor(BotApiComponentDescriptor.None);
 protected IEnumerable <IBotApiComponentsManager> GetComponentsManagersToRegisterAfterAppHost(IBotApiComponentsLocator botApiComponentsLocator) =>
 GetComponentsManagers(botApiComponentsLocator).Where(_ => _.RegisterAtApplicationStart && _.RegisterAtApplicationStartAfterAppHost);
 protected IEnumerable <IBotApiComponentsManager> GetComponentsManagers(IBotApiComponentsLocator botApiComponentsLocator) =>
 botApiComponentsLocator.GetAllComponents <IBotApiComponentsManager>();
        private IEnumerable <BotApiComponentDescriptor> GetDescriptorsMissingComponentsManagerWithinGroup(IBotApiComponentsLocator botApiComponentsLocator)
        {
            var descriptorsSet = new HashSet <BotApiComponentDescriptor>();

            foreach (var descriptor in IBotApiComponent.ApplicableComponentDescriptors)
            {
                if (botApiComponentsLocator.GetComponentByDescriptor <IBotApiComponentsManager>(descriptor) == null)
                {
                    descriptorsSet.Add(descriptor);
                }
            }
            return(descriptorsSet);
        }