using System;
using System.Collections.Concurrent;
using System.Text;
using System.Threading;
using GameMessage;
using MessagePack;
using MrWu;
using MrWu.Debug;
using Server.Core;
using Server.Core.Extend;

namespace Server.Net
{
    /// <summary>
    /// 会话  
    /// </summary>
    public class Session : IUserSession
    {
        /// <summary>
        /// 唯一id
        /// </summary>
        public long Id { get; private set; }

        public long InstanceId {
            get
            {
                return Id;
            }
        }
        
        public BaseWChannel WChannel { get; private set; }

        /// <summary>
        /// 读写时间
        /// </summary>
        public long ReadWriteTime;

        /// <summary>
        /// 登录验证码
        /// </summary>
        public string VerificationCode { get; set; }
        
        /// <summary>
        /// 是否已经断开连接
        /// </summary>
        public bool IsDisConnected { get; private set; }

        /// <summary>
        /// 绑定的用户数据 -- 老的用户数据
        /// </summary>
        public SessionUserData UserData { get; private set; }
        
        /// <summary>
        /// 断线锁
        /// </summary>
        public readonly object DisConnectLock = new object();

        public string RemoteIPAddress
        {
            get { return WChannel.RemoteEndPointIP; }
        }

        public Session(BaseWChannel wChannel)
        {
            this.WChannel = wChannel;
            Id = NetServices.CreateAcceptChannelId();
        }

        public virtual void Send(MessageData messageData)
        {
            if (messageData == null)
            {
                Debug.Error("不能发送空数据!");
                return;
            }
            byte[] data = PacketUtility.MessageParseData(messageData);
            Send(data);
        }

        public void Send(byte[] data,Type messageType)
        {
            data = PacketUtility.MessageParseData(messageType, data);
            Send(data);
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="data"></param>
        public virtual void Send(byte[] data)
        {
            if (IsDisConnected)
            {
                Debug.Info("发送失败，链接已经断开!");
                return;
            }

            if (!WChannel.Active)
            {
                Debug.Info("链接已经断开，发送失败!");
                return;
            }

            Interlocked.Exchange(ref ReadWriteTime, TimeInfo.Instance.FrameTime);
            // 组件 data 数据
            // 分类发送
            WChannel.Send(data);
        }

        public virtual void Send(string message)
        {
            if (IsDisConnected)
            {
                Debug.Info("发送失败，链接已经断开!");
                return;
            }

            if (!WChannel.Active)
            {
                Debug.Info("链接已经断开，发送失败!");
                return;
            }

            Interlocked.Exchange(ref ReadWriteTime, TimeInfo.Instance.FrameTime);
            WChannel.Send(message);
        }

        public void DisConnected()
        {
            WChannel.BeginDisconnect();
        }

        /// <summary>
        /// 绑定用户
        /// </summary>
        public void BindUser(int userid, string uuid, int clientVer, int plat, string deviceInfo, bool isNewUser,string storeType, bool reset = false)
        {
            if (IsDisConnected)
            {
                return;
            }

            if (!reset && UserData != null)
            {
                Debug.Error("该会话已经绑定了用户数据!");
                return;
            }

            ClearUserData();

            UserData = SessionUserData.Create(userid, uuid, clientVer, plat, deviceInfo,isNewUser, storeType);
            SessionUUIDManager.Instance.AddSessionUUID(uuid, UserData);
            GameNetDispatcher.Instance.Dispatch(GameNetMsgId.SessionBindUser, this);
        }

        public void ClearUserData()
        {
            if (UserData != null)
            {
                GameNetDispatcher.Instance.Dispatch(GameNetMsgId.SessionUnBindUser, this);
                SessionUUIDManager.Instance.RemoveLocalUUID(UserData.Uuid, UserData);
                UserData = null;
            }
        }

        /// <summary>
        /// 断开连接事件
        /// </summary>
        public virtual void OnDisConnected()
        {
            if (IsDisConnected)
            {
                return;
            }

            IsDisConnected = true;
            GameNetDispatcher.Instance.DispatchNextFrame(GameNetMsgId.SessionDisConnected, this);
            ClearUserData();
            Clear();
        }

        public virtual void Clear()
        {
        }
    }
}