/// <summary>
        /// Disconnects the session and invokes the
        /// <see cref="OnSessionDisconnection"/> event.
        /// </summary>
        public async Task DisconnectClientSession()
        {
            lock (syncObj)
            {
                //This prevents us from calling disconnected multiple times.
                if (HasDisconnectedBeenCalled)
                {
                    return;
                }

                HasDisconnectedBeenCalled = true;
            }

            if (OnSessionDisconnection != null)
            {
                await OnSessionDisconnection.Invoke(this, new DisconnectedSessionStatusChangeEventArgs(Details))
                .ConfigureAwait(false);
            }

            OnSessionDisconnection = null;

            //TODO: Can this ever throw??
            //Also disconnect the network client
            await InternalManagedNetworkClient.DisconnectAsync(0)
            .ConfigureAwait(false);
        }
        /// <inheritdoc />
        public ManagedClientSession <BaseGameServerPayload, BaseGameClientPayload> Create([NotNull] ManagedClientSessionCreationContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (Logger.IsDebugEnabled)
            {
                Logger.Debug($"Creating new session. Details: {context.Details}");
            }

            try
            {
                GameClientSession clientSession = new GameClientSession(context.Client, context.Details, HandlerService, Logger);

                clientSession.OnSessionDisconnection += (source, args) =>
                {
                    OnSessionDisconnection?.Invoke(source, args);
                    return(Task.CompletedTask);
                };

                return(clientSession);
            }
            catch (Exception e)
            {
                if (Logger.IsErrorEnabled)
                {
                    Logger.Error($"Failed to create Client: {context.Details} Error: {e.Message} \n\n Stack: {e.StackTrace}");
                }

                throw;
            }
        }
        /// <inheritdoc />
        public ManagedClientSession <GameServerPacketPayload, GameClientPacketPayload> Create([NotNull] ManagedClientSessionCreationContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (Logger.IsDebugEnabled)
            {
                Logger.Debug($"Creating new session. Details: {context.Details}");
            }

            try
            {
                ZoneClientSession clientSession = new ZoneClientSession(context.Client, context.Details, HandlerService, Logger);

                //We should add this to the session collection, and also make sure it is unregistered on disconnection
                SessionRegisterable.Register(context.Details.ConnectionId, clientSession);
                clientSession.OnSessionDisconnection += (source, args) =>
                {
                    OnSessionDisconnection?.Invoke(source, args);
                    return(Task.CompletedTask);
                };

                return(clientSession);
            }
            catch (Exception e)
            {
                if (Logger.IsErrorEnabled)
                {
                    Logger.Error($"Failed to create Client: {context.Details} Error: {e.Message} \n\n Stack: {e.StackTrace}");
                }

                throw;
            }
        }