import asyncio

from discord import Activity, ActivityType, TextChannel

from core.dict_object import DictObject


class DiscordManager:
    def __init__(self, client):
        self.client = client
        client = client.client
        client.event(self.on_ready)
        client.event(self.on_member_join)
        client.event(self.on_member_remove)
        client.event(self.on_member_update)
        client.event(self.on_guild_role_delete)
        client.event(self.on_guild_role_create)
        client.event(self.on_guild_role_update)
        client.event(self.on_invite_create)
        client.event(self.on_invite_delete)

    async def on_member_update(self, member_before, member_after):
        await self.client.discord_update_bot_basic()

    async def on_guild_role_create(self, role):
        await self.client.discord_update_bot_full()

    async def on_guild_role_delete(self, role):
        await self.client.discord_update_bot_full()

    async def on_guild_role_update(self, role_before, role_after):
        await self.client.discord_update_bot_full()

    async def on_invite_create(self, invite):
        await self.client.discord_update_bot_full()

    async def on_invite_delete(self, invite):
        await self.client.discord_update_bot_full()

    async def on_member_join(self, member):
        temp_invites = await self.client.guild.invites()
        invite_used = self.discord_invite_used(temp_invites)
        self.client.discord_queue.append(
            DictObject({"type": "on_member_join", "member": member, "invite": invite_used}))
        await invite_used.delete()

    def discord_invite_used(self, temp_invites):
        for temp_invite in temp_invites:
            # if temp_invite.inviter.id == self.client.user.id:
            # ## Using this line limits it to invite created by the account the Discord bot runs as..
            for invite in self.client.invites:
                if int(temp_invite.uses) > int(invite.uses) and temp_invite.code == invite.code:
                    return temp_invite
        return None

    async def on_member_remove(self, member):
        self.client.discord_queue.append(DictObject({"type": "on_member_remove", "member": member}))
        await self.client.discord_update_bot_full()

    async def on_ready(self):
        await self.client.discord_update_bot_full()
        count = self.client.db.query_single('SELECT count(*) as count from online '
                                            'where char_id NOT IN (select char_id from org_bots) and bot=?',
                                            [self.client.bot.get_char_id()]).count

        act = Activity(type=ActivityType.listening,
                       name=f"{count} Players")
        asyncio.run_coroutine_threadsafe(self.client.client.change_presence(activity=act), self.client.loop)
        asyncio.run_coroutine_threadsafe(self.client.setup_relayhub(), self.client.loop)
        await self.clean_channel()

        if self.client.guild.large:
            self.client.logger.error(
                f"Guild {self.client.guild.name} is classified as large, "
                f"you need to request offline members to manage roles properly, this is not yet implemented")

    async def clean_channel(self):
        for channel in self.client.setting_service.get_value("public_relay").lstrip("[").rstrip("]").split(','):
            if ch := self.client.client.get_channel(int(channel)):
                for i in range(5):
                    await ch.purge(check=self.client.check)

