﻿namespace Dike.Core.Configuration.Startup
{
    using Autofac;
    using Dike.Core.Dependency;
    using System;

    /// <summary>
    /// Extension methods for <see cref="IStartupConfiguration"/> interface.
    /// </summary>
    public static class StartupConfigurationExtensions
    {
        #region Methods

        /// <summary>
        /// Replaces a specific base service type by a custom service type.
        /// </summary>
        /// <param name="configuration">The configuration.</param>
        /// <param name="type">The type of the service.</param>
        /// <param name="impl">The type of the implementation.</param>
        /// <param name="lifetime">The dependency injection lifetime.</param>
        public static void ReplaceService(this IStartupConfiguration configuration, Type type, Type impl, DependencyLifetime lifetime = DependencyLifetime.SingleInstance)
        {
            switch (lifetime)
            {
                case DependencyLifetime.InstancePerDependency:
                    configuration.ReplaceService(
                        type,
                        (builder) =>
                            builder
                                .RegisterType(impl)
                                .AsSelf()
                                .As(type)
                                .InstancePerDependency()
                                .AddInterceptors());
                    break;

                default:
                    configuration.ReplaceService(
                        type,
                        (builder) =>
                            builder
                                .RegisterType(impl)
                                .AsSelf()
                                .As(type)
                                .SingleInstance()
                                .AddInterceptors());
                    break;
            }
        }

        /// <summary>
        /// Replaces a specific base service type by a custom service type.
        /// </summary>
        /// <typeparam name="TType">The type of the service.</typeparam>
        /// <typeparam name="TImpl">The type of the implementation.</typeparam>
        /// <param name="configuration">The configuration.</param>
        /// <param name="lifetime">The dependency injection lifetime.</param>
        public static void ReplaceService<TType, TImpl>(this IStartupConfiguration configuration, DependencyLifetime lifetime = DependencyLifetime.SingleInstance)
            where TType : class
            where TImpl : class, TType
            => configuration.ReplaceService(typeof(TType), typeof(TImpl), lifetime);

        /// <summary>
        /// Replaces a specific base service type by a custom service type.
        /// </summary>
        /// <typeparam name="TType">The type of the service.</typeparam>
        /// <param name="configuration">The configuration.</param>
        /// <param name="replaceAction">The action to resolve the new type. This action will be called by the <see cref="KernelModule.RegisterServices(Autofac.ContainerBuilder)"/> method.</param>
        public static void ReplaceService<TType>(this IStartupConfiguration configuration, Action<ContainerBuilder> replaceAction)
            where TType : class
            => configuration.ReplaceService(typeof(TType), replaceAction);

        #endregion Methods
    }
}