using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using CommonNetwork_ICE.Util;
using CommonLang.Protocol;
using CommonNetwork_ICE.Common;
using Slice;
using CommonNetwork_ICE.Client;
using CommonNetwork.Net;
using System.Collections;
using CommonLang.IO;
using CommonLang.Log;
using System.Net;

namespace CommonNetwork_ICE.Session
{
    /// <summary>
    /// 网络会话对象实现,通过会话对象可以发送消息,存储会话级变量
    /// </summary>
    public abstract class IceClientNetSession : INetSession
    {
        protected string mHost = "127.0.0.1";
        protected int mPort = 80;

        protected IceClientConnector iceConnector = null;

        protected INetPackageCodec mCodec;

        protected INetSessionListener mListener;

        private IExternalizableFactory sl;

        protected IPEndPoint mRemoteAddress;

        private Hashtable mAttributes = new Hashtable();

        public long mSendBytes = 0;
        public long mRecvBytes = 0;
        public long mSendPacks = 0;
        public long mRecvPacks = 0;


        private object closeLock = new object();

        public IceClientNetSession()
        {
        }

        public void SetBattleMessageFactory(IExternalizableFactory externalizableFactory)
        {
            sl = externalizableFactory;
        }

        public long TotalSentBytes { get { return mSendBytes; } }
        public long TotalRecvBytes { get { return mRecvBytes; } }
        public long TotalSentPackages { get { return mSendPacks; } }
        public long TotalRecvPackages { get { return mRecvPacks; } }
        public string URL { get { return (mHost + ":" + mPort); } }
        public string Host { get { return mHost; } }
        public int Port { get { return mPort; } }
        public IPEndPoint RemoteAddress { get { return mRemoteAddress; } }

        /// <summary>
        /// 判断当前网络是否已经连接
        /// </summary>
        /// <returns></returns>
        public bool IsConnected
        {
            get {
                if(iceConnector == null)
                {
                    return false;
                }
                return iceConnector.IsConnected;
            }
        }

        public abstract bool Open(string url, INetPackageCodec codec, INetSessionListener listener);

        public bool Close()
        {
            bool ret = false;
            lock (closeLock)
            {
                if(iceConnector == null)
                {
                    return true;
                }
            }
            iceConnector.Close();
            iceConnector = null;
            return ret;
        }


        public void Dispose()
        {
            Close();
        }

        //-------------------------------------------------------------------------------------

        /// <summary>
        /// 发送一个消息,该方法将立即返回。
        /// </summary>
        /// <param name="data"></param>
        public void Send(Object data)
        {
            if (data == null)
            {
                return;
            }
            if (IsConnected)
            {
                iceConnector.SendMessage(data as IMessage);
            }
        }
        public void SendResponse(IMessage rsponse, int requestMessageID)
        {
            rsponse.MessageID = requestMessageID;
            Send(rsponse);
        }


        //-------------------------------------------------------------------------------------

        public void PutAttribute(Object key, Object value)
        {
            mAttributes[key] = value;
        }

        public Object GetAttribute(Object key)
        {
            return mAttributes[key];
        }
        override public string ToString()
        {
            return "Session[" + URL + "](" + GetHashCode() + ")";
        }

        //-------------------------------------------------------------------------------------

        public void onClose()
        {
            if (mListener != null)
            {
                mListener.sessionClosed(this);
            }
            if (mOnSessionClosed != null)
            {
                mOnSessionClosed.Invoke(this);
            }
        }

        public void onOpen()
        {
            mListener.sessionOpened(this);
            if (mOnSessionOpened != null)
            {
                mOnSessionOpened.Invoke(this);
            }
        }

        public void onReceive(Object message, int recvBytes)
        {
            mRecvPacks++;
            mRecvBytes += recvBytes;
            mListener.messageReceived(this, message);
            if (mOnMessageReceived != null)
            {
                mOnMessageReceived.Invoke(this, message);
            }
        }

        public void onSent(Object message, int sentBytes)
        {
            mSendPacks++;
            mSendBytes += sentBytes;
            mListener.messageSent(this, message);
            if (mOnMessageSent != null)
            {
                mOnMessageSent.Invoke(this, message);
            }
        }

        public void onException(Exception err)
        {
            mListener.onError(this, err);
            if (mOnError != null)
            {
                mOnError.Invoke(this, err);
            }
        }

        //-------------------------------------------------------------------------------------

        private OnSessionOpenedHandler mOnSessionOpened;
        private OnSessionClosedHandler mOnSessionClosed;
        private OnMessageReceivedHandler mOnMessageReceived;
        private OnMessageSentHandler mOnMessageSent;
        private OnErrorHandler mOnError;
        private OnUpdateHandler mOnUpdate;

        public event OnSessionOpenedHandler OnSessionOpened { add { mOnSessionOpened += value; } remove { mOnSessionOpened -= value; } }
        public event OnSessionClosedHandler OnSessionClosed { add { mOnSessionClosed += value; } remove { mOnSessionClosed -= value; } }
        public event OnMessageReceivedHandler OnMessageReceived { add { mOnMessageReceived += value; } remove { mOnMessageReceived -= value; } }
        public event OnMessageSentHandler OnMessageSent { add { mOnMessageSent += value; } remove { mOnMessageSent -= value; } }
        public event OnErrorHandler OnError { add { mOnError += value; } remove { mOnError -= value; } }
        public event OnUpdateHandler OnUpdate { add { mOnUpdate += value; } remove { mOnUpdate -= value; } }


        /// <summary>
        /// Ice传输解码器
        /// </summary>
        internal class IceClientMessageCodecImpl : IceMessageCodec
        {
            public static int DEFAULT_BUFFER_SIZE = 1024;
            private INetPackageCodec codec = null;
            private IceClientNetSession client;
            public IceClientMessageCodecImpl(INetPackageCodec codec, IceClientNetSession client)
            {
                this.codec = codec;
                this.client = client;
            }

            public bool doDecode(TransMessage transMessage, out CommonLang.Protocol.IMessage message)
            {
                int length = transMessage.length;

                using (MemoryStream ms = new MemoryStream(transMessage.data))
                {
                    object msg;
                    if (codec.doDecode(client, ms, out msg))
                    {
                        message = msg as IMessage;
                        return true;
                    }
                }
                message = null;
                return false;
            }

            public void doEncode(CommonLang.Protocol.IMessage message, out TransMessage transMessage)
            {
                transMessage = new TransMessage();
                IMessage nm = (IMessage)message;
                using (MemoryStream ms = new MemoryStream(DEFAULT_BUFFER_SIZE))
                {
                    if (codec.doEncode(client, ms, message))
                    {
                        int length = (int)ms.Position;
                        transMessage.data = new byte[length];
                        Array.Copy(ms.GetBuffer(), transMessage.data, length);
                        transMessage.length = length;
                        transMessage.type = 1;
                    }
                }
            }
        }
    }
}