import discord

from io import BytesIO
from utils import default
from utils.default import CustomContext
from discord.ext import commands
from utils.data import DiscordBot


class Discord_Info(commands.Cog):
    def __init__(self, bot):
        self.bot: DiscordBot = bot

    @commands.command(aliases=["av", "pfp"])
    @commands.guild_only()
    async def avatar(self, ctx: CustomContext, *, user: discord.Member = None):
        """ Get the avatar of you or someone else """
        user = user or ctx.author

        avatars_list = []

        def target_avatar_formats(target):
            formats = ["JPEG", "PNG", "WebP"]
            if target.is_animated():
                formats.append("GIF")
            return formats

        if not user.avatar and not user.guild_avatar:
            return await ctx.send(f"**{user}** has no avatar set, at all...")

        if user.avatar:
            avatars_list.append("**Account avatar:** " + " **-** ".join(
                f"[{img_format}]({user.avatar.replace(format=img_format.lower(), size=1024)})"
                for img_format in target_avatar_formats(user.avatar)
            ))

        embed = discord.Embed(colour=user.top_role.colour.value)

        if user.guild_avatar:
            avatars_list.append("**Server avatar:** " + " **-** ".join(
                f"[{img_format}]({user.guild_avatar.replace(format=img_format.lower(), size=1024)})"
                for img_format in target_avatar_formats(user.guild_avatar)
            ))
            embed.set_thumbnail(url=user.avatar.replace(format="png"))

        embed.set_image(url=f"{user.display_avatar.with_size(256).with_static_format('png')}")
        embed.description = "\n".join(avatars_list)

        await ctx.send(f"🖼 Avatar to **{user}**", embed=embed)

    @commands.command()
    @commands.guild_only()
    async def roles(self, ctx: CustomContext):
        """ Get all roles in current server """
        allroles = ""

        for num, role in enumerate(sorted(ctx.guild.roles, reverse=True), start=1):
            allroles += f"[{str(num).zfill(2)}] {role.id}\t{role.name}\t[ Users: {len(role.members)} ]\r\n"

        data = BytesIO(allroles.encode("utf-8"))
        await ctx.send(content=f"Roles in **{ctx.guild.name}**", file=discord.File(data, filename=f"{default.timetext('Roles')}"))

    @commands.command(aliases=["joindate", "joined"])
    @commands.guild_only()
    async def joinedat(self, ctx: CustomContext, *, user: discord.Member = None):
        """ Check when a user joined the current server """
        user = user or ctx.author
        await ctx.send("\n".join([
            f"**{user}** joined **{ctx.guild.name}**",
            f"{default.date(user.joined_at, ago=True)}"
        ]))

    @commands.command()
    @commands.guild_only()
    async def mods(self, ctx: CustomContext):
        """ Check which mods are online on current guild """
        message = ""
        all_status = {
            "online": {"users": [], "emoji": "🟢"},
            "idle": {"users": [], "emoji": "🟡"},
            "dnd": {"users": [], "emoji": "🔴"},
            "offline": {"users": [], "emoji": "⚫"}
        }

        for user in ctx.guild.members:
            user_perm = ctx.channel.permissions_for(user)
            if user_perm.kick_members or user_perm.ban_members:
                if not user.bot:
                    all_status[str(user.status)]["users"].append(f"**{user}**")

        for g in all_status:
            if all_status[g]["users"]:
                message += f"{all_status[g]['emoji']} {', '.join(all_status[g]['users'])}\n"

        await ctx.send(f"Mods in **{ctx.guild.name}**\n{message}")

    @commands.group()
    @commands.guild_only()
    async def server(self, ctx: CustomContext):
        """ Check info about current server """
        if ctx.invoked_subcommand is None:
            find_bots = sum(1 for member in ctx.guild.members if member.bot)

            embed = discord.Embed()

            if ctx.guild.icon:
                embed.set_thumbnail(url=ctx.guild.icon)
            if ctx.guild.banner:
                embed.set_image(url=ctx.guild.banner.with_format("png").with_size(1024))

            embed.add_field(name="Server Name", value=ctx.guild.name)
            embed.add_field(name="Server ID", value=ctx.guild.id)
            embed.add_field(name="Members", value=ctx.guild.member_count)
            embed.add_field(name="Bots", value=find_bots)
            embed.add_field(name="Owner", value=ctx.guild.owner)
            embed.add_field(name="Created", value=default.date(ctx.guild.created_at, ago=True))
            await ctx.send(content=f"ℹ information about **{ctx.guild.name}**", embed=embed)

    @server.command(name="avatar", aliases=["icon"])
    @commands.guild_only()
    async def server_avatar(self, ctx: CustomContext):
        """ Get the current server icon """
        if not ctx.guild.icon:
            return await ctx.send("This server does not have an icon...")

        format_list = []
        formats = ["JPEG", "PNG", "WebP"]
        if ctx.guild.icon.is_animated():
            formats.append("GIF")

        for img_format in formats:
            format_list.append(f"[{img_format}]({ctx.guild.icon.replace(format=img_format.lower(), size=1024)})")

        embed = discord.Embed()
        embed.set_image(url=f"{ctx.guild.icon.with_size(256).with_static_format('png')}")
        embed.title = "Icon formats"
        embed.description = " **-** ".join(format_list)

        await ctx.send(f"🖼 Icon to **{ctx.guild.name}**", embed=embed)

    @server.command(name="banner")
    async def server_banner(self, ctx: CustomContext):
        """ Get the current banner image """
        if not ctx.guild.banner:
            return await ctx.send("This server does not have a banner...")

        await ctx.send("\n".join([
            f"Banner of **{ctx.guild.name}**",
            f"{ctx.guild.banner.with_format('png')}"
        ]))

    @commands.command()
    @commands.guild_only()
    async def user(self, ctx: CustomContext, *, user: discord.Member = None):
        """ Get user information """
        user = user or ctx.author

        show_roles = "None"
        if len(user.roles) > 1:
            show_roles = ", ".join([
                f"<@&{x.id}>" for x in sorted(
                    user.roles, key=lambda x: x.position,
                    reverse=True
                )
                if x.id != ctx.guild.default_role.id
            ])

        embed = discord.Embed(colour=user.top_role.colour.value)
        embed.set_thumbnail(url=user.avatar)

        embed.add_field(name="Full name", value=user)
        embed.add_field(name="Nickname", value=user.nick if hasattr(user, "nick") else "None")
        embed.add_field(name="Account created", value=default.date(user.created_at, ago=True))
        embed.add_field(name="Joined this server", value=default.date(user.joined_at, ago=True))
        embed.add_field(name="Roles", value=show_roles, inline=False)

        await ctx.send(content=f"ℹ About **{user.id}**", embed=embed)


async def setup(bot):
    await bot.add_cog(Discord_Info(bot))
