public async Task GetTeamIdToNamesNoOverwritePermissions()
        {
            ByRoleTeamManager teamManager = CreateTeamManager();
            IReadOnlyDictionary <string, string> teamIdToName = await teamManager.GetTeamIdToNames();

            VerifyAllTeamsInTeamIdToName(teamIdToName);
        }
        public async Task GetPlayerTeamPairsForServerNoRolesEveryoneDeniedView()
        {
            ByRoleTeamManager teamManager = CreateTeamManager((roleId) => roleId != EveryoneRoleId ?
                                                              (OverwritePermissions?)null :
                                                              new OverwritePermissions(viewChannel: PermValue.Deny));
            IEnumerable <IGrouping <string, PlayerTeamPair> > pairs = await teamManager.GetPlayerTeamPairsForServer();

            Assert.AreEqual(PlayerIds.Length, pairs.Count(), "Unexpected number of players");
        }
        public async Task GetKnownPlayersNoRolesEveryoneDeniedView()
        {
            ByRoleTeamManager teamManager = CreateTeamManager((roleId) => roleId != EveryoneRoleId ?
                                                              (OverwritePermissions?)null :
                                                              new OverwritePermissions(viewChannel: PermValue.Deny));
            IEnumerable <PlayerTeamPair> pairs = await teamManager.GetKnownPlayers();

            Assert.AreEqual(0, pairs.Count(), "Unexpected number of players");
        }
        public async Task GetTeamIdToNamesForServerNoRolesEveryoneDeniedView()
        {
            ByRoleTeamManager teamManager = CreateTeamManager((roleId) => roleId != EveryoneRoleId ?
                                                              (OverwritePermissions?)null :
                                                              new OverwritePermissions(viewChannel: PermValue.Deny));
            IReadOnlyDictionary <string, string> teamIdToName = await teamManager.GetTeamIdToNamesForServer();

            Assert.AreEqual(2, teamIdToName.Count, "Unexpected number of teams");
        }
        public async Task GetTeamIdToNamesRolesInheritEveryoneAllowed()
        {
            ByRoleTeamManager teamManager = CreateTeamManager((roleId) => roleId != EveryoneRoleId ?
                                                              OverwritePermissions.InheritAll :
                                                              new OverwritePermissions(viewChannel: PermValue.Allow, sendMessages: PermValue.Allow));
            IReadOnlyDictionary <string, string> teamIdToName = await teamManager.GetTeamIdToNames();

            VerifyAllTeamsInTeamIdToName(teamIdToName);
        }
        public async Task GetTeamIdToNamesRolesInheritEveryoneSendOnly()
        {
            ByRoleTeamManager teamManager = CreateTeamManager((roleId) => roleId != EveryoneRoleId ?
                                                              OverwritePermissions.InheritAll :
                                                              new OverwritePermissions(viewChannel: PermValue.Deny, sendMessages: PermValue.Allow));
            IReadOnlyDictionary <string, string> teamIdToName = await teamManager.GetTeamIdToNames();

            Assert.AreEqual(0, teamIdToName.Count, "Unexpected number of teams");
        }
        public async Task GetTeamIdOfPlayer()
        {
            ByRoleTeamManager teamManager = CreateTeamManager();

            for (int i = 0; i < PlayerIds.Length; i++)
            {
                Assert.AreEqual(
                    RoleIds[i].ToString(CultureInfo.InvariantCulture),
                    await teamManager.GetTeamIdOrNull(PlayerIds[i]),
                    $"Unexpected team ID for player {i}");
            }
        }
        public async Task GetTeamIdToNames()
        {
            ByRoleTeamManager teamManager = CreateTeamManager();
            IReadOnlyDictionary <string, string> teamIdToName = await teamManager.GetTeamIdToNames();

            Assert.AreEqual(RoleIds.Length, teamIdToName.Count, "Unexpected number of teams");

            for (int i = 0; i < RoleIds.Length; i++)
            {
                Assert.IsTrue(
                    teamIdToName.TryGetValue(RoleIds[i].ToString(CultureInfo.InvariantCulture), out string teamName),
                    $"Couldn't get the team name for role ID {RoleIds[i]}");
                Assert.AreEqual(TeamNames[i], teamName, $"Unexpected team name for team #{i + 1}");
            }
        }
        public async Task GetTeamIdToNamesFirstAllowsSecondDeniedEveryoneAllowed()
        {
            ByRoleTeamManager teamManager = CreateTeamManager((roleId) =>
            {
                if (roleId == RoleIds[0] || roleId == EveryoneRoleId)
                {
                    return(new OverwritePermissions(viewChannel: PermValue.Allow, sendMessages: PermValue.Allow));
                }

                return(new OverwritePermissions(viewChannel: PermValue.Deny, sendMessages: PermValue.Deny));
            });

            IReadOnlyDictionary <string, string> teamIdToName = await teamManager.GetTeamIdToNames();

            VerifyOnlyOneTeamInTeamIdToName(teamIdToName);
        }
        public async Task GetKnownPlayers()
        {
            ByRoleTeamManager            teamManager = CreateTeamManager();
            IEnumerable <PlayerTeamPair> pairs       = await teamManager.GetKnownPlayers();

            Assert.AreEqual(PlayerIds.Length, pairs.Count(), "Unexpected number of players");

            for (int i = 0; i < PlayerIds.Length; i++)
            {
                PlayerTeamPair pair = pairs.FirstOrDefault(pair => pair.PlayerId == PlayerIds[i]);
                Assert.IsNotNull(pair, $"Couldn't find the player #{i + 1}");
                Assert.AreEqual(
                    RoleIds[i].ToString(CultureInfo.InvariantCulture),
                    pair.TeamId,
                    $"Unexpected team ID for player #{i + 1}");
            }
        }
        private async Task SetRostersFromRolesForSheets(string sheetsUrl, GoogleSheetsType type)
        {
            if (!(this.Context.Channel is IGuildChannel guildChannel))
            {
                return;
            }

            if (!Uri.TryCreate(sheetsUrl, UriKind.Absolute, out Uri sheetsUri))
            {
                await this.Context.Channel.SendMessageAsync(
                    "The link to the Google Sheet wasn't understandable. Be sure to copy the full URL from the address bar.");

                return;
            }

            Logger.Information($"User {this.Context.User.Id} attempting to export a {type.ToString()} scoresheet");

            // TODO: Figure out an limitation story (count as export? Separate DB field?)
            string teamRolePrefix;

            using (DatabaseAction action = this.DatabaseActionFactory.Create())
            {
                teamRolePrefix = await action.GetTeamRolePrefixAsync(this.Context.Guild.Id);
            }

            if (string.IsNullOrEmpty(teamRolePrefix))
            {
                await this.Context.Channel.SendMessageAsync(
                    "Couldn't export to the rosters sheet. This server is not using the team role prefix. Use !setTeamRolePrefix to set the prefix for role names to use for teams.");

                return;
            }

            IByRoleTeamManager     teamManager = new ByRoleTeamManager(guildChannel, teamRolePrefix);
            IGoogleSheetsGenerator generator   = this.GoogleSheetsGeneratorFactory.Create(type);
            IResult <string>       result      = await generator.TryUpdateRosters(teamManager, sheetsUri);

            if (!result.Success)
            {
                await this.Context.Channel.SendMessageAsync(result.ErrorMessage);

                return;
            }

            await this.Context.Channel.SendMessageAsync("Rosters updated.");
        }
        public async Task GetTeamIdToNamesFirstPartialSecondInheritsEveryoneDenied()
        {
            ByRoleTeamManager teamManager = CreateTeamManager((roleId) =>
            {
                if (roleId == RoleIds[0])
                {
                    return(new OverwritePermissions(viewChannel: PermValue.Allow, sendMessages: PermValue.Inherit));
                }
                else if (roleId == EveryoneRoleId)
                {
                    return(new OverwritePermissions(viewChannel: PermValue.Deny, sendMessages: PermValue.Deny));
                }

                return(OverwritePermissions.InheritAll);
            });

            IReadOnlyDictionary <string, string> teamIdToName = await teamManager.GetTeamIdToNames();

            Assert.AreEqual(0, teamIdToName.Count, "Unexpected number of teams");
        }
        public async Task GetTeamIdOfNonexistentUser()
        {
            ByRoleTeamManager teamManager = CreateTeamManager();

            Assert.IsNull(await teamManager.GetTeamIdOrNull(NonexistentUserId), "Unexpected team ID");
        }
        public async Task ReloadTeamRoles()
        {
            Mock <IGuild> mockGuild = new Mock <IGuild>();
            List <IRole>  roles     = new List <IRole>();

            for (int i = 0; i < RoleIds.Length; i++)
            {
                Mock <IRole> mockRole = new Mock <IRole>();
                mockRole.Setup(role => role.Id).Returns(RoleIds[i]);
                mockRole.Setup(role => role.Name).Returns(RoleNames[i]);
                roles.Add(mockRole.Object);
            }

            mockGuild
            .Setup(guild => guild.Roles)
            .Returns(roles);

            bool newRolesAssigned   = false;
            List <IGuildUser> users = new List <IGuildUser>();

            for (int i = 0; i < PlayerIds.Length; i++)
            {
                Mock <IGuildUser> mockUser = new Mock <IGuildUser>();
                mockUser.Setup(user => user.Id).Returns(PlayerIds[i]);
                mockUser.Setup(user => user.Nickname).Returns($"User_{PlayerIds[i]}");

                // Make a copy so that we don't use the value of i after it's done in the loop in the return function's
                // closure
                int index = i;
                mockUser.Setup(user => user.RoleIds).Returns(() =>
                {
                    if (newRolesAssigned || index % 2 == 0)
                    {
                        return(new ulong[] { RoleIds[index] });
                    }

                    return(Array.Empty <ulong>());
                });
                users.Add(mockUser.Object);
            }

            IReadOnlyCollection <IGuildUser> readonlyUsers = users;

            mockGuild
            .Setup(guild => guild.GetUsersAsync(It.IsAny <CacheMode>(), It.IsAny <RequestOptions>()))
            .Returns <CacheMode, RequestOptions>((mode, options) => Task.FromResult(readonlyUsers));
            mockGuild
            .Setup(guild => guild.GetUserAsync(It.IsAny <ulong>(), It.IsAny <CacheMode>(), It.IsAny <RequestOptions>()))
            .Returns <ulong, CacheMode, RequestOptions>((id, mode, options) => Task.FromResult(users.FirstOrDefault(user => user.Id == id)));

            Mock <IGuildChannel> mockGuildChannel = new Mock <IGuildChannel>();

            mockGuildChannel
            .Setup(channel => channel.GetPermissionOverwrite(It.IsAny <IRole>()))
            .Returns <IRole>(null);
            mockGuildChannel
            .SetupGet(channel => channel.Guild)
            .Returns(mockGuild.Object);

            ByRoleTeamManager teamManager = new ByRoleTeamManager(mockGuildChannel.Object, DefaultTeamRolePrefix);

            IEnumerable <PlayerTeamPair> players = await teamManager.GetKnownPlayers();

            Assert.AreEqual(PlayerIds.Length / 2, players.Count(), "Unexpected number of players the first time");
            Assert.AreEqual(PlayerIds[0], players.First().PlayerId, "Unexpected player in the first set of players");

            newRolesAssigned = true;
            string message = teamManager.ReloadTeamRoles();

            Assert.IsNotNull(message, "Message to report shouldn't be null");
            Assert.AreEqual(PlayerIds.Length, players.Count(), "Unexpected number of players the second time");
            Assert.IsTrue(players.Any(player => player.PlayerId == PlayerIds[0]), "First player isn't in the list of teams");
            Assert.IsTrue(players.Any(player => player.PlayerId == PlayerIds[1]), "Second player isn't in the list of teams");
        }