using Autofac;
using SlnMesnac.Repository;
using System.Reflection;
using TouchSocket.Sockets;

#region << 版 本 注 释 >>
/*--------------------------------------------------------------------
* 版权所有 (c) 2024 WenJY 保留所有权利。
* CLR版本：4.0.30319.42000
* 机器名称：LAPTOP-E0N2L34V
* 命名空间：SlnMesnac.Ioc
* 唯一标识：496f8d2b-70e3-4a05-ae18-a9b0fcd06b82
*
* 创建者：WenJY
* 电子邮箱：wenjy@mesnac.com
* 创建时间：2024-03-27 21:58:35
* 版本：V1.0.0
* 描述：
*
*--------------------------------------------------------------------
* 修改人：
* 时间：
* 修改说明：
*
* 版本：V1.0.0
*--------------------------------------------------------------------*/
#endregion << 版 本 注 释 >>
namespace SlnMesnac.Ioc
{
    /// <summary>
    /// Utility class for configuring dependency injection.
    /// </summary>
    public static class DependencyConfigurator
    {
        /// <summary>
        /// Configures dependency injection for the application.
        /// </summary>
        /// <param name="builder">The Autofac container builder.</param>
        public static void Configure(ContainerBuilder builder)
        {
            //注入Repository
            builder.RegisterGeneric(typeof(Repository<>)).As(typeof(Repository<>));
            RegisterImplementations(builder, Assembly.LoadFrom("SlnMesnac.Repository.dll"));

            //注入Plc
            RegisterTypeTransient(builder, Assembly.LoadFrom("SlnMesnac.Plc.dll"));

            //注入Rfid
            RegisterTypeTransient(builder, Assembly.LoadFrom("SlnMesnac.Rfid.dll"));

            //注入通用类
            RegisterType(builder, Assembly.LoadFrom("SlnMesnac.Common.dll"));

            //注入MQTT
            RegisterType(builder, Assembly.LoadFrom("SlnMesnac.Mqtt.dll"));

            //注入TouchSocket
            builder.RegisterType(typeof(TcpService));
            RegisterType(builder, Assembly.LoadFrom("SlnMesnac.TouchSocket.dll"));

            //注入业务类
            RegisterType(builder, Assembly.LoadFrom("SlnMesnac.Business.dll"));

            //注入代码生成
            RegisterType(builder, Assembly.LoadFrom("SlnMesnac.Generate.dll"));
        }


        /// <summary>
        /// 自动注入接口实现
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="assembly"></param>
        private static void RegisterImplementations(ContainerBuilder builder, Assembly assembly)
        {
            //自动注入仓储层的接口实现类
            var types = assembly.GetTypes()
                .Where(t => t.IsClass && !t.IsAbstract && !t.IsGenericType)
                .ToList();

            foreach (var type in types)
            {
                var interfaces = type.GetInterfaces();

                foreach (var @interface in interfaces)
                {
                    builder.RegisterType(type).As(@interface);
                }
            }
        }

        /// <summary>
        /// 自动注入自定义类、抽象类
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="assembly"></param>
        private static void RegisterType(ContainerBuilder builder, Assembly assembly)
        {
            var types = assembly.GetTypes()
                .Where(t => t.IsClass && !t.IsAbstract && !t.IsGenericType)
                .ToList();

            foreach (var type in types)
            {
                var interfaces = type.GetInterfaces();
                var baseType = type.BaseType;

                #region 只注入抽象类 Delete By wenjy 2024-03-27
                //if (baseType != null && baseType.IsAbstract && baseType == typeof(PlcAbsractFactory)) 
                //{
                //    builder.RegisterType(type);
                //}
                #endregion


                if (!typeof(Delegate).IsAssignableFrom(type)) //不注入委托事件
                {
                    builder.RegisterType(type).SingleInstance();
                }
            }
        }

        private static void RegisterTypeTransient(ContainerBuilder builder, Assembly assembly)
        {
            var types = assembly.GetTypes()
                .Where(t => t.IsClass && !t.IsAbstract && !t.IsGenericType)
                .ToList();

            foreach (var type in types)
            {
                var interfaces = type.GetInterfaces();
                var baseType = type.BaseType;

                if (!typeof(Delegate).IsAssignableFrom(type))
                {
                    builder.RegisterType(type);
                }
            }
        }
    }
}
