using System;
using System.Reflection;
using Apache.NMS;
using Microsoft.VisualBasic;

namespace tcEAI_C
{

    /// <summary>
/// 20211027 13871,共用功能
/// </summary>
    public class clsCom
    {

        /// <summary>
    /// 20211027 13871,Reflection方法
    /// </summary>
    /// <param name="strComponent">DLL Name</param>
    /// <param name="strClassName">Class Name</param>
    /// <param name="strMethodName">Function Name</param>
    /// <param name="mi"></param>
    /// <param name="obj"></param>
    /// <returns></returns>
        public static bool DetermineCustomized_Constructor(string strComponent, string strClassName, string strMethodName, ref MethodInfo mi, ref object obj)
        {
            bool DetermineCustomized_ConstructorRet = default(bool);
            bool blnResult = false;

            DetermineCustomized_ConstructorRet = false;
            try
            {
                blnResult = DetermineMethod_Constructor(strComponent, strClassName, strMethodName, ref mi, ref obj);
            }
            catch (Exception ex)
            {
            }

            finally
            {
                DetermineCustomized_ConstructorRet = blnResult;
            }

            return DetermineCustomized_ConstructorRet;

        }

        /// <summary>
    /// 20211027 13871,Reflection找出Method
    /// </summary>
        public static bool DetermineMethod_Constructor(string strComponent, string strClassName, string strMethodName, ref MethodInfo mi, ref object obj)
        {
            string strAppBase = AppDomain.CurrentDomain.BaseDirectory;
            string strFilePath = "";
            Assembly mainAssembly;
            Type t;
            Type[] argumentTypes;
            ConstructorInfo ctor;

            MethodInfo[] aryMethos;

            try
            {
                strFilePath = strAppBase.TrimEnd('\\') + @"\bin\" + strComponent;
                mainAssembly = Assembly.LoadFrom(strFilePath);
                t = mainAssembly.GetType(mainAssembly.GetName().Name + "." + strClassName, true, true);
                // 20211211 13871,支援Module
                if (t.GetConstructors().Length > 0)
                {
                    argumentTypes = Type.EmptyTypes;
                    ctor = t.GetConstructor(argumentTypes);
                    obj = ctor.Invoke(new object[] { });
                }
                strMethodName = Strings.Replace(strMethodName, ".", "_");
                aryMethos = t.GetMethods();
                foreach (MethodInfo item in aryMethos)
                {
                    if ((strMethodName.ToUpper() ?? "") == (item.Name.ToUpper() ?? ""))
                    {
                        mi = item;
                        return true;
                    }
                }

                if (mi == null)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        /// <summary>
    /// 20211027 13871,取得Method的參數預設值陣列
    /// </summary>
    /// <param name="strComponent">DLL Name,可不傳副檔名,會自動補.dll</param>
    /// <param name="strClassName">Class Name</param>
    /// <param name="strMethodName">Method Name</param>
    /// <returns></returns>
        public static object[] funGetMethodParameters(string strComponent, string strClassName, string strMethodName)
        {
            object[] funGetMethodParametersRet = default(object[]);
            try
            {
                var mi = default(MethodInfo);
                var obj = default(object);
                if (!strComponent.ToUpper().Contains(".DLL"))
                {
                    strComponent = strComponent + ".dll";
                }

                if (!DetermineCustomized_Constructor(strComponent, strClassName, strMethodName, ref mi, ref obj))
                {
                    throw new iMESException.MESException("0000-200003", strComponent + "." + strClassName + "," + strMethodName + " [%METHOD%] [%NOT FOUND%]");
                }

                int iParameterLength = mi.GetParameters().Length;
                var aryParameter = new object[iParameterLength];
                for (int i = 0, loopTo = mi.GetParameters().Length - 1; i <= loopTo; i++)
                    aryParameter[i] = mi.GetParameters()[i].DefaultValue;
                funGetMethodParametersRet = aryParameter;
            }
            catch (Exception ex)
            {
                throw;
            }

            return funGetMethodParametersRet;
        }

        /// <summary>
    /// 20211027 13871,執行指定DLL、Class、Method,無法執行多載Method
    /// </summary>
    /// <param name="strComponent">DLL Name,可不傳副檔名,會自動補.dll</param>
    /// <param name="strClassName">Class Name</param>
    /// <param name="strMethodName">Method Name</param>
    /// <param name="aryParameters"></param>
        public static object funExecuteMethod(string strComponent, string strClassName, string strMethodName, ref object[] aryParameters)
        {
            object funExecuteMethodRet = default(object);
            try
            {
                var mi = default(MethodInfo);
                var obj = default(object);
                if (!strComponent.ToUpper().Contains(".DLL"))
                {
                    strComponent = strComponent + ".dll";
                }

                if (!DetermineCustomized_Constructor(strComponent, strClassName, strMethodName, ref mi, ref obj))
                {
                    throw new iMESException.MESException("0000-200003", strComponent + "." + strClassName + "," + strMethodName + " [%METHOD%] [%NOT FOUND%]");
                }

                funExecuteMethodRet = mi.Invoke(obj, aryParameters);
            }

            catch (Exception ex)
            {
                ex = funGetRealException(ex);
                throw ex;
            }

            return funExecuteMethodRet;
        }

        // 20211208 13871,從clsEAP移植
        public static Exception funGetRealException(Exception ex)
        {
            Exception funGetRealExceptionRet = default(Exception);
            try
            {
                funGetRealExceptionRet = ex;

                if (ex is TargetInvocationException && ex.InnerException != null)
                {
                    funGetRealExceptionRet = funGetRealException(ex.InnerException);
                }
            }
            catch (Exception ex2)
            {
                throw;
            }

            return funGetRealExceptionRet;
        }

    }
}