using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Runtime.InteropServices;
using System.Threading;
using MrWu.Debug;

namespace Server.Net
{
    public abstract class AService : IDisposable
    {
        /// <summary>
        /// 监听回调
        /// </summary>
        public Action<long, IPEndPoint> AcceptCallBack;
        /// <summary>
        /// 读取收包数据
        /// </summary>
        public Action<long, MemoryBuffer> ReadCallBack;
        /// <summary>
        /// 错误回调
        /// </summary>
        public Action<long, int> ErrorCallBack;
        
        public ServiceType ServiceType { get; protected set; }

        private const int MaxMemoryBufferSize = 1024 * 1;
        
        /// <summary>
        /// 每个的大小都是MaxMemoryBufferSize
        /// </summary>
        private readonly ConcurrentQueue<MemoryBuffer> pool = new ConcurrentQueue<MemoryBuffer>();
        
        public MemoryBuffer Fetch(int size = 0)
        {
            ServiceThreadManager.Instance.CheckThread(this, Thread.CurrentThread.ManagedThreadId);
            
            if (size > MaxMemoryBufferSize)
            {
                return new MemoryBuffer(size);
            }

            if (size < MaxMemoryBufferSize)
            {
                size = MaxMemoryBufferSize;
            }

            if (pool.TryDequeue(out MemoryBuffer memoryBuffer))
            {
                return memoryBuffer;
            }
            
            return new MemoryBuffer(size);
        }

        public void Recycle(MemoryBuffer memoryBuffer)
        {
            if (memoryBuffer.Capacity > MaxMemoryBufferSize)
            {
                return;
            }

            //池最大数量
            if (this.pool.Count > 10)
            {
                return;
            }

            memoryBuffer.Seek(0, SeekOrigin.Begin);
            memoryBuffer.SetLength(0);
            
            this.pool.Enqueue(memoryBuffer);
        }

        public virtual void Dispose()
        {
            
        }

        public abstract void Update();

        public abstract void Remove(long id, int error = 0);

        public abstract bool IsDisposed();

        public abstract void Create(long id, IPEndPoint ipEndPoint);

        public abstract void Send(long channelId, MemoryBuffer memoryBuffer);
    }
}