/*
 * OpenAPI Petstore
 *
 * This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\
 *
 * The version of the OpenAPI document: 1.0.0
 * Generated by: https://github.com/openapitools/openapi-generator.git
 */

using System;
using System.Linq;
using Microsoft.Extensions.DependencyInjection;
using Org.OpenAPITools.Client;
using Org.OpenAPITools.Api;

namespace Org.OpenAPITools.Extensions
{
    /// <summary>
    /// Extension methods for IServiceCollection
    /// </summary>
    public static class IServiceCollectionExtensions
    {
        /// <summary>
        /// Add the api to your host builder.
        /// </summary>
        /// <param name="services"></param>
        /// <param name="options"></param>
        public static void AddApi<TAnotherFakeApi, TDefaultApi, TFakeApi, TFakeClassnameTags123Api, TPetApi, TStoreApi, TUserApi>(this IServiceCollection services, Action<HostConfiguration<TAnotherFakeApi, TDefaultApi, TFakeApi, TFakeClassnameTags123Api, TPetApi, TStoreApi, TUserApi>> options)
            where TAnotherFakeApi : class, IApi.IAnotherFakeApi
            where TDefaultApi : class, IApi.IDefaultApi
            where TFakeApi : class, IApi.IFakeApi
            where TFakeClassnameTags123Api : class, IApi.IFakeClassnameTags123Api
            where TPetApi : class, IApi.IPetApi
            where TStoreApi : class, IApi.IStoreApi
            where TUserApi : class, IApi.IUserApi
        {
            HostConfiguration<TAnotherFakeApi, TDefaultApi, TFakeApi, TFakeClassnameTags123Api, TPetApi, TStoreApi, TUserApi> config = new HostConfiguration<TAnotherFakeApi, TDefaultApi, TFakeApi, TFakeClassnameTags123Api, TPetApi, TStoreApi, TUserApi>(services);
            options(config);
            AddApi(services, config);
        }

        /// <summary>
        /// Add the api to your host builder.
        /// </summary>
        /// <param name="services"></param>
        /// <param name="options"></param>
        public static void AddApi(this IServiceCollection services, Action<HostConfiguration<AnotherFakeApi, DefaultApi, FakeApi, FakeClassnameTags123Api, PetApi, StoreApi, UserApi>> options)
        {
            HostConfiguration<AnotherFakeApi, DefaultApi, FakeApi, FakeClassnameTags123Api, PetApi, StoreApi, UserApi> config = new HostConfiguration<AnotherFakeApi, DefaultApi, FakeApi, FakeClassnameTags123Api, PetApi, StoreApi, UserApi>(services);
            options(config);
            AddApi(services, config);
        }

        internal static void AddApi<TAnotherFakeApi, TDefaultApi, TFakeApi, TFakeClassnameTags123Api, TPetApi, TStoreApi, TUserApi>(IServiceCollection services, HostConfiguration<TAnotherFakeApi, TDefaultApi, TFakeApi, TFakeClassnameTags123Api, TPetApi, TStoreApi, TUserApi> host)
            where TAnotherFakeApi : class, IApi.IAnotherFakeApi
            where TDefaultApi : class, IApi.IDefaultApi
            where TFakeApi : class, IApi.IFakeApi
            where TFakeClassnameTags123Api : class, IApi.IFakeClassnameTags123Api
            where TPetApi : class, IApi.IPetApi
            where TStoreApi : class, IApi.IStoreApi
            where TUserApi : class, IApi.IUserApi
        {
            if (!host.HttpClientsAdded)
                host.AddApiHttpClients();

            services.AddSingleton<CookieContainer>();

            // ensure that a token provider was provided for this token type
            // if not, default to RateLimitProvider
            var containerServices = services.Where(s => s.ServiceType.IsGenericType &&
                s.ServiceType.GetGenericTypeDefinition().IsAssignableFrom(typeof(TokenContainer<>))).ToArray();

            foreach(var containerService in containerServices)
            {
                var tokenType = containerService.ServiceType.GenericTypeArguments[0];

                var provider = services.FirstOrDefault(s => s.ServiceType.IsAssignableFrom(typeof(TokenProvider<>).MakeGenericType(tokenType)));

                if (provider == null)
                {
                    services.AddSingleton(typeof(RateLimitProvider<>).MakeGenericType(tokenType));
                    services.AddSingleton(typeof(TokenProvider<>).MakeGenericType(tokenType), 
                        s => s.GetRequiredService(typeof(RateLimitProvider<>).MakeGenericType(tokenType)));
                }
            }
        }
    }
}
