using System;
using System.IO;
using System.Data;
using System.Reflection;
using System.Collections;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Windows.Forms;

using STMes;
using Core.Mes.ServerFrameWork;
using System.Configuration;
using System.Net.Sockets;
using System.Collections.Specialized;
using System.Net;
using Core.Mes.IBaseInterface;
using System.Diagnostics;

namespace Core.Mes.ServerManager
{
    /// <summary>
    /// ClsServerMain 的摘要说明。
    /// </summary>
    public class ClsServerMain : IDisposable
    {
        public bool _isLogging = false;
 
        private CoreWriteLogFile cwl_sql = null; 

        private ServerConfigure _serverConf;

        public ClsServerMain() { }

        public delegate void ShowLogDelegate(string log);

        public event ShowLogDelegate ShowLogEvent;

        private void ShowLog(string log)
        {
            if (ShowLogEvent != null)
            {
                ShowLogEvent(log);
            }
        }

        #region "	Property	"
        private Hashtable _dbManagerList = new Hashtable();
        public Hashtable DBManagerList
        {
            //set { _dbManagerList = value; }
            get { return _dbManagerList; }
        }
        private Hashtable _htAssemblyService = new Hashtable();
        public Hashtable HtAssemblyService
        {
            //set { _htAssemblyServer = value; }
            get { return _htAssemblyService; }
        }
        private Hashtable _htServiceKeys = new Hashtable();
        public Hashtable HTServiceKeys
        {
            get { return _htServiceKeys; }
        }

        private Hashtable _htExternServer = new Hashtable();
        public Hashtable HtExternServer
        {
            get { return _htExternServer; }
        }

        private Hashtable _htDispatcher = new Hashtable();
        public Hashtable HtDispatcher
        {
            get { return _htDispatcher; }
        }

        private DataSet _dsServerList = new DataSet();
        #endregion

        public void InitServerMain(Object[] objs)
        {
            if (objs != null)
            {
                if (objs.GetLength(0) >= 1)
                {
                    _serverConf = (ServerConfigure)(objs[0]);
                }
            }
            try
            {
                RemotingGate _rg = new RemotingGate(_serverConf);
                ShowLog("初始化数据库连接......");
                InitDBManager();
                ShowLog("数据库连接初始化完毕！");
                GetServerListDataSet();
                ShowLog("读取应用服务配置......");
                foreach (DataRow dr in this._dsServerList.Tables[0].Rows)
                {
                    LoadAssemblyServer(dr["ServerName"].ToString(), dr["AssemblyName"].ToString(), dr["DBName"].ToString(), dr["Url"].ToString(), dr["Description"].ToString());
                }
                ShowLog("读取扩展服务器配置......");
                InitExternServer();
            }
            catch (SocketException sEx)
            {
                ShowLog("只能运行一个服务端！");

                if (sEx.ErrorCode == 10048)
                {
                    long start_time = DateTime.Now.Ticks;
                    int T_Count = 10;
                    do
                    {
                        int vSec = (int)(T_Count - (DateTime.Now.Ticks - start_time) / 10000000);
                        if (vSec != T_Count)
                        {
                            ShowLog(string.Format("退出倒计时：{0} 秒", vSec));
                            T_Count = vSec;
                        }
                        Application.DoEvents();
                    } while (DateTime.Now.Ticks - start_time <= T_Count * 10000000);
                    Application.Exit();
                }
            }
            catch (Exception ex)
            {
                ShowLog(ex.Message);
            }
        }

        private void InitDBManager()
        {
            ShowLog(string.Format("读取配置文件: {0}", _serverConf.ConfigFilePath));
            string _strDB = _serverConf.MESDB;
            string[] strDBs = _strDB.Split('|');

            for (int i = 0; i < strDBs.Length; i++)
            {
                try
                {
                    string str = strDBs[i];

                    ShowLog(string.Format("[{0}/{1}]初始化DBManager: {2} {3}", i + 1, strDBs.Length, str, "A"));
                    DBManager dbm = new STMes.DBManager(str, "A");
                    dbm.SetLogHandle(this._isLogging ? new DBManager.ShowLogDelegate(ShowLog) : null);
                    dbm.IsLogging = this._isLogging;
                    DBManagerList.Add(str, dbm);

                    ShowLog(string.Format("[{0}/{1}]初始化DBManager: {2} {3}", i + 1, strDBs.Length, str, "B"));
                    dbm = new STMes.DBManager(str, "B");
                    dbm.SetLogHandle(this._isLogging ? new DBManager.ShowLogDelegate(ShowLog) : null);
                    dbm.IsLogging = this._isLogging;
                    DBManagerList.Add(str + "B", dbm);

                    ShowLog(string.Format("[{0}/{1}]初始化DBManager: {2} {3}", i + 1, strDBs.Length, str, "C"));
                    dbm = new STMes.DBManager(str, "C");
                    dbm.SetLogHandle(this._isLogging ? new DBManager.ShowLogDelegate(ShowLog) : null);
                    dbm.IsLogging = this._isLogging;
                    DBManagerList.Add(str + "C", dbm);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
        }


        //获得服务端配置信息列表
        private DataTable GetServerConfigInfo()
        {
            return null;
        }
        //==========================================================
        // 加载应用服务
        //==========================================================
        private void LoadAssemblyServer(string ServiceName, string assName, string dbName, string ServiceURL, string ServiceDescrption)
        {
            try
            {
                string file = Path.Combine(Application.StartupPath, assName + ".dll");

                IServerPool obj = new IServerPool();
                obj.DBManagerList = DBManagerList;
                obj.ServerName = ServiceName;
                obj.AssemblyName = assName;
                obj.HTServiceKeys = this._htServiceKeys;
                obj.HtExtServer = this._htExternServer;
                obj.ServerConfig = this._serverConf;
                obj.OwnObjects = new ArrayList() { this };

                obj.LoadAllClass(file, dbName);

                string md5key;
                string sha256key;
                obj.GetFileKey(file, out md5key, out sha256key);
                if (HTServiceKeys.ContainsKey(ServiceName))
                {
                    HTServiceKeys.Remove(ServiceName);
                }

                ServiceObject mso = new ServiceObject();
                mso.MD5_KEY = md5key;
                mso.SHA256_KEY = sha256key;
                mso.URL = ServiceURL;
                mso.Valid = ServiceObjectStatus.Normal;
                mso.Enable = true;
                mso.Description = ServiceDescrption;
                mso.DLL_FileName = assName + ".dll";

                HTServiceKeys.Add(ServiceName, mso);

                //== 以服务名键值,加入本地服务列表
                if (HtAssemblyService.ContainsKey(ServiceName))
                {
                    IServerPool isp = (IServerPool)HtAssemblyService[ServiceName];
                    isp.Dispose();
                    HtAssemblyService.Remove(ServiceName);
                }
                HtAssemblyService.Add(ServiceName, obj);


                if (_htDispatcher.ContainsKey(ServiceName))
                {
                    Dispatcher dp = (Dispatcher)(_htDispatcher[ServiceName]);
                    RemotingServices.Disconnect(dp);
                    dp.MemoryDispose();
                    _htDispatcher.Remove(ServiceName);
                }

                //Dispatcher myDisp = new Dispatcher(obj, _serverConf, null);
                Dispatcher myDisp = new Dispatcher(obj, _serverConf, obj.OwnObjects);
                _htDispatcher.Add(ServiceName, myDisp);

                RemotingServices.Marshal(myDisp, ServiceName);

                this.ShowLog(" 加载" + ServiceName + "成功！");
            }
            catch (Exception ex)
            {
                this.ShowLog(" 加载" + ServiceName + "失败！\n" + ex.Message);
                throw ex;
            }
        }

        private void UnLoadAssemblyServer(string ServiceName)
        {
            try
            {
                if (_htDispatcher.ContainsKey(ServiceName))
                {
                    Dispatcher dp = (Dispatcher)(_htDispatcher[ServiceName]);
                    RemotingServices.Disconnect(dp);
                    dp.MemoryDispose();
                    _htDispatcher.Remove(ServiceName);
                }


                //== 以服务名键值,加入本地服务列表
                string AssemblyName = "";
                if (HtAssemblyService.ContainsKey(ServiceName))
                {
                    IServerPool isp = (IServerPool)HtAssemblyService[ServiceName];
                    AssemblyName = isp.AssemblyName;
                    isp.Dispose();
                    HtAssemblyService.Remove(ServiceName);
                }

                if (HTServiceKeys.ContainsKey(ServiceName))
                {
                    HTServiceKeys.Remove(ServiceName);
                }

                this.ShowLog(" 卸载" + ServiceName + "成功！");
            }
            catch (Exception ex)
            {
                this.ShowLog(" 卸载" + ServiceName + "失败！\n" + ex.Message);
                throw ex;
            }
        }

        private void InitExternServer()
        {
            try
            {
                string[] exServers = _serverConf.ExtServers.Split(new string[] { "|", ",", ";" }, StringSplitOptions.RemoveEmptyEntries);
                if (exServers.GetLength(0) == 0) return;

                foreach (string _serv in exServers)
                {
                    bool same_server = false;
                    string serv = _serv.Trim();
                    UriBuilder ub = new UriBuilder(serv);

                    System.Net.IPAddress[] ips = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
                    if (ips.Length > 0)
                    {
                        foreach (IPAddress cip in ips)
                        {
                            if (cip.AddressFamily == AddressFamily.InterNetwork)
                            {
                                string ip = cip.ToString().Trim();
                                if (string.IsNullOrEmpty(ip) || ip.Length < 7 || ip.Length > 15) continue;

                                if (ub.Host == ip)
                                {
                                    same_server = true;
                                    break;
                                }
                            }
                        }
                    }
                    if (same_server) continue;

                    if (!_htExternServer.ContainsKey(serv))
                    {
                        UriBuilder ubr = new UriBuilder(serv);
                        RemotingServer rs = new RemotingServer(serv, HTServiceKeys);
                        rs.InitServiceUrlList("ServerCommon", serv);
                        rs.InitServiceUrlList("ServerListener", string.Format("Tcp://{0}:{1}/ServerListener", ubr.Host, ubr.Port - 2));
                        _htExternServer.Add(serv, rs);
                        this.ShowLog(string.Format(" 获取扩展服务器 [{0}:{1}]资源！", ub.Host, ub.Port));
                        rs.SetChangeEvent(_serverConf.ssc_event);
                        rs.LoadExternServices();
                        if (_serverConf.ssc_event != null) _serverConf.ssc_event();
                        rs.CheckHeartBeat();
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.Print(ex.Message);
            }
        }


        public void SetServerFlag(string ServerName, bool Enable)
        {
            foreach (string FullServerName in this.HtExternServer.Keys)
            {
                UriBuilder ub = new UriBuilder(FullServerName);
                string sn = string.Format("{0}:{1}", ub.Host, ub.Port);
                if (ServerName == sn)
                {
                    ((RemotingServer)(this.HtExternServer[FullServerName])).Enable = Enable;
                    break;
                }
            }
        }

        public void SetServiceFlag(string ServerName, string ServiceName, bool Enable)
        {
            foreach (string FullServerName in this.HtExternServer.Keys)
            {
                UriBuilder ub = new UriBuilder(FullServerName);
                string sn = string.Format("{0}:{1}", ub.Host, ub.Port);
                Hashtable ht_srv = ((RemotingServer)(this.HtExternServer[FullServerName])).HTServices;
                if (ServerName == sn && ht_srv.ContainsKey(ServiceName))
                {
                    ((ServiceObject)(ht_srv[ServiceName])).Enable = Enable;
                }
            }
        }

        private void GetServerListDataSet()
        {
            if (!File.Exists("MesServer.xml"))
            {
                throw new Exception("未找到服务配置文件！");
            }

            _dsServerList.ReadXml("MesServer.xml");

            if (_dsServerList == null || _dsServerList.Tables.Count == 0)
                throw new Exception("配置文件设置错误！");

            _dsServerList.AcceptChanges();
        }

        #region IDisposable 成员

        public void Dispose()
        {
            if (this.DBManagerList != null)
            {
                IEnumerator ie = this.DBManagerList.GetEnumerator();

                while (ie.MoveNext())
                {
                    try
                    {
                        System.Collections.DictionaryEntry id = (System.Collections.DictionaryEntry)ie.Current;

                        STMes.DBManager myDbManager = (STMes.DBManager)id.Value;

                        myDbManager.Dispose();
                        myDbManager = null;
                    }
                    catch { }

                }
                this.DBManagerList.Clear();
            }
            if (STMes.DBManager._dbProxy != null)
            {
                try
                {
                    STMes.DBManager._dbProxy.Dispose();
                }
                catch { }
            }
        }

        #endregion
    }
}
