from math import floor
from typing import List

from discord import Embed, Member
from discord.ext.commands import Cog, command
from discord.utils import get

from .utils import add_cog, align_separator


class RankProfile(Cog):

    def __init__(self, bot):
        self.bot = bot
        self.rank_roles = self.bot.MongoDB(collection='Rank_Roles')
        self.rank_system = self.bot.MongoDB(collection='Rank_System')

    @Cog.listener()
    async def on_ready(self):
        print('Loaded > Class %s' % (self.__class__.__name__))

    @command()
    async def rank(self, ctx, member: Member = None):
        """Checks current Rank in Guild."""

        member: Member = (
            ctx.author
            if member is None
            else member
        )

        if member.bot:
            return await ctx.send('Bot users can not receive Ranks.')

        _filter = {'guild_id': ctx.guild.id}
        data = await self.rank_roles.find_one(filter=_filter)

        role_list = []

        if data is not None:
            for number in data:
                if number.lower().startswith('role'):

                    # Remove 'Role' from field in database
                    # to be left with just the number
                    # that we can use to loop through our roles
                    # and append to our empty list `role_list`.
                    n = number[4:]

                    role_id = data[f'Role{n}']
                    role = get(ctx.guild.roles, id=role_id)
                    role_list.append(role)

            # Loop through roles in role_list
            # and check if rank role is in member's roles.
            for role in role_list:

                if role in member.roles:
                    rank = role.mention

                elif role not in member.roles:
                    pass

        # if no rank roles were set up for Rank System,
        # use member's top role as Rank.
        else:
            rank = member.top_role.mention

        result = await self.rank_system.find_one(
            filter={'guild_id': ctx.guild.id, 'user_id': member.id}
        )

        if not result:
            response: str = 'Member has not sent any messages!'
            return await ctx.send(response)

        elif result:

            level: int = result['level']
            experience: float = result['experience']

            total_exp: int = floor((((level + 1) ** 4) ** 2) ** (1 / 3))

            status: str = str(member.status).title()

            embed: Embed = Embed(
                description=f'{member.mention} is {status}',
                color=member.color,
                timestamp=ctx.message.created_at
            )

            embed.set_author(
                name=f'{member.name} | Rank Profile',
                icon_url=member.avatar_url
            )

            embed.set_thumbnail(url=member.avatar_url)

            categories = {
                '🔰 RANK': f'{rank}',
                '🔥 LEVEL': f'**{level}**',
                '✨ EXP': f'**{experience}**/{total_exp}'
            }

            keys: List[str] = list(categories.keys())
            fields: List[str] = align_separator(keys, sep=':', spaces=0)

            profile: str = ''

            for i in range(len(fields)):
                profile += f'{fields[i]} {categories[keys[i]]}\n'

            profile += '\uFEFF'

            embed.add_field(name='**STATS**', value=profile, inline=False)
            embed.set_footer(text=ctx.guild.name, icon_url=ctx.guild.icon_url)

            return await ctx.message.reply(embed=embed)


# Required at the end of every module.
def setup(bot):
    return add_cog(bot, __name__)

from math import floor
from typing import List

from discord import Embed, Member
from discord.ext.commands import Cog, command
from discord.utils import get

from .utils import add_cog, align_separator


class RankProfile(Cog):

    def __init__(self, bot):
        self.bot = bot
        self.rank_roles = self.bot.MongoDB(collection='Rank_Roles')
        self.rank_system = self.bot.MongoDB(collection='Rank_System')

    @Cog.listener()
    async def on_ready(self):
        print('Loaded > Class %s' % (self.__class__.__name__))

    @command()
    async def rank(self, ctx, member: Member = None):
        """Checks current Rank in Guild."""

        member: Member = (
            ctx.author
            if member is None
            else member
        )

        if member.bot:
            return await ctx.send('Bot users can not receive Ranks.')

        _filter = {'guild_id': ctx.guild.id}
        data = await self.rank_roles.find_one(filter=_filter)

        role_list = []

        if data is not None:
            for number in data:
                if number.lower().startswith('role'):

                    # Remove 'Role' from field in database
                    # to be left with just the number
                    # that we can use to loop through our roles
                    # and append to our empty list `role_list`.
                    n = number[4:]

                    role_id = data[f'Role{n}']
                    role = get(ctx.guild.roles, id=role_id)
                    role_list.append(role)

            # Loop through roles in role_list
            # and check if rank role is in member's roles.
            for role in role_list:

                if role in member.roles:
                    rank = role.mention

                elif role not in member.roles:
                    pass

        # if no rank roles were set up for Rank System,
        # use member's top role as Rank.
        else:
            rank = member.top_role.mention

        result = await self.rank_system.find_one(
            filter={'guild_id': ctx.guild.id, 'user_id': member.id}
        )

        if not result:
            response: str = 'Member has not sent any messages!'
            return await ctx.send(response)

        elif result:

            level: int = result['level']
            experience: float = result['experience']

            total_exp: int = floor((((level + 1) ** 4) ** 2) ** (1 / 3))

            status: str = str(member.status).title()

            embed: Embed = Embed(
                description=f'{member.mention} is {status}',
                color=member.color,
                timestamp=ctx.message.created_at
            )

            embed.set_author(
                name=f'{member.name} | Rank Profile',
                icon_url=member.avatar_url
            )

            embed.set_thumbnail(url=member.avatar_url)

            categories = {
                '🔰 RANK': f'{rank}',
                '🔥 LEVEL': f'**{level}**',
                '✨ EXP': f'**{experience}**/{total_exp}'
            }

            keys: List[str] = list(categories.keys())
            fields: List[str] = align_separator(keys, sep=':', spaces=0)

            profile: str = ''

            for i in range(len(fields)):
                profile += f'{fields[i]} {categories[keys[i]]}\n'

            profile += '\uFEFF'

            embed.add_field(name='**STATS**', value=profile, inline=False)
            embed.set_footer(text=ctx.guild.name, icon_url=ctx.guild.icon_url)

            return await ctx.message.reply(embed=embed)


# Required at the end of every module.
def setup(bot):
    return add_cog(bot, __name__)

Checks current Rank in Guild. # Remove 'Role' from field in database # to be left with just the number # that we can use to loop through our roles # and append to our empty list `role_list`. # Loop through roles in role_list # and check if rank role is in member's roles. # if no rank roles were set up for Rank System, # use member's top role as Rank. # Required at the end of every module.