using System;
using System.Diagnostics;
using System.Threading;
using GameDAL.Game;
using GameMessage;
using Server.Core;
using Debug = MrWu.Debug.Debug;

namespace Server.Net
{
    /// <summary>
    /// 用在这个代理Session的原因是 源Session可以被复用
    /// </summary>
    public class ProxySession : Reference, IUserSession
    {
        /// <summary>
        /// 是否已经被释放
        /// </summary>
        private bool IsDisposed { get; set; }
        
        /// <summary>
        /// 实例Id
        /// </summary>
        public long InstanceId { get; private set; }

        /// <summary>
        /// 注意这个ID 与 普通 Session 会有相同的情况
        /// </summary>
        public long Id
        {
            get { return SourceSession.Id; }
        }

        /// <summary>
        /// 是否断开连接
        /// </summary>
        public bool IsDisConnected
        {
            get
            {
                //Debug.Info($"IsDisConnected: {SourceSession == null} {InstanceId} {SourceSession?.InstanceId}");
                return SourceSession == null || SourceSession.IsDisConnected || InstanceId != SourceSession.InstanceId;
            }
        }

        private SessionUserData _userData;
        
        public SessionUserData UserData {
            get
            {
                CheckDisposed();
                return _userData;
            }
            private set
            {
                CheckDisposed();
                _userData = value;
            }
        }

        public string RemoteIPAddress { get; private set; }

        /// <summary>
        /// 登录验证码
        /// </summary>
        public string VerificationCode
        {
            get
            {
                if (SourceSession == null)
                {
                    Debug.Fatal("VerificationCode Get Error, SourceSession is null!");
                    return null;
                }
                return SourceSession.VerificationCode;
            }
            set
            {
                if (SourceSession == null)
                {
                    Debug.Fatal("VerificationCode Set Error, SourceSession is null!");
                    return;
                }
                SourceSession.VerificationCode = value;
            }
        }

        /// <summary>
        /// 源会话 -- 使用者不能拿这个用，因为这个是对象池中的，随时会变
        /// </summary>
        public UserSession SourceSession { get; private set; }

        public void BindUser(int userid, string uuid, int clientVer, int plat, string deviceInfo,bool isNewUser,string storeType, bool reset = false)
        {
            if (!IsDisConnected)
            {
                SourceSession.BindUser(userid, uuid, clientVer, plat, deviceInfo, isNewUser,storeType, reset);
                UserData = SourceSession.UserData;
            }
            
            CheckDisposed();
        }

        
        
        public void Send(byte[] buffer, Type messageType)
        {
            if (!IsDisConnected)
            {
                SourceSession.Send(buffer, messageType);
            }
        }

        public void Send(MessageData messageData)
        {
            //Debug.Info($"发送消息:{IsDisConnected}");
            if (!IsDisConnected)
            {
                SourceSession.Send(messageData);
            }
            
            CheckDisposed();
        }

        public static ProxySession Create(UserSession session)
        {
            ProxySession proxySession = ReferencePool.Fetch<ProxySession>();
            proxySession.IsDisposed = false;
            proxySession.InstanceId = session.InstanceId;
            proxySession.UserData = session.UserData;
            proxySession.RemoteIPAddress = session.RemoteIPAddress;
            proxySession.SourceSession = session;
            return proxySession;
        }

        public override void Dispose()
        {
            if (this.IsFromPool)
            {
                this.SourceSession = null;
                this.UserData = null;
                ReferencePool.Recycle(this);
                this.IsDisposed = true;
            }
        }

        public void DisConnected()
        {
            if (!IsDisConnected)
            {
                SourceSession.DisConnected();
            }

            CheckDisposed();
        }
        
        private void CheckDisposed()
        {
            if (this.IsDisposed)
            {
                //打印堆栈信息
                StackTrace st = new StackTrace();
                Debug.Fatal($"ProxySession is Disposed! {st.ToString()}");
            }
        }
    }
}