using System.Collections.Generic;
using System.Linq;
using System.Net;

namespace WS
{
    [ObjectSystem]
    public class NetworkComponentAwake : AwakeSystem<NetworkComponent, NetworkType>
    {
        public override void Awake(NetworkComponent self, NetworkType a)
        {
            self.Awake(a);
        }
    }

    [ObjectSystem]
    public class NetworkComponentAwakeS : AwakeSystem<NetworkComponent, NetworkType, string>
    {
        public override void Awake(NetworkComponent self, NetworkType a, string b)
        {
            self.Awake(a, b);
        }
    }


    [ObjectSystem]
    public class NetWorkComponentUpdate : UpdateSystem<NetworkComponent>
    {
        public override void Update(NetworkComponent self)
        {
            self.Update();
        }
    }

    ///<summary>网络Socket</summary>
    public class NetworkComponent : WSComponent
    {
        public static NetworkComponent Instance;

        ///<summary>服务</summary>
        private AService Service;

        ///<summary>代理储存器</summary>
        private Dictionary<long, Session> sessions = new Dictionary<long, Session>();

        public void Awake(NetworkType network)
        {
            StartComponent();
            switch (network)
            {
                case NetworkType.KCP:

                    break;
                case NetworkType.TCP:
                    Service = new TService(Packet.PacketSizeLength4) { Parent = this };
                    break;
                case NetworkType.WebSocket:

                    break;
            }
        }

        public void Awake(NetworkType network, string address)
        {
            StartComponent();
            IPEndPoint ipEndPoint;
            switch (network)
            {
                case NetworkType.KCP:

                    break;
                case NetworkType.TCP:
                    ipEndPoint = NetworkHelper.ToIPEndPoint(address);
                    Service = new TService(Packet.PacketSizeLength4, ipEndPoint, OnAccept) { Parent = this };
                    break;
                case NetworkType.WebSocket:

                    break;
            }
        }

        ///<summary>初始化组件其它数据</summary>
        public void StartComponent()
        {
            Instance = this;
            Proto = AddComponent<ProtoManager>();
            Event = AddComponent<NetworkEvent>();
        }

        ///<summary>协议组件</summary>
        public ProtoManager Proto { get; private set; }

        ///<summary>网络消息组件</summary>
        public NetworkEvent Event { get; private set; }

        ///<summary>链接数量</summary>
        public int Count { get { return sessions.Count; } }

        ///<summary>服务器监听创建成功</summary>
        private void OnAccept(AChannel channel)
        {
            Session session = ComponentFactory.CreateWithParent<Session, AChannel>(this, channel);
            sessions.Add(session.InstanceId, session);
            session.Start();
        }

        ///<summary>删除</summary>
        public void Remove(long id)
        {
            Session session;
            if (!sessions.TryGetValue(id, out session))
            {
                return;
            }
            Log.LogDebug($"服务器:{session.RemoteAddress.Address}:{session.RemoteAddress.Port} 断开链接");
            sessions.Remove(id);
            session.Dispose();
        }

        ///<summary>获取Session</summary>
        public Session Get(long id)
        {
            Session session;
            sessions.TryGetValue(id, out session);
            return session;
        }

        ///<summary>创建 Session</summary>
        public Session CreateSession(IPEndPoint ipendpoint)
        {
            AChannel channel = Service.ConnectChannel(ipendpoint);
            Session session = ComponentFactory.CreateWithParent<Session, AChannel>(this, channel);
            sessions.Add(session.InstanceId, session);
            session.Start();
            return session;
        }

        ///<summary>创建 Session</summary>
        public Session CreateSession(string address)
        {
            AChannel channel = Service.ConnectChannel(address);
            Session session = ComponentFactory.CreateWithParent<Session, AChannel>(this, channel);
            sessions.Add(session.InstanceId, session);
            session.Start();
            return session;
        }

        public void Update()
        {
            if (Service != null)
            {
                Service.Update();
            }
        }

        public override void Dispose()
        {
            base.Dispose();

            Session[] arr = sessions.Values.ToArray();
            for (int i = 0; i < arr.Length; i++)
            {
                arr[i].Dispose();
            }
            Service.Dispose();
        }
    }
}