public async Task <bool> UserChannelsUnsubscribeUserFromGroupChannel(int channelId)
        {
            return(await _contextActionAsync(async connection =>
            {
                var cr = _getCurrentUser(connection);
                var channelAdminUsrId = 0;
                var removedConnection = _channelService.UnsubscribeUserFromGroupChannel(connection, channelId,
                                                                                        cr.UserId, admId => { channelAdminUsrId = admId; });

                await cr.RemoveGroupChannelNameAsync(Groups, channelId);

                if (channelAdminUsrId != 0)
                {
                    var admin = _getOnlineSingleUser(connection, channelAdminUsrId);
                    if (admin != null)
                    {
                        var connOut = new ChannelConnectionUserOut(removedConnection, cr.Name, "");
                        await Clients.Client(admin.ConnectionId).InvokeAsync("onUserChannelsGroupUserUnsubscribe",
                                                                             channelAdminUsrId, connOut);
                    }
                }
                var updHubUser = _hubCache.AddOrUpdateLocal(cr, true);

                await Clients.Client(updHubUser.ConnectionId).InvokeAsync("updateConnectionUser", updHubUser);


                return true;
            }));
        }
        public async Task <bool> UserChannelsDeepDeleteOtherGroupChannels()
        {
            return(await _contextActionAsync(async connection =>
            {
                var cr = _getCurrentUser(connection);
                var dic = new Dictionary <int, ChannelConnectionDataModel>();
                _channelService.DeepDeleteOtherGroupChannels(connection, cr.UserId, (adminId, item) => { dic.Add(adminId, item); });


                foreach (var item in dic)
                {
                    var admin = _getOnlineSingleUser(connection, item.Key);
                    if (admin != null)
                    {
                        var connOut = new ChannelConnectionUserOut(item.Value, cr.Name, "");
                        await Clients.Client(admin.ConnectionId)
                        .InvokeAsync("onUserChannelsGroupUserUnsubscribe", item.Key, connOut);
                    }
                    await cr.RemoveGroupChannelNameAsync(Groups, item.Value.ChannelId);
                }
                var updHubUser = _hubCache.AddOrUpdateLocal(cr, true);
                await Clients.Client(cr.ConnectionId).InvokeAsync("updateConnectionUser", updHubUser);
                return true;
            }));
        }
        public async Task <ChannelConnectionUserOut> UserChannelsGroupUpdateUser(ChannelConnectionUserOut tragetUser,
                                                                                 bool updatePasswordByChannel, int channelAdminUserId)
        {
            return(await _contextActionAsync(async connection =>
            {
                //ChannelConnectionUserOut
                var cr = _getCurrentUser(connection);

                if (cr.UserId != channelAdminUserId)
                {
                    throw new SecurityException(Error.NotPermitted);
                }
                GroupChannelOut targetChannel = null;
                ChannelConnectionDataModel oldModel = null;

                var channelId = tragetUser.ChannelId;
                var hasChange = _channelService.UpdateGroupUser(connection, tragetUser, updatePasswordByChannel,
                                                                channelAdminUserId,
                                                                targetUserChat => { targetChannel = targetUserChat; },
                                                                oldM => { oldModel = oldM; });

                if (!hasChange)
                {
                    return tragetUser;
                }
                var tu = _getOnlineSingleUser(connection, tragetUser.UserId);
                if (tu == null)
                {
                    return tragetUser;
                }
                var iHubGroupItem = cr.GetUserChannelGroup(channelId);
                // changes for target  user
                if (targetChannel != null)
                {
                    await tu.AddOrReplaceGroupChannelGroupNameAsync(Groups, channelId, iHubGroupItem.NativeName);
                    _hubCache.AddOrUpdateLocal(tu, true);
                    await Clients.Client(tu.ConnectionId).InvokeAsync("userChannelsAddOrUpdateGroupChannel",
                                                                      targetChannel, iHubGroupItem);
                    //todo Clients.Client(tu.ConnectionId).
                    return tragetUser;
                }
                if (oldModel.MessageRead && !tragetUser.MessageRead)
                {
                    await tu.RemoveGroupChannelNameAsync(Groups, channelId);
                    _hubCache.AddOrUpdateLocal(tu, true);
                    await Clients.Client(tu.ConnectionId).InvokeAsync("userChannelsGroupDropChannel", channelId, false,
                                                                      iHubGroupItem.GroupeName);
                    return tragetUser;
                }

                await Clients.Client(tu.ConnectionId)
                .InvokeAsync("onUserChannelsCrUserGroupUpdatedPermition", tragetUser);
                return tragetUser;
            }));
        }
        public async Task <GroupChannelOut> UserChannelsJoinToGroupChannel(int channelId, string password)
        {
            NameIdInt channelOwner = null;

            try
            {
                return(await _contextActionAsync(async connection =>
                {
                    var cr = _getCurrentUser(connection);
                    ChannelConnectionUserOut newConnectionUser = null;
                    var chOut = _channelService.JoinUserToGroupChannel(connection, channelId, password, cr.UserId,
                                                                       (owner, conOut) =>
                    {
                        channelOwner = owner;
                        newConnectionUser = conOut;
                    });
                    await cr.AddOrReplaceGroupChannelGroupNameAsync(Groups, channelId, chOut.ChannelName);
                    var updHubUser = _hubCache.AddOrUpdateLocal(cr, true);
                    await Clients.Client(updHubUser.ConnectionId).InvokeAsync("updateConnectionUser", updHubUser);
                    if (channelOwner == null || newConnectionUser == null)
                    {
                        throw new NotImplementedException(
                            "data correct but target admin or new connection user not exist");
                    }
                    var admin = _getOnlineSingleUser(connection, channelOwner.Id);
                    if (admin != null)
                    {
                        newConnectionUser.UserName = cr.Name;
                        await Clients.Client(admin.ConnectionId).InvokeAsync("onUserChannelsGroupUserSubscribe",
                                                                             admin.UserId, newConnectionUser);
                    }
                    return chOut;
                }));
            }
            catch (Exception e)
            {
                e.Data.Add("ChannelOwner", channelOwner);
                throw new HubException(e.Message, e);
            }
        }
        public bool UpdateGroupUser(IDbConnection connection, ChannelConnectionUserOut tragetUser, bool updatePasswordByChannel, int channelAdminUserId, Action <GroupChannelOut> setChannelToTargetUserIfBeforeCantRead, Action <ChannelConnectionDataModel> setOldModel)
        {
            var channelData = _channelRepo.GetChannelWithConnectedUsers(connection, tragetUser.ChannelId, new List <int>(tragetUser.UserId));

            if (channelData == null)
            {
                throw new ArgumentNullException(nameof(channelData), Error.NoData);
            }
            if (channelData.creatorId != channelAdminUserId)
            {
                throw new SecurityException(Error.NotPermitted);
            }
            if (!channelData.HasConnections())
            {
                throw new SecurityException(Error.ChannelNotExist);
            }
            var channelConnections = channelData.GetConnections();

            if (channelConnections.Count > 1)
            {
                throw new NotImplementedException("channelConnections.Count >1");
            }
            var channelConnection = channelConnections[0];

            // ReSharper disable ConditionIsAlwaysTrueOrFalse
            // ReSharper disable InvertIf

            setOldModel(_channelConnRepo.ConvertToWorkModel(channelConnection));
            if (!tragetUser.MessageRead && channelConnection.messageRead)
            {
                tragetUser.MessageSend        = false;
                channelConnection.messageRead = tragetUser.MessageRead;
                channelConnection.messageSend = tragetUser.MessageSend;

                return(_channelConnRepo.Update(connection, channelConnection));
            }

            if (tragetUser.MessageRead && !channelConnection.messageRead)
            {
                channelConnection.messageRead = true;
                channelConnection.messageSend = tragetUser.MessageSend;
                if (updatePasswordByChannel)
                {
                    channelConnection.password    = channelData.password;
                    tragetUser.HasCorrectPassword = true;
                }
                if (_channelConnRepo.Update(connection, channelConnection))
                {
                    var targetChat = new GroupChannelOut(channelData.ConvertToWorkModel(), tragetUser.UserId);
                    targetChat.SetMessages(connection, _channelMessageRepo);
                    targetChat.SetComplexButtonView();
                    targetChat.SetBtnSend(tragetUser.MessageSend);
                    setChannelToTargetUserIfBeforeCantRead(targetChat);
                    return(true);
                }
                return(false);
            }

            if (!channelConnection.messageRead)
            {
                return(false);
            }
            var hasChange = false;

            if (updatePasswordByChannel && channelConnection.password != channelData.password)
            {
                channelConnection.password    = channelData.password;
                tragetUser.HasCorrectPassword = true;

                var targetChat = new GroupChannelOut(channelData.ConvertToWorkModel(), tragetUser.UserId);
                targetChat.SetMessages(connection, _channelMessageRepo);
                targetChat.SetComplexButtonView();
                targetChat.SetBtnSend(channelConnection.messageSend);
                setChannelToTargetUserIfBeforeCantRead(targetChat);
                hasChange = true;
            }
            if (channelConnection.messageSend != tragetUser.MessageSend)
            {
                channelConnection.messageSend = tragetUser.MessageSend;
                hasChange = true;
            }
            if (hasChange)
            {
                var suc = _channelConnRepo.Update(connection, channelConnection);
                if (!suc)
                {
                    throw new NotImplementedException();
                }
            }
            return(hasChange);
        }