using System;
using System.IO;
using System.Xml;
using System.Data;
using System.Text;
using System.Collections;
using System.Reflection;
using System.Configuration;

using Core.Mes.IBaseInterface;

namespace Core.Mes.ServerFrameWork
{
    public class Dispatcher : MarshalByRefObject, ICommon
    {
        #region	"	Construct	"
        public Dispatcher() { }
        public Dispatcher(IServerPool pool)
        {
            Pool = pool;
            Debug = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).AppSettings.Settings["Debug"].Value.ToString().ToLower();
        }
        private IServerPool _pool = null;
        public IServerPool Pool
        {
            get { return _pool; }
            set { _pool = value; }
        }
        private string Debug = "false";
        #endregion

        #region "	Variable	"

        //== 子服务集合
        public static Hashtable _htServers = new Hashtable();
        //== 数据链接集合
        public static Hashtable htDBManager = new Hashtable();

        public event GetStatusInfoHandler getStatusInfo;

        public delegate void GetStatusInfoHandler(string info);

        protected virtual void SetStatusMessage(string info)
        {
            if (getStatusInfo != null)
            {
                getStatusInfo(info);
            }
        }

        #endregion

        #region 内存释放
        public void MemoryDispose()
        {
            int MemoryMaxSize = 100;
            int.TryParse(ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).AppSettings.Settings["MemoyMaxSize"].Value.ToString(), out MemoryMaxSize);
            long memorysize = System.Diagnostics.Process.GetCurrentProcess().WorkingSet64;
            int PagedMemorySize = (int)memorysize / (1024 * 1024);
            if (PagedMemorySize > MemoryMaxSize)//进程占用内存>100M 做GC.
            {

                try
                {
                    GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
                }
                catch
                {

                }
                System.Diagnostics.Process.GetCurrentProcess().Dispose();

            }
        }
        #endregion
        #region MethodTimeLog
        private static object lockObj = new object();
        public void MethodTimeLog(TimeSpan tspan, object[] objs, object[] args)
        {
            string path = string.Format(@"./log/Method/MethodTimeLog_{0}.txt", System.DateTime.Now.ToString("yyyy_MM_dd"));

            lock (lockObj)
            {


                using (StreamWriter sw = new StreamWriter(path, true, Encoding.UTF8))
                {

                    StringBuilder sbtxt = new StringBuilder();
                    sbtxt.AppendLine("==============================================");
                    sbtxt.AppendLine(string.Format("LogWriteTime:{0}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
                    sbtxt.AppendLine(string.Format("Time:{0}", tspan.TotalMilliseconds));
                    sbtxt.AppendLine(string.Format("ClassName:{0}", objs[0].ToString()));
                    sbtxt.AppendLine(string.Format("MethodName:{0}", objs[1].ToString()));
                    if (args != null)
                    {
                        foreach (object obj in args)
                        {
                            if (obj != null)
                            {
                                sbtxt.AppendLine(string.Format("Parameters:{0}", obj.ToString()));
                            }
                        }
                    }
                    sbtxt.AppendLine("==============================================");
                    sw.WriteLine(sbtxt.ToString());

                }
            }
        }
        public void MethodErrLog(Exception ex, object[] objs, object[] args)
        {
            string path = string.Format(@"./log/Method/MethodErrLog_{0}.txt", System.DateTime.Now.ToString("yyyy_MM_dd"));
            lock (lockObj)
            {
                using (StreamWriter sw = new StreamWriter(path, true, Encoding.UTF8))
                {

                    StringBuilder sbtxt = new StringBuilder();
                    sbtxt.AppendLine("==============================================");
                    sbtxt.AppendLine(string.Format("LogWriteTime:{0}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
                    sbtxt.AppendLine(string.Format("ClassName:{0}", objs[0].ToString()));
                    sbtxt.AppendLine(string.Format("MethodName:{0}", objs[1].ToString()));
                    if (args != null)
                    {
                        foreach (object obj in args)
                        {
                            if (obj != null)
                            {
                                sbtxt.AppendLine(string.Format("Parameters:{0}", obj.ToString()));
                            }
                        }
                    }
                    sbtxt.AppendLine(ex.Message);
                    sbtxt.AppendLine(ex.StackTrace);
                    sbtxt.AppendLine("==============================================");
                    sw.WriteLine(sbtxt.ToString());

                }
            }
        }
        public void DebugLog(object[] objs, object[] args)
        {
            string path = string.Format(@"./log/Method/DebugLog_{0}.txt", System.DateTime.Now.ToString("yyyy_MM_dd"));
            lock (lockObj)
            {
                if (File.Exists(Path.GetFullPath(path)))
                {
                    FileInfo fileInfo = new FileInfo(Path.GetFullPath(path));
                    if (fileInfo.Length / (1024 * 1024) > 6)
                    {
                        File.Delete(path);
                    }
                }

                using (StreamWriter sw = new StreamWriter(path, true, Encoding.UTF8))
                {

                    StringBuilder sbtxt = new StringBuilder();
                    sbtxt.AppendLine("==============================================");
                    sbtxt.AppendLine(string.Format("LogWriteTime:{0}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")));
                    sbtxt.AppendLine(string.Format("ClassName:{0}", objs[0].ToString()));
                    sbtxt.AppendLine(string.Format("MethodName:{0}", objs[1].ToString()));
                    if (args != null)
                    {
                        foreach (object obj in args)
                        {
                            if (obj != null)
                            {
                                sbtxt.AppendLine(string.Format("Parameters:{0}", obj.ToString()));
                            }
                        }
                    }
                    sbtxt.AppendLine("==============================================");
                    sw.WriteLine(sbtxt.ToString());

                }
            }
        }
        #endregion
        #region "	调用服务	"
        /// <summary>
        /// 服务端公开给客户端的调用后台服务的方法
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public ReturnObject MethodHandler(CallingMessage message, ValidateInfo validateInfo)
        {
            //step1:
            MemoryDispose();

            //step2:
            string serverName = message.ServerName;
            string assemblyName = message.AssemblyName;
            string className = message.ClassName;
            string methodName = message.MethodName;
            object[] args = message.args;

            ReturnObject rtnObj = new ReturnObject();
            MethodInfo myMethod = null;
            try
            {
                if (Pool.HtComponent.Contains(className))
                {
                    myMethod = Pool.GetType().GetMethod("HandleMethod");
                    try
                    {
                        //rtnObj = Pool.HandleMethod(className, methodName, args);
                        DateTime startTime = DateTime.Now;
                        if (Debug == "true")
                        {
                            DebugLog(new object[] { className, methodName }, args);
                        }


                        rtnObj = (ReturnObject)myMethod.Invoke(Pool, new object[] { className, methodName, args });
                        DateTime endTime = DateTime.Now;
                        TimeSpan tspan = endTime - startTime;
                        int MethodTime = 30;

                        int.TryParse(ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).AppSettings.Settings["MethodTime"].Value.ToString().ToLower(), out MethodTime);
                        if (tspan.TotalMilliseconds > (MethodTime * 1000))
                        {
                            MethodTimeLog(tspan, new object[] { className, methodName }, args);
                        }

                        return rtnObj;
                    }
                    catch (Exception ex)
                    {
                        MethodErrLog(ex, new object[] { className, methodName }, args);
                        return new ReturnObject(null, ex.Message);
                    }
                    finally
                    {
                        //if (myMethod != null) myMethod = null;
                        try
                        {
                            if (rtnObj.RealObject != null)
                            {
                                rtnObj.RealObject = null;
                            }
                            if (rtnObj.RealDataSet != null)
                            {
                                rtnObj.RealDataSet = null;
                            }
                        }
                        catch { }
                    }

                }
                else
                {

                    return new ReturnObject(null, "未找到请求的服务！");
                }
            }
            catch (Exception ex)
            {
                return new ReturnObject(null, "服务调用发生异常！ \n" + ex.Message);
            }
        }
        #endregion

        #region "	Common Handler	"
        //=======================================================
        // 用来确保当创建 Singleton 时, 第一个实例永远不会过期
        //=======================================================
        public override object InitializeLifetimeService()
        {
            return null;
        }
        #endregion
    }
}
