using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Resources;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Xml;
using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
using static iMESCore.Base.iMESComXML;
using static iMESCore.Base.iMESConst;

namespace AutoRunLib_C
{

    static class modAutoRunLibrary
    {
        public enum GroupType
        {
            UserGroup = 0,       // 使用者群組
            IssueGroup = 1,          // 簽核群組
            EquipmentGroup = 2,      // 設備工程師群組
            InventoryGroup = 3,      // 庫房工程師群組
            ReportGroup = 4,         // 報表使用群組
            ERFDispositionGroup = 5, // 異常處理群組
            ERFMailccGroup = 6      // 附件收件人群組
        }

        private static string InXml, OutXml, strIdentity, strParameter, XmlData, XmlSchema;


        #region Invoke

        /// <summary>
        /// 叫用Web Service, 並回傳Response XML
        /// </summary>
        /// <param name="Method">要呼叫哪一個WebService的方法, ex: wsWIP.LoadLotBasis</param>
        /// <param name="InXml">InXml</param>
        /// <param name="Customize">是否客製的WebService</param>
        /// <returns></returns>
        /// <remarks>
        /// 2019/08/22 OwenLiu, Mantis:0061402, 修正WS加上CI/CO執行時間紀錄 運作邏輯後AutoRun Servive呼叫WS失敗的問題
        /// </remarks>
        public static string InvokeSrv(string Method, string InXml, bool Customize = false, int TimeOut = defInteger, bool LogOn = false)
        {

            object result;

            try
            {

                using (var ws = new wsInvoke.wsInvoke())
                {
                    ws.Url = modWIN.LocalizeWebService(ws.Url.ToString(), Customize);
                    ws.EnableDecompression = true;

                    if (TimeOut != defInteger)
                    {
                        ws.Timeout = TimeOut;
                    }

                    result = ws.invokeSrv(Method, new object[] { InXml, LogOn });
                }
            }

            catch (Exception ex)
            {
                throw;
            }

            return Conversions.ToString(result);

        }

        /// <summary>
        /// 叫用Web Service, 回傳Response XML
        /// </summary>
        /// <param name="Method">要呼叫哪一個WebService的方法, ex: wsWIP.LoadLotBasis</param>
        /// <param name="InXml">InXml</param>
        /// <param name="buffer">用來取回byte資料或傳入byte資料</param>
        /// <param name="Customize">是否客製的WebService</param>
        /// <remarks>
        /// 2019/08/22 OwenLiu, Mantis:0061402, 修正WS加上CI/CO執行時間紀錄 運作邏輯後AutoRun Servive呼叫WS失敗的問題
        /// </remarks>
        public static string InvokeSrv(string Method, string InXml, byte[] buffer, bool Customize = false, int TimeOut = defInteger, bool LogOn = false)
        {

            object result;

            try
            {

                using (var ws = new wsInvoke.wsInvoke())
                {
                    ws.Url = modWIN.LocalizeWebService(ws.Url.ToString(), Customize);
                    ws.EnableDecompression = true;

                    if (TimeOut != defInteger)
                    {
                        ws.Timeout = TimeOut;
                    }

                    result = ws.invokeSrv(Method, new object[] { InXml, buffer, LogOn });
                }
            }

            catch (Exception ex)
            {
                throw;
            }

            return Conversions.ToString(result);

        }

        /// <summary>
        /// 叫用Web Service, 並回傳Response XML
        /// </summary>
        /// <param name="Method">要呼叫哪一個WebService的方法, ex: wsWIP.LoadLotBasis</param>
        /// <param name="InXml">InXml</param>
        /// <param name="pDataSet">接收結果的DataSet</param>
        /// <param name="Customize">是否客製的WebService</param>
        /// <returns></returns>
        public static string InvokeSrv(string Method, string InXml, ref DataSet pDataSet, bool Customize = false)
        {

            object result;

            try
            {

                using (var ws = new wsInvoke.wsInvoke())
                {
                    ws.Url = modWIN.LocalizeWebService(ws.Url.ToString(), Customize);
                    ws.EnableDecompression = true;
                    result = ws.invokeSrv_DataSet(Method, InXml, ref pDataSet);
                }
            }

            catch (Exception ex)
            {
                throw;
            }

            return Conversions.ToString(result);

        }

        public static string InvokeSrv_GuardServer(bool Customize = false)
        {
            object result;

            try
            {

                using (var ws = new wsInvoke.wsInvoke())
                {
                    ws.Url = modWIN.LocalizeWebService(ws.Url.ToString(), Customize);
                    ws.EnableDecompression = true;
                    result = ws.Invoke_GuardServer_Process();

                }
            }

            catch (Exception ex)
            {
                throw;
            }

            return Conversions.ToString(result);
        }

        #endregion


        /// <summary>
        /// EAI 檢核編碼(MD5)
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public static string GetRequestKey(string input)
        {

            const string ID = "28682266"; // 鼎新統編

            string key = "";
            var md5Hasher = MD5.Create(); // 建立MD5物件

            try
            {

                input += ID;

                // 將input轉換成MD5，並且以Bytes傳回，由於ComputeHash只接受Bytes型別參數，所以要先轉型別為Bytes
                byte[] data = md5Hasher.ComputeHash(Encoding.UTF8.GetBytes(input));

                // 建立StringBuilder物件
                var sb = new StringBuilder();

                // 將Bytes轉型別為String，並且以16進位存放
                for (int i = 0, loopTo = data.Length - 1; i <= loopTo; i++)
                    sb.Append(data[i].ToString("x2"));

                key = sb.ToString();
            }

            catch (Exception ex)
            {
                throw;
            }
            finally
            {
                md5Hasher = null;
            }

            return key;

        }


        /// <summary>
        /// 紀錄Transaction
        /// </summary>
        /// <param name="InXml"></param>
        /// <param name="OutXml"></param>
        /// <param name="ModuleID"></param>
        /// <param name="FunctionID"></param>
        /// <param name="Result"></param>
        /// <param name="KeyValue"></param>
        /// <returns></returns>
        /// <remarks></remarks>
        public static bool addTransactionLog(string InXml, string OutXml, string TransactionID, string ModuleID, string FunctionID, string ComputerName, string CurUserNo, string SendTime, string Result, string KeyValue, string ExceptionFun, string strException = null)
        {
            bool addTransactionLogRet = default(bool);
            try
            {
                using (var wsERP = new wsERP_MES.wsMES())
                {
                    wsERP.Url = modWIN.LocalizeWebService_ERP(wsERP.Url.ToString());
                    wsERP.EnableDecompression = true;
                    if (wsERP.addTransactionLog(InXml, OutXml, TransactionID, ModuleID, FunctionID, ComputerName, CurUserNo, SendTime, Result, KeyValue, ExceptionFun, ref strException) == true)
                    {
                        addTransactionLogRet = true;
                    }
                    else
                    {
                        addTransactionLogRet = false;
                    }
                }
            }
            catch (Exception ex)
            {
                addTransactionLogRet = false;
            }

            return addTransactionLogRet;
        }
        /// <summary>
        /// 紀錄Transaction
        /// </summary>
        public static bool addTransactionLog_ErrorCode(string InXml, string OutXml, string TransactionID, string ModuleID, string FunctionID, string ComputerName, string CurUserNo, string SendTime, string Result, string KeyValue, string ExceptionFun, string strException = null, string ErrorCode = "0000-999999", string LogClass = null)
        {
            bool addTransactionLog_ErrorCodeRet = default(bool);
            try
            {
                using (var wsERP = new wsERP_MES.wsMES())
                {
                    wsERP.Url = modWIN.LocalizeWebService_ERP(wsERP.Url.ToString());
                    wsERP.EnableDecompression = true;
                    if (wsERP.addTransactionLog_ErrorCode(InXml, OutXml, TransactionID, ModuleID, FunctionID, ComputerName, CurUserNo, SendTime, Result, KeyValue, ExceptionFun, ref strException, ErrorCode, LogClass) == true)
                    {
                        addTransactionLog_ErrorCodeRet = true;
                    }
                    else
                    {
                        addTransactionLog_ErrorCodeRet = false;
                    }
                }
            }
            catch (Exception ex)
            {
                addTransactionLog_ErrorCodeRet = false;
            }

            return addTransactionLog_ErrorCodeRet;
        }


        // =====Elvis ,0091128: [605][CP+FT] E10ICD整合問題_AutoRun主檔拋轉的ERP交易紀錄exception時紀錄不正確
        #region --- Combine (Exception, Message) ---

        public static bool ChgTranslateException(ref List<ArrayList> Exception, ref string strExceptionSysmsg, ref string strExceptionMesmsg, ref string strExceptionStack)
        {
            bool ChgTranslateExceptionRet = default(bool);

            try
            {
                foreach (ArrayList al in Exception)
                {
                    // If strExceptionSysmsg <> String.Empty Then strExceptionSysmsg += Chr(10)
                    if (string.IsNullOrEmpty(Conversions.ToString(al[1])) == false)
                        strExceptionSysmsg += al[1].ToString();
                    // If String.IsNullOrEmpty(strExceptionMesmsg) = False Then strExceptionMesmsg += Chr(10)
                    if (string.IsNullOrEmpty(Conversions.ToString(al[2])) == false)
                    {
                        // 翻譯錯誤訊息
                        string strErrName_Rep = "";
                        string ErrorName = al[2].ToString();
                        if (Strings.InStr(ErrorName, "[%", CompareMethod.Text) > 0)
                        {
                            string strKey, strKeyValue;
                            int intStart, j, k, l;

                            intStart = 1;
                            j = 1;

                            while (j != 0)
                            {
                                j = Strings.InStr(intStart, ErrorName, "[%", CompareMethod.Text);
                                if (j == 0)
                                {
                                    strErrName_Rep += Strings.Mid(ErrorName, intStart);
                                }
                                else
                                {
                                    k = Strings.InStr(j + 2, ErrorName, "%]", CompareMethod.Text);
                                    if (k == 0)
                                    {
                                        // 找不到對應的結束字元.
                                        strErrName_Rep += Strings.Mid(ErrorName, intStart);
                                        j = 0;
                                    }
                                    else
                                    {
                                        // 檢查是否有不對稱的情況.
                                        l = Strings.InStr(j + 2, ErrorName, "[%", CompareMethod.Text);
                                        if (l == 0 || l > k)
                                        {
                                            strErrName_Rep += Strings.Mid(ErrorName, intStart, j - intStart);
                                            strKey = Strings.Mid(ErrorName, j + 2, k - j - 2);
                                            // 將Key執行語系轉換
                                            try
                                            {
                                                strKeyValue = "";
                                            }
                                            // strKeyValue = Resources.Resource.ResourceManager.GetString(strKey)
                                            catch (Exception ex)
                                            {
                                                strKeyValue = strKey;
                                            }
                                            if (string.IsNullOrEmpty(strKeyValue))
                                            {
                                                strErrName_Rep += strKey;
                                            }
                                            else
                                            {
                                                strErrName_Rep += strKeyValue;
                                            } // & "(" & strKey & ")"
                                              // 下次截取字串的起始位置
                                            intStart = k + 2;
                                        }
                                        else
                                        {
                                            // 不對稱,找到最內層的[%%]
                                            int m;
                                            // 在前面的條件下,一定找得到.
                                            m = Strings.InStrRev(ErrorName, "[%", k, CompareMethod.Text);
                                            // 擷出不轉換的字串.
                                            strErrName_Rep += Strings.Mid(ErrorName, intStart, m - intStart);
                                            strKey = Strings.Mid(ErrorName, m + 2, k - m - 2);
                                            // 將Key執行語系轉換
                                            try
                                            {
                                                strKeyValue = "";
                                            }
                                            // strKeyValue = Resources.Resource.ResourceManager.GetString(strKey)
                                            catch (Exception ex)
                                            {
                                                strKeyValue = strKey;
                                            }
                                            if (string.IsNullOrEmpty(strKeyValue))
                                            {
                                                strErrName_Rep += strKey;
                                            }
                                            else
                                            {
                                                strErrName_Rep += strKeyValue;
                                            } // & "(" & strKey & ")"
                                              // 下次截取字串的起始位置
                                            intStart = k + 2;
                                        }
                                    }
                                }
                            }
                        }
                        // strExceptionMesmsg += Chr(9) & Chr(9) & Chr(9) & Resources.Resource.ResourceManager.GetString(al.Item(2).ToString) & "(" & al.Item(2).ToString & ")"
                        strExceptionMesmsg += strErrName_Rep;
                    }

                    // If strExceptionStack <> String.Empty Then strExceptionStack += Chr(10)
                    if (string.IsNullOrEmpty(Conversions.ToString(al[3])) == false)
                        strExceptionStack += al[3].ToString();
                }

                ChgTranslateExceptionRet = true;
            }

            catch (Exception e1)
            {
                throw;
                ChgTranslateExceptionRet = false;
            }

            return ChgTranslateExceptionRet;

        }


        public static string CombineXMLResponse(string Identity, string ReturnValue = null, List<ArrayList> Exception = null, string Result = null, List<ArrayList> Message = null)
        {
            string CombineXMLResponseRet = default(string);

            try
            {
                // <response>
                CombineXMLResponseRet = "<response>";

                // <identity>
                if (string.IsNullOrEmpty(Identity))
                {
                    CombineXMLResponseRet += "<identity></identity>";
                }
                else
                {
                    CombineXMLResponseRet += "<identity>";
                    CombineXMLResponseRet += Identity;
                    CombineXMLResponseRet += "</identity>";
                }

                // <returnvalue>
                if (string.IsNullOrEmpty(ReturnValue))
                {
                    CombineXMLResponseRet += "<returnvalue></returnvalue>";
                }
                else
                {
                    CombineXMLResponseRet += "<returnvalue>";
                    CombineXMLResponseRet += ReturnValue;
                    CombineXMLResponseRet += "</returnvalue>";
                }

                // <result>
                if (string.IsNullOrEmpty(Result))
                {
                    CombineXMLResponseRet += "<result></result>";
                }
                else
                {
                    CombineXMLResponseRet += "<result>" + Result + "</result>";
                }

                // <exception>
                string strExceptionSysmsg = string.Empty;
                string strExceptionMesmsg = string.Empty;
                string strExceptionStack = string.Empty;

                if (Exception.Count == 0)
                {
                    CombineXMLResponseRet += "<exception></exception>";
                }
                else
                {
                    // 2016-12-01, Joe, Exception轉語系
                    ChgTranslateException(ref Exception, ref strExceptionSysmsg, ref strExceptionMesmsg, ref strExceptionStack);

                    CombineXMLResponseRet += "<exception>";
                    CombineXMLResponseRet += "<code></code>";
                    if (string.IsNullOrEmpty(strExceptionSysmsg) == true)
                    {
                        CombineXMLResponseRet += "<sysmsg></sysmsg>";
                    }
                    else
                    {
                        CombineXMLResponseRet += "<sysmsg>" + strExceptionSysmsg + '\n' + "</sysmsg>" + '\n';
                    }
                    if (string.IsNullOrEmpty(strExceptionMesmsg) == true)
                    {
                        CombineXMLResponseRet += "<mesmsg>" + strExceptionMesmsg + "</mesmsg>" + '\n';
                    }
                    else
                    {
                        CombineXMLResponseRet += "<mesmsg>" + strExceptionMesmsg + "</mesmsg>" + '\n';
                    }
                    if (string.IsNullOrEmpty(strExceptionStack))
                    {
                        CombineXMLResponseRet += "<stack></stack>";
                    }
                    else
                    {
                        // CombineXMLResponse += Chr(9) & Chr(9) & "<stack>" & Chr(10) & strExceptionStack & Chr(10) & Chr(9) & Chr(9) & "</stack>" & Chr(10) 
                        CombineXMLResponseRet += "<stack></stack>";
                    }
                    CombineXMLResponseRet += '\t' + "</exception>" + '\n';
                }

                // <message>
                string strMmsg = string.Empty;

                if (Message.Count == 0)
                {
                    CombineXMLResponseRet += '\t' + "<message></message>" + '\n';
                }
                else
                {
                    CombineXMLResponseRet += '\t' + "<message>" + '\n';
                    // 2016-12-01, Joe, Message轉語系
                    // Call ChgTranslateMessage(Message, strMmsg)

                    CombineXMLResponseRet += Conversions.ToString('\t') + '\t' + "<mcode></mcode>" + '\n';
                    CombineXMLResponseRet += Conversions.ToString('\t') + '\t' + "<mtype></mtype>" + '\n';
                    CombineXMLResponseRet += Conversions.ToString('\t') + '\t' + "<mmsg>" + strMmsg + "</mmsg>" + '\n';
                    CombineXMLResponseRet += '\t' + "</message>" + '\n';
                }

                CombineXMLResponseRet += "</response>" + '\n';
            }

            catch (Exception e1)
            {
                // 發生錯誤時丟回本身的Function Name及系統錯誤訊息
                // Throw 'New Exception("modWS.CombineXMLResponse: " & e1.Message)
                CombineXMLResponseRet = "<response>" + '\n';
                CombineXMLResponseRet += '\t' + "<identity></identity>" + '\n';
                CombineXMLResponseRet += '\t' + "<exception>" + '\n';
                CombineXMLResponseRet += Conversions.ToString('\t') + '\t' + "<code></code>" + '\n';
                CombineXMLResponseRet += Conversions.ToString('\t') + '\t' + "<sysmsg>" + '\n';
                CombineXMLResponseRet += Conversions.ToString('\t') + '\t' + '\t' + e1.Message + '\n';
                CombineXMLResponseRet += Conversions.ToString('\t') + '\t' + "</sysmsg>" + '\n';
                CombineXMLResponseRet += Conversions.ToString('\t') + '\t' + "<mesmsg>" + '\n';
                CombineXMLResponseRet += Conversions.ToString('\t') + '\t' + '\t' + "CombineXMLResponse;Fail" + '\n';
                CombineXMLResponseRet += Conversions.ToString('\t') + '\t' + "</mesmsg>" + '\n';
                CombineXMLResponseRet += Conversions.ToString('\t') + '\t' + "<stack>" + '\n';
                CombineXMLResponseRet += e1.StackTrace + '\n';
                CombineXMLResponseRet += Conversions.ToString('\t') + '\t' + "</stack>" + '\n';
                CombineXMLResponseRet += '\t' + "</exception>" + '\n';
                CombineXMLResponseRet += '\t' + "<message></message>" + '\n';
                CombineXMLResponseRet += "</response>";
            }

            return CombineXMLResponseRet;

        }

        public static bool combineException(ref List<ArrayList> arrException, string code = null, string sysmsg = null, string mesmsg = null, string stack = null)
        {
            bool result = false;
            try
            {
                var al = new ArrayList();

                al.Add(code);
                al.Add(sysmsg);
                al.Add(mesmsg);
                al.Add(stack);
                arrException.Add(al);
                result = true;
            }
            catch (Exception ex)
            {
                result = false;
            }

            return default(Boolean);

        }

        // Public Function combineMessage(
        // ByRef strMessage As List(Of ArrayList),
        // Optional ByVal mcode As String = Nothing,
        // Optional ByVal mtype As String = Nothing,
        // Optional ByVal mmsg As String = Nothing
        // ) As Boolean
        // Dim result As Boolean = False
        // Try
        // Dim al As New ArrayList
        // al.Add(mcode)
        // al.Add(mtype)
        // al.Add(mmsg)
        // strMessage.Add(al)
        // result = True
        // Catch ex As Exception
        // result = False
        // End Try
        // End Function

        #endregion
        // =====

        // 發Mail功能 非群組與群組發送
        public static string SendMultiEmail(ref string FileName, ref string EmailSubject, string EmailBody = defString, string GroupNo = defString, byte[] AttachFile = null, GroupType GroupType = GroupType.UserGroup)
        {
            string SendMultiEmailRet = default(string);
            // GroupType
            // 0:User Group (使用者群組)
            // 1:Issue Group (簽核群組) 
            // 2:Equipment Group(設備工程師群組) 
            // 3:Inventory Group(庫房工程師群組) 
            // 4:Report Group(報表使用群組) 
            // 5:ERF Disposition Group(異常處理群組) 
            // 6:ERF Mail ccGroup(附件收件人群組)

            try
            {

                strIdentity = CombineXMLIdentity(modWIN.gComputerName, "AUTORUN", DateTime.Now.ToString());
                strParameter = CombineXMLParameter("groupno", "GroupNo", "String", CInput(GroupNo), "");
                strParameter = strParameter + CombineXMLParameter("emailsubject", "EmailSubject", "String", EmailSubject, "");
                strParameter = strParameter + CombineXMLParameter("emailbody", "EmailBody", "String", EmailBody, "");
                strParameter = strParameter + CombineXMLParameter("grouptype", "GroupType", "Integer", GroupType.ToString(), "");
                strParameter = strParameter + CombineXMLParameter("attachfilename", "AttachFileName", "String", FileName, "");

                var XmlDoc = new XmlDocument();

                InXml = CombineXMLRequest(strIdentity, strParameter);

                // OutXml = wsWIP.SendEmailAndAttachFileToGroup(InXml, AttachFile)
                OutXml = InvokeSrv("wsWIP.SendEmailAndAttachFileToGroup", InXml, AttachFile);

                XmlDoc.LoadXml(OutXml);

                if (chkExecutionSuccess(XmlDoc))  // 找出Exception訊並顯示出來
                {
                    SendMultiEmailRet = "success";
                }
                else
                {
                    SendMultiEmailRet = "fail";
                }

                XmlDoc = null;
            }

            catch (Exception ex)
            {
                SendMultiEmailRet = "fail;" + ex.Message;
            }

            return SendMultiEmailRet;

        }

        #region --- 數值查核 ---

        public static bool funChkNumericIsValid(string pSourceText, bool AllowFloat = true, bool AllowContainsDot = true, bool AllowZeroValue = true, bool AllowMinus = true)
        {

            bool blnExecResult = false;
            decimal decInputValue = 0m;

            try
            {

                if (!Information.IsNumeric(pSourceText))
                {
                    blnExecResult = false;
                    return blnExecResult;
                }
                decInputValue = Convert.ToDecimal(pSourceText);

                if (!AllowMinus && decInputValue < 0m)
                {
                    blnExecResult = false;
                    return blnExecResult;
                }
                if (!AllowZeroValue && decInputValue == 0m)
                {
                    blnExecResult = false;
                    return blnExecResult;
                }
                if (!AllowFloat)
                {
                    if (decInputValue % 1m > 0m)
                    {
                        blnExecResult = false;
                        return blnExecResult;
                    }
                }

                if (!AllowContainsDot && !pSourceText.IndexOf(".").Equals(-1))
                {
                    blnExecResult = false;
                    return blnExecResult;
                }

                blnExecResult = true;
            }
            catch (Exception ex)
            {
                throw;
            }

            return blnExecResult;

        }

        #endregion
    }
}