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;
using System.ComponentModel;
using System.Diagnostics;

namespace Core.Mes.ServerFrameWork
{
    public class Dispatcher : MarshalByRefObject, ICommon
    {
        /// <summary>
        /// 内存最大值 “”M
        /// </summary>
        private int MemoryMaxSize = 1000;
        /// <summary>
        /// 方法时间超时 “”秒记录方法
        /// </summary>
        private int MethodTime = 30;
        #region	"	Construct	"
        public Dispatcher() { }
        public Dispatcher(IServerPool pool)
        {
            Pool = pool;
            Debug = System.Configuration.ConfigurationManager.AppSettings["Debug"].ToLower();

            int.TryParse(System.Configuration.ConfigurationManager.AppSettings["MemoryMaxSize"], out MemoryMaxSize);

            int.TryParse(System.Configuration.ConfigurationManager.AppSettings["MethodTime"], out MethodTime);

        }
        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()
        {
            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);
                    GC.Collect();
                }
                catch
                {

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

            }
        }
        #endregion
        #region MethodTimeLog
        private static object lockObj = new object();
      
        //2012-9-6 longjing增加日志打印参数 process
        public void MethodTimeLog(long tspan, object[] objs, object[] args)
        {
            string path = string.Format(@"./log/Method/MethodTimeLog_{0}.txt", System.DateTime.Now.ToString("yyyy_MM_dd"));

            string str = ClsCommon.Clscommon.ProcessType== true ? "主进程" : "子进程";
            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} ms", tspan));
                    sbtxt.AppendLine(string.Format("Process:{0}", str));
                    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"));

            string str = ClsCommon.Clscommon.ProcessType == true ? "主进程" : "子进程";
            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("Process:{0}", str));
                    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()));
                            }
                        }
                    }
                    ExceptionLog(ex, sbtxt);
                    sw.WriteLine(sbtxt.ToString());


                }
            }
        }
        private void ExceptionLog(Exception ex, StringBuilder sbtxt)
        {
            if (ex.InnerException != null)
            {
                ExceptionLog(ex.InnerException, sbtxt);
            }
            else
            {
                sbtxt.AppendLine(ex.Message);
                sbtxt.AppendLine(ex.StackTrace);
                sbtxt.AppendLine("==============================================");
            }
        }
        public void DebugLog(object[] objs, object[] args)
        {
            string path = string.Format(@"./log/Method/DebugLog_{0}.txt", System.DateTime.Now.ToString("yyyy_MM_dd"));
            string str = ClsCommon.Clscommon.ProcessType == true ? "主进程" : "子进程";

            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("Process:{0}", str));
                    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:2012-4-17暂停使用内存释放原因CPU内存占用太高
            //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
                    {

                        if (Debug == "true")
                        {
                            DebugLog(new object[] { className, methodName }, args);
                        }

                        Stopwatch watch = new Stopwatch();
                        watch.Start();
                        //
                        //rtnObj = (ReturnObject)myMethod.Invoke(Pool, new object[] { className, methodName, args });
                        //2012-5-10
                        FastInvoke.FastInvokeHandler fastInvoker = FastInvoke.GetMethodInvoker(myMethod);
                        rtnObj = (ReturnObject)fastInvoker(Pool, new object[] { className, methodName, args });
                        //更改之后
                        watch.Stop();
                        //记录超时方法
                        if (watch.ElapsedMilliseconds > (MethodTime * 1000))
                        {


                            try
                            {
                                MethodTimeLog(watch.ElapsedMilliseconds, new object[] { className, methodName }, args);
                            }
                            // 2012-9-6 add longjing 
                            catch (Exception ex)
                            {
                                MethodErrLog(ex, new object[] { className, methodName }, args);
                            }

                        }


                        #region add maliang 2012-3-16 大数据时候序列化成2进制

                        if (rtnObj.RealObject is DataSet)
                        {
                            (rtnObj.RealObject as DataSet).RemotingFormat = SerializationFormat.Binary;

                        }
                        if (rtnObj.RealDataSet is DataSet)
                        {
                            (rtnObj.RealObject as DataSet).RemotingFormat = SerializationFormat.Binary;
                        }
                        if (rtnObj.RealObject is DataTable)
                        {
                            (rtnObj.RealObject as DataTable).RemotingFormat = SerializationFormat.Binary;
                        }

                        #endregion

                        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
    }


}
