using System;
using System.Data;
using System.Collections;
using System.Windows.Forms;

using Core.Mes.IBaseInterface;
using System.ComponentModel;
using System.Drawing;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Net.Sockets;
using System.Configuration;

namespace Core.Mes.ClientFrameWork
{
    /// <summary>
    /// RemotingHelp 的摘要说明。多进程切换
    /// </summary>
    public class RemotingHelp
    {
        public RemotingHelp()
        {

        }
        public DataSet ServerUrlList
        {
            set
            {
                DataSet ds = value;
                string BackupRemoteServerUrl = ConfigurationManager.AppSettings["BackupRemoteServerUrl"];

                if (ds != null || ds.Tables.Count > 0)
                {
                    _htServerUrlList = new Hashtable();
                    _htChildServerUrlList = new Hashtable();

                    foreach (DataRow dr in ds.Tables[0].Rows)
                    {
                        string url = dr["Url"].ToString() + "/" + dr["ServerName"];
                        List<string> urls = MultiTcpUrl(url);
                        _htServerUrlList.Add(dr["ServerName"].ToString(), urls);
                        //
                        //添加子进程的端口
                        //
                        if (!string.IsNullOrEmpty(BackupRemoteServerUrl))
                        {
                            string oldPort = TcpPort(url);
                            string newPort = TcpPort(BackupRemoteServerUrl);
                            string new_url = url.Replace(oldPort, newPort);
                            _htChildServerUrlList.Add(dr["ServerName"].ToString(), new_url);
                        }
                    }
                }
                ds.Dispose();
            }
        }
        private Hashtable _htServerUrlList = new Hashtable();
        private Hashtable _htRemoteServer = new Hashtable();

        /// <summary>
        /// 访问主进程服务
        /// </summary>
        private static bool AccessMainServer = true;
        #region 子进程服务
        private Hashtable _htChildServerUrlList = new Hashtable();
        private Hashtable _htChildRemoteServer = new Hashtable();
        #endregion

        private bool GetServer(string serverName)
        {
            try
            {
                if (!_htRemoteServer.Contains(serverName))
                {
                    List<string> urls = _htServerUrlList[serverName] as List<string>;
                    List<ICommon> iCommons = new List<ICommon>();

                    foreach (string url in urls)
                    {
                        ICommon iCommon = (ICommon)Activator.GetObject(typeof(ICommon), url);
                        iCommons.Add(iCommon);
                    }
                    _htRemoteServer.Add(serverName, iCommons);

                    //子进程服务
                    string childUrl = _htChildServerUrlList[serverName] == null ? "" : _htChildServerUrlList[serverName].ToString();
                    if (!string.IsNullOrEmpty(childUrl))
                    {
                        ICommon childICommon = (ICommon)Activator.GetObject(typeof(ICommon), childUrl);
                        _htChildRemoteServer.Add(serverName, childICommon);
                    }

                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }
            return true;
        }
        private bool MainServer = false;//主进程
        private bool ChildServer = false;//子进程
        public object ExecuteMethod(CallingMessage par, out string errorInfo)
        {
            errorInfo = "";

            if (!FindRemoteServer(par.ServerName))
            {
                errorInfo = "未找到请求的服务！";
                return null;
            }
            try
            {
                if (AccessMainServer)
                {
                    List<string> urls = _htServerUrlList[par.ServerName] as List<string>;
                    List<ICommon> iCommons = _htRemoteServer[par.ServerName] as List<ICommon>;
                    Random rd = new Random();
                    int index = rd.Next(iCommons.Count);
                    ICommon iCommon = iCommons[index];
                    string url = urls[index];
                    ReturnObject rtnObj = iCommon.MethodHandler(par, new ValidateInfo());
                    errorInfo = rtnObj.ErrMessage;
                    
                    MainServer = false;
                    return rtnObj.RealObject;
                }
                else
                {
                    ReturnObject rtnObj = (_htChildRemoteServer[par.ServerName] as ICommon).MethodHandler(par, new ValidateInfo());
                    errorInfo = rtnObj.ErrMessage;
                    ChildServer = false;
                    return rtnObj.RealObject;
                }

            }
            
            catch (System.Net.Sockets.SocketException ex)
            {
                //add longjing 10-9
                if (ex.ErrorCode == 10065)
                {
                    //MessageBox.Show("网络连接断开或存在问题!!");
                    errorInfo="网络连接已断开或存在异常，错误代码："+ex.ErrorCode;
                    return null;
                }
                //end

                if (MainServer && ChildServer)//主、子进程服务都挂掉
                {
                    #region  调用尝试恢复服务

                    CallingMessage temp_par = new CallingMessage();
                    temp_par.ServerName = "ServerCommon";
                    temp_par.ClassName = "Core.Mes.ServerCommon.UserInfoManager";
                    temp_par.MethodName = "getDBSrvTime";
                    temp_par.args = null;

                    temp_par.ServerType = MesServerType.IComponentContainServer;
                    temp_par.TransType = NetWorkTransType.Remoting;
                    temp_par.visitType = VisitType.Method;

                    ReConMainServer(temp_par);
                    ReConChildServer(temp_par);

                    #endregion
                    //errorInfo = ex.Message;
                    //add longjing
                    if (ex.ErrorCode == 10061)
                        errorInfo = "远程应用服务程序没有启动，错误代码：" + ex.ErrorCode;
                    else if (ex.ErrorCode == 10054)
                        errorInfo = "远程应用服务突然停止运行或者远程主机重新启动，错误代码：" + ex.ErrorCode;
                    else if (ex.ErrorCode == 10050)
                        errorInfo = "网络系统出现异常，错误代码：" + ex.ErrorCode;
                    else
                        errorInfo = ex.Message;
                    //end
                       
                    return null;
                }
                object obj = null;
                //连接发生异常尝试访问子进程服务。
                if (AccessMainServer == true && ex.ErrorCode == 10061)
                {
                    MainServer = true;//主进程挂掉
                    AccessMainServer = false;
                    obj = ExecuteMethod(par, out errorInfo);

                    //
                    //发送干掉主进程的命令 监听会重启操作
                    //
                    /*
                     * string strOut = "";
                    object obj = ExecuteMethod("ServerCommon", "Core.Mes.ServerCommon.UserInfoManager", "KillMainProcessAndRestart",
                             null, out strOut);
                     */
                }
                else if (AccessMainServer == false && ex.ErrorCode == 10061) //连接发生异常尝试访问主进程服务。
                {
                    ChildServer = true;//子进程挂掉
                    AccessMainServer = true;
                    obj = ExecuteMethod(par, out errorInfo);
                }

                return obj;
            }
            catch (Exception ex)
            {

                
                errorInfo = ex.Message;
                return null;
            }
        }
        void _RemotingHelp_OnComplete(object returnObj, string returnMsg)
        {
            if (string.IsNullOrEmpty(returnMsg))
            {
                AccessMainServer = true;
            }


        }
        #region 尝试重连服务 add maliang 2012-5-15
        /// <summary>
        /// 尝试连接主进程服务 
        /// </summary>
        /// <param name="par"></param>
        /// <returns>返回True服务连接失败。返回False服务连接成功</returns>
        public bool ReConMainServer(CallingMessage par)
        {
            string errorInfo = "";
            try
            {
                if (!FindRemoteServer(par.ServerName))
                {
                    errorInfo = "未找到请求的服务！";
                    return true;
                }
                List<string> urls = _htServerUrlList[par.ServerName] as List<string>;
                List<ICommon> iCommons = _htRemoteServer[par.ServerName] as List<ICommon>;
                Random rd = new Random();
                int index = rd.Next(iCommons.Count);
                ICommon iCommon = iCommons[index];
                string url = urls[index];
                ReturnObject rtnObj = iCommon.MethodHandler(par, new ValidateInfo());

                MainServer = false;//主进程好了
            }
            catch (Exception ex)
            {

                MainServer = true;//主进程仍然挂掉
            }
            return MainServer;
        }
        /// <summary>
        /// 尝试连接子进程服务 
        /// </summary>
        /// <param name="par"></param>
        /// <returns>返回True服务连接失败。返回False服务连接成功</returns>
        public bool ReConChildServer(CallingMessage par)
        {
            string errorInfo = "";
            try
            {
                if (!FindRemoteServer(par.ServerName))
                {
                    errorInfo = "未找到请求的服务！";
                    return true;
                }
                ReturnObject rtnObj = (_htChildRemoteServer[par.ServerName] as ICommon).MethodHandler(par, new ValidateInfo());
                errorInfo = rtnObj.ErrMessage;
                ChildServer = false;//子进程好了
            }
            catch (Exception ex)
            {

                ChildServer = true;//子进程仍然挂掉
            }
            return ChildServer;
        }
        #endregion
        public object ExecuteMethod(string serverName, string className, string methodName, object[] args, out string errorInfo)
        {
            //==	解析参数
            
            CallingMessage par = new CallingMessage();
            par.ServerName = serverName;
            par.ClassName = className;
            par.MethodName = methodName;
            par.args = args;

            par.ServerType = MesServerType.IComponentContainServer;
            par.TransType = NetWorkTransType.Remoting;
            par.visitType = VisitType.Method;

            errorInfo = "";

            
           return ExecuteMethod(par, out errorInfo);
        }


        private bool FindRemoteServer(string serverName)
        {
            if (!_htRemoteServer.Contains(serverName))
                return GetServerUrl(serverName);
            return true;
        }
        private bool GetServerUrl(string serverName)
        {
            if (!_htServerUrlList.Contains(serverName))
                return false;

            return GetServer(serverName);
        }
        public void InitServerUrlList(string serverName, string url)
        {
            if (_htServerUrlList.Count == 0)
            {
                List<string> strs = MultiTcpUrl(url);
                _htServerUrlList.Add(serverName, strs);
            }
            //
            //添加子进程的端口
            //
            string BackupRemoteServerUrl = ConfigurationManager.AppSettings["BackupRemoteServerUrl"];
            if (_htChildServerUrlList.Count == 0)
            {
                _htChildServerUrlList.Add(serverName, BackupRemoteServerUrl);
            }
        }


        #region add maliang 2012-5-4
        /// <summary>
        /// 
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        private List<string> MultiTcpUrl(string url)
        {

            List<string> strs = new List<string>();
            try
            {

                Regex r = new Regex(@"^\w+://[^/]+?(?<port>\d+)?/", RegexOptions.Compiled);
                string strPort = r.Match(url).Result("${port}");
                int iport = Convert.ToInt32(strPort);

                strs.Add(url);

                int iport_a = iport - 20;
                string url_a = url.Replace(strPort, iport_a.ToString());
                strs.Add(url_a);

                int iport_b = iport + 20;
                string url_b = url.Replace(strPort, iport_b.ToString());
                strs.Add(url_b);

                int iport_c = iport - 10;
                string url_c = url.Replace(strPort, iport_c.ToString());
                strs.Add(url_c);

                int iport_d = iport + 10;
                string url_d = url.Replace(strPort, iport_d.ToString());
                strs.Add(url_d);



            }
            catch
            {
                //dologs 匹配端口号失败。启用默认的地址。
                strs.Add(url);

            }
            return strs;
        }



        private string TcpPort(string url)
        {
            string strPort = string.Empty;
            try
            {
                Regex r = new Regex(@"^\w+://[^/]+?(?<port>\d+)?/", RegexOptions.Compiled);
                strPort = r.Match(url).Result("${port}");
            }
            catch
            {
                //donothing
            }
            return strPort;

        }
        #endregion






        public AsyncExecute AsyncExecute
        {
            get
            {
                return new AsyncExecute(this);
            }
        }
    }
    #region add maliang 2012-4-12
    public class AsyncExecute
    {

        private RemotingHelp _RemotingHelp = null;
        public AsyncExecute(RemotingHelp pRemotingHelp)
        {
            _RemotingHelp = pRemotingHelp;
        }
        private Form m_ParentBusy;
        /// <summary>
        /// 需要显示忙的窗体。
        /// </summary>
        public Form ParentBusy
        {
            get { return m_ParentBusy; }
            set { m_ParentBusy = value; }
        }

        private Point m_BusyLocation = new Point(0, 0);
        /// <summary>
        /// 需要显示忙的窗体。
        /// </summary>
        public Point BusyLocation
        {
            get { return m_BusyLocation; }
            set { m_BusyLocation = value; }
        }

        /// <summary>
        /// 请求完成的委托
        /// </summary>
        /// <param name="returnObj">返回的对象</param> 
        /// <param name="returnMsg">返回的消息内容</param>
        public delegate void CompleteEventHandler(object returnObj, string returnMsg);

        /// <summary>
        /// 请求完成的事件,如果返回的对象需要处理，请订阅该事件
        /// </summary>
        public event CompleteEventHandler OnComplete;
        /// <summary>
        /// 参数
        /// </summary>
        private CallingMessage CallingMessage;
        /// <summary>
        /// 错误信息
        /// </summary>
        private string errorInfo = string.Empty;
        /// <summary>
        /// 返回的对象
        /// </summary>
        private object returnObj;

        public void AsyncExecuteMethod(CallingMessage par)
        {
            CallingMessage = par;
            BackgroundWorker bw = new BackgroundWorker();
            bw.DoWork += new DoWorkEventHandler(DoWork);
            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(RunWorkerCompleted);
            bw.WorkerReportsProgress = true;
            bw.RunWorkerAsync();

        }


        /// <summary>
        /// 请求完成
        /// </summary> 
        void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {


            if (ParentBusy != null)
            {
                BusyCtl.Stop();
                ParentBusy.Controls.Remove(BusyCtl);
            }
            string msg = string.Empty;

            //如果订阅了该事件并且返回的结果没有问题才调用完成的事件
            if (OnComplete == null)
            {
                throw new Exception("调用接口请求时未订阅OnComplete事件,请在调用AsyncExecuteMethod请求对象是订阅OnComplete事件");
            }

            OnComplete.Invoke(returnObj, errorInfo);

        }
        private BusyControl BusyCtl = new BusyControl();
        /// <summary>
        /// 发送请求
        /// </summary> 
        void DoWork(object sender, DoWorkEventArgs e)
        {
            if (ParentBusy != null)
            {

                ParentBusy.Invoke(new dlgAddControl(addCtl), ParentBusy, BusyCtl);

            }
            errorInfo = "";
            returnObj = _RemotingHelp.ExecuteMethod(CallingMessage, out errorInfo);
        }

        delegate void dlgAddControl(Control Pctl, BusyControl BusyCtl);

        private void addCtl(Control Pctl, BusyControl BusyCtl)
        {
            BusyCtl.Size = new System.Drawing.Size(32, 32);
            Pctl.Controls.Add(BusyCtl);

            BusyCtl.BringToFront();
            BusyCtl.Location = BusyLocation;

            BusyCtl.Start();
        }

        public void AsyncExecuteMethod(string serverName, string className, string methodName, object[] args)
        {
            //==	解析参数
            CallingMessage par = new CallingMessage();
            par.ServerName = serverName;
            par.ClassName = className;
            par.MethodName = methodName;
            par.args = args;

            par.ServerType = MesServerType.IComponentContainServer;
            par.TransType = NetWorkTransType.Remoting;
            par.visitType = VisitType.Method;

            AsyncExecuteMethod(par);
        }



    }
    #endregion
}
