/*
         +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
         * IMPLEMENTATIONS
         */

        private static async Task <ServerSocketResponse> ReceiveResponseAsync(WebSocket socket, CancellationToken ct = default(CancellationToken))
        {
            try
            {
                ServerSocketResponse response = new ServerSocketResponse();
                response.Stream = new MemoryStream();
                var buffer = new ArraySegment <byte>(new byte[8192]);

                WebSocketReceiveResult result;
                do
                {
                    ct.ThrowIfCancellationRequested();

                    result = await socket.ReceiveAsync(buffer, ct);

                    response.Stream.Write(buffer.Array, buffer.Offset, result.Count);
                }while (!result.EndOfMessage);
                response.Stream.Seek(0, SeekOrigin.Begin);

                response.Type = result.MessageType;
                return(response);
            }
            catch (Exception e)
            {
                return(null);
            }
        }
        public async Task CallInvoke(HttpContext context)
        {
            CancellationToken ct            = context.RequestAborted;
            WebSocket         currentSocket = await context.WebSockets.AcceptWebSocketAsync();

            var socketId = Guid.NewGuid().ToString();

            _sockets.TryAdd(socketId, currentSocket);
            await this.OnClientConnect(socketId);

            while (true)
            {
                if (ct.IsCancellationRequested)
                {
                    break;
                }

                ServerSocketResponse package = await ReceiveResponseAsync(currentSocket);

                if (!package.HasTransimssion)
                {
                    if (currentSocket.State != WebSocketState.Open)
                    {
                        break;
                    }
                    if (this.CloseIfConnectionProblem(socketId))
                    {
                        break;
                    }
                }
                else
                {
                    await this.OnReceiveMessage(socketId, package);
                }
            }

            WebSocket dummy;

            _sockets.TryRemove(socketId, out dummy);

            await currentSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "Closing", ct);

            currentSocket.Dispose();
            await this.OnClientDisconect(socketId);
        }
        /*
         +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=
         * APSTRACTIOn
         */

        protected virtual Task OnReceiveMessage(string uid, ServerSocketResponse package) => Task.FromResult(default(object));