using System;
using System.Collections.Generic;
using System.Data.Common;
using DapperORM.Enums;

namespace DapperORM.ORMExtention
{
    /// <summary>
    /// DbProviderFactory工厂类
    /// </summary>
    public class ProviderFactory
    {
        /// <summary>
        /// 数据库驱动字段
        /// </summary>
        private static Dictionary<DbProviderType, string> _ProviderInvariantNames = new Dictionary<DbProviderType, string>();

        /// <summary>
        /// 驱动工厂字段
        /// </summary>
        private static Dictionary<DbProviderType, DbProviderFactory> _ProviderFactoies = new Dictionary<DbProviderType, DbProviderFactory>(20);

        static ProviderFactory()
        {
            //加载已知的数据库访问类的程序集
            _ProviderInvariantNames.Add(DbProviderType.SqlServer, "System.Data.SqlClient");
            _ProviderInvariantNames.Add(DbProviderType.OleDb, "System.Data.OleDb");
            _ProviderInvariantNames.Add(DbProviderType.ODBC, "System.Data.ODBC");
            _ProviderInvariantNames.Add(DbProviderType.Oracle, "Oracle.DataAccess.Client");
            _ProviderInvariantNames.Add(DbProviderType.MySql, "MySql.Data.MySqlClient");
            _ProviderInvariantNames.Add(DbProviderType.SQLite, "System.Data.SQLite");
            _ProviderInvariantNames.Add(DbProviderType.Firebird, "FirebirdSql.Data.Firebird");
            _ProviderInvariantNames.Add(DbProviderType.PostgreSql, "Npgsql");
            _ProviderInvariantNames.Add(DbProviderType.DB2, "IBM.Data.DB2.iSeries");
            _ProviderInvariantNames.Add(DbProviderType.Informix, "IBM.Data.Informix");
            _ProviderInvariantNames.Add(DbProviderType.SqlServerCe, "System.Data.SqlServerCe");
        }

        /// <summary>
        /// 获取指定数据库类型对应的程序集名称
        /// </summary>
        /// <param name="providerType">数据库类型枚举</param>
        /// <returns></returns>
        public static string GetProviderInvariantName(DbProviderType providerType)
        {
            return _ProviderInvariantNames[providerType];
        }

        /// <summary>
        /// 获取指定类型的数据库对应的DbProviderFactory
        /// </summary>
        /// <param name="providerType">数据库类型枚举</param>
        /// <returns></returns>
        public static DbProviderFactory GetDbProviderFactory(DbProviderType providerType)
        {
            //如果还没有加载，则加载该DbProviderFactory
            if (!_ProviderFactoies.ContainsKey(providerType))
            {
                _ProviderFactoies.Add(providerType, ImportDbProviderFactory(providerType));
            }
            return _ProviderFactoies[providerType];
        }

        /// <summary>
        /// 加载指定数据库类型的DbProviderFactory
        /// </summary>
        /// <param name="providerType">数据库类型枚举</param>
        /// <returns></returns>
        private static DbProviderFactory ImportDbProviderFactory(DbProviderType providerType)
        {
            string providerName = _ProviderInvariantNames[providerType];

            DbProviderFactory factory = null;

            try
            {
                //从全局程序集中查找
                factory = DbProviderFactories.GetFactory(providerName);
            }
            catch (ArgumentException e)
            {
                factory = null;
            }
            return factory;
        }
    }
}
