<commit_before>﻿using Autofac;
using System.Reflection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Bibliotheca.Server.ServiceDiscovery.ServiceClient;
using System.Linq;
using Microsoft.AspNetCore.Http;
using System.Collections.Generic;
using Microsoft.Extensions.Primitives;
using Bibliotheca.Server.Gateway.Core.Exceptions;
using Microsoft.Extensions.Options;
using Bibliotheca.Server.Gateway.Core.Parameters;
using Autofac.Core;
using Bibliotheca.Server.Gateway.Core.HttpClients;
using Bibliotheca.Server.Gateway.Core.Services;
using System;
using Microsoft.Extensions.Logging;

namespace Bibliotheca.Server.Gateway.Core.DependencyInjection
{
    public class InjectionModule : Autofac.Module
    {
        private readonly IConfigurationRoot _configuration;
        private readonly IServiceCollection _serviceCollection;

        public InjectionModule(IServiceCollection serviceCollection, IConfigurationRoot configuration)
        {
            _serviceCollection = serviceCollection;
            _configuration = configuration;
        }

        protected override void Load(ContainerBuilder builder)
        {
            RegisterServices(builder);
            RegisterDepositoryClients(builder);
            RegisterIndexerClients(builder);
            RegisterNightcrawlerClients(builder);
            RegisterHeimdallClients(builder);
        }

        private void RegisterServices(ContainerBuilder builder)
        {
            var serviceAssembly = typeof(InjectionModule).GetTypeInfo().Assembly;

            builder.RegisterAssemblyTypes(serviceAssembly)
                .Where(t => t.Name.EndsWith("Service"))
                .AsImplementedInterfaces()
                .InstancePerLifetimeScope();
        }

        private void RegisterHeimdallClients(ContainerBuilder builder)
        {
            var baseAddressParameter = new ResolvedParameter(
                    (pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "baseAddress",
                    (pi, ctx) => GetServiceAddress(ctx, "authorization"));

            var customHeadersParameter = new ResolvedParameter(
                    (pi, ctx) => pi.ParameterType == typeof(IDictionary<string, StringValues>) && pi.Name == "customHeaders",
                    (pi, ctx) => GetHttpHeaders(ctx));

            builder.RegisterType<UsersClient>().As<IUsersClient>()
                .WithParameter(baseAddressParameter)
                .WithParameter(customHeadersParameter);
        }

        private void RegisterNightcrawlerClients(ContainerBuilder builder)
        {
            var baseAddressParameter = new ResolvedParameter(
                    (pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "baseAddress",
                    (pi, ctx) => GetServiceAddress(ctx, "crawler"));

            var customHeadersParameter = new ResolvedParameter(
                    (pi, ctx) => pi.ParameterType == typeof(IDictionary<string, StringValues>) && pi.Name == "customHeaders",
                    (pi, ctx) => GetHttpHeaders(ctx));

            builder.RegisterType<NightcrawlerClient>().As<INightcrawlerClient>()
                .WithParameter(baseAddressParameter)
                .WithParameter(customHeadersParameter);
        }

        private void RegisterDepositoryClients(ContainerBuilder builder)
        {
            var baseAddressParameter = new ResolvedParameter(
                    (pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "baseAddress",
                    (pi, ctx) => GetServiceAddress(ctx, "depository"));

            var customHeadersParameter = new ResolvedParameter(
                    (pi, ctx) => pi.ParameterType == typeof(IDictionary<string, StringValues>) && pi.Name == "customHeaders",
                    (pi, ctx) => GetHttpHeaders(ctx));

            builder.RegisterType<ProjectsClient>().As<IProjectsClient>()
                .WithParameter(baseAddressParameter)
                .WithParameter(customHeadersParameter);

            builder.RegisterType<BranchesClient>().As<IBranchesClient>()
                .WithParameter(baseAddressParameter)
                .WithParameter(customHeadersParameter);

            builder.RegisterType<DocumentsClient>().As<IDocumentsClient>()
                .WithParameter(baseAddressParameter)
                .WithParameter(customHeadersParameter);
        }

        private void RegisterIndexerClients(ContainerBuilder builder)
        {
            var baseAddressParameter = new ResolvedParameter(
                    (pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "baseAddress",
                    (pi, ctx) => GetServiceAddress(ctx, "indexer"));

            var customHeadersParameter = new ResolvedParameter(
                    (pi, ctx) => pi.ParameterType == typeof(IDictionary<string, StringValues>) && pi.Name == "customHeaders",
                    (pi, ctx) => GetHttpHeaders(ctx));

            builder.RegisterType<SearchClient>().As<ISearchClient>()
                .WithParameter(baseAddressParameter)
                .WithParameter(customHeadersParameter);
        }

        private static IDictionary<string, StringValues> GetHttpHeaders(IComponentContext c)
        {
            var httpContextAccessor = c.Resolve<IHttpContextAccessor>();
            var httpContext = httpContextAccessor.HttpContext;

            IDictionary<string, StringValues> headers = null;
            if (httpContext != null && httpContext.Request != null)
            {
                headers = httpContext.Request.Headers as IDictionary<string, StringValues>;
            }

            return headers;
        }

        private static string GetServiceAddress(IComponentContext c, string serviceTag)
        {
            var logger = c.Resolve<ILogger<InjectionModule>>();
            try
            {    
                logger.LogInformation($"Getting address for '{serviceTag}' microservice.");

                var servicesService = c.Resolve<IServicesService>();
                var instance = servicesService.GetServiceInstanceAsync(serviceTag).GetAwaiter().GetResult();
                if (instance == null)
                {
                    logger.LogWarning($"Address for '{serviceTag}' microservice wasn't retrieved.");
                    return null;
                }

                var address = $"http://{instance.Address}:{instance.Port}/api/";
                logger.LogInformation($"Address for '{serviceTag}' microservice was retrieved ({address}).");
                return address;
            }
            catch(Exception exception)
            {
                logger.LogError($"Address for '{serviceTag}' microservice wasn't retrieved. There was an exception during retrieving address.");
                logger.LogError($"Exception: {exception.Message}");
                if(exception.InnerException != null)
                {
                    logger.LogError($"Inner exception: {exception.InnerException.Message}");
                }

                return null;
            }
        }
    }
}<commit_msg>Change log.<commit_after>﻿using Autofac;
using System.Reflection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Bibliotheca.Server.ServiceDiscovery.ServiceClient;
using System.Linq;
using Microsoft.AspNetCore.Http;
using System.Collections.Generic;
using Microsoft.Extensions.Primitives;
using Bibliotheca.Server.Gateway.Core.Exceptions;
using Microsoft.Extensions.Options;
using Bibliotheca.Server.Gateway.Core.Parameters;
using Autofac.Core;
using Bibliotheca.Server.Gateway.Core.HttpClients;
using Bibliotheca.Server.Gateway.Core.Services;
using System;
using Microsoft.Extensions.Logging;

namespace Bibliotheca.Server.Gateway.Core.DependencyInjection
{
    public class InjectionModule : Autofac.Module
    {
        private readonly IConfigurationRoot _configuration;
        private readonly IServiceCollection _serviceCollection;

        public InjectionModule(IServiceCollection serviceCollection, IConfigurationRoot configuration)
        {
            _serviceCollection = serviceCollection;
            _configuration = configuration;
        }

        protected override void Load(ContainerBuilder builder)
        {
            RegisterServices(builder);
            RegisterDepositoryClients(builder);
            RegisterIndexerClients(builder);
            RegisterNightcrawlerClients(builder);
            RegisterHeimdallClients(builder);
        }

        private void RegisterServices(ContainerBuilder builder)
        {
            var serviceAssembly = typeof(InjectionModule).GetTypeInfo().Assembly;

            builder.RegisterAssemblyTypes(serviceAssembly)
                .Where(t => t.Name.EndsWith("Service"))
                .AsImplementedInterfaces()
                .InstancePerLifetimeScope();
        }

        private void RegisterHeimdallClients(ContainerBuilder builder)
        {
            var baseAddressParameter = new ResolvedParameter(
                    (pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "baseAddress",
                    (pi, ctx) => GetServiceAddress(ctx, "authorization"));

            var customHeadersParameter = new ResolvedParameter(
                    (pi, ctx) => pi.ParameterType == typeof(IDictionary<string, StringValues>) && pi.Name == "customHeaders",
                    (pi, ctx) => GetHttpHeaders(ctx));

            builder.RegisterType<UsersClient>().As<IUsersClient>()
                .WithParameter(baseAddressParameter)
                .WithParameter(customHeadersParameter);
        }

        private void RegisterNightcrawlerClients(ContainerBuilder builder)
        {
            var baseAddressParameter = new ResolvedParameter(
                    (pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "baseAddress",
                    (pi, ctx) => GetServiceAddress(ctx, "crawler"));

            var customHeadersParameter = new ResolvedParameter(
                    (pi, ctx) => pi.ParameterType == typeof(IDictionary<string, StringValues>) && pi.Name == "customHeaders",
                    (pi, ctx) => GetHttpHeaders(ctx));

            builder.RegisterType<NightcrawlerClient>().As<INightcrawlerClient>()
                .WithParameter(baseAddressParameter)
                .WithParameter(customHeadersParameter);
        }

        private void RegisterDepositoryClients(ContainerBuilder builder)
        {
            var baseAddressParameter = new ResolvedParameter(
                    (pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "baseAddress",
                    (pi, ctx) => GetServiceAddress(ctx, "depository"));

            var customHeadersParameter = new ResolvedParameter(
                    (pi, ctx) => pi.ParameterType == typeof(IDictionary<string, StringValues>) && pi.Name == "customHeaders",
                    (pi, ctx) => GetHttpHeaders(ctx));

            builder.RegisterType<ProjectsClient>().As<IProjectsClient>()
                .WithParameter(baseAddressParameter)
                .WithParameter(customHeadersParameter);

            builder.RegisterType<BranchesClient>().As<IBranchesClient>()
                .WithParameter(baseAddressParameter)
                .WithParameter(customHeadersParameter);

            builder.RegisterType<DocumentsClient>().As<IDocumentsClient>()
                .WithParameter(baseAddressParameter)
                .WithParameter(customHeadersParameter);
        }

        private void RegisterIndexerClients(ContainerBuilder builder)
        {
            var baseAddressParameter = new ResolvedParameter(
                    (pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "baseAddress",
                    (pi, ctx) => GetServiceAddress(ctx, "indexer"));

            var customHeadersParameter = new ResolvedParameter(
                    (pi, ctx) => pi.ParameterType == typeof(IDictionary<string, StringValues>) && pi.Name == "customHeaders",
                    (pi, ctx) => GetHttpHeaders(ctx));

            builder.RegisterType<SearchClient>().As<ISearchClient>()
                .WithParameter(baseAddressParameter)
                .WithParameter(customHeadersParameter);
        }

        private static IDictionary<string, StringValues> GetHttpHeaders(IComponentContext c)
        {
            var httpContextAccessor = c.Resolve<IHttpContextAccessor>();
            var httpContext = httpContextAccessor.HttpContext;

            IDictionary<string, StringValues> headers = null;
            if (httpContext != null && httpContext.Request != null)
            {
                headers = httpContext.Request.Headers as IDictionary<string, StringValues>;
            }

            return headers;
        }

        private static string GetServiceAddress(IComponentContext c, string serviceTag)
        {
            var logger = c.Resolve<ILogger<InjectionModule>>();
            try
            {    
                logger.LogInformation($"Getting address for '{serviceTag}' microservice.");

                var servicesService = c.Resolve<IServicesService>();
                var instance = servicesService.GetServiceInstanceAsync(serviceTag).GetAwaiter().GetResult();
                if (instance == null)
                {
                    logger.LogWarning($"Address for '{serviceTag}' microservice wasn't retrieved.");
                    return null;
                }

                var address = $"http://{instance.Address}:{instance.Port}/api/";
                logger.LogInformation($"Address for '{serviceTag}' microservice was retrieved ({address}).");
                return address;
            }
            catch(Exception exception)
            {
                logger.LogError($"Address for '{serviceTag}' microservice wasn't retrieved. There was an exception during retrieving address.");
                logger.LogError($"Exception: {exception}");
                if(exception.InnerException != null)
                {
                    logger.LogError($"Inner exception: {exception.InnerException}");
                }

                return null;
            }
        }
    }
}
{'fraction_non_alphanumeric': 0.09749753971601294, 'fraction_numerical': 0.0, 'mean_word_length': 2.3341926411999063, 'pattern_counts': {'":': 0, '<': 49, '<?xml version=': 0, '>': 83, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4335054', 'n_tokens_mistral': 3380, 'n_tokens_neox': 3248, 'n_words': 645}