import discord
from user_manager import user_manager
import storybot_exceptions
from file_manager import file_manager
import config

class AskForPause(discord.ui.View):
    def __init__(self, server_name: str, guild_id: int, dml, file_manager: file_manager, generic_discord):
        super().__init__(timeout=None)
        self.value = None
        self.guild_id = guild_id
        self.dm_listener = dml
        self.file_manager = file_manager
        self.msg = None
        self.generic_discord = generic_discord
        
    async def set_message_id(self, message_id: int):
        await self.file_manager.set_persistent_message_guild(message_id, self.guild_id)

    @discord.ui.button(label='Pause for 1 week', style=discord.ButtonStyle.green, custom_id="ask_for_pause:pause7")
    async def pause_for_a_week(self, interaction: discord.Interaction, button: discord.ui.Button):
        g_id = await self.file_manager.get_guild_id_for_persistent_view(interaction.message.id)
        if g_id == None:
            await self.generic_discord.reply_to_message(reply_to=interaction, content="I'm sorry, but this interaction has expired!", error=True)
            return
        
        guild_name = (await self.dm_listener.bot.fetch_guild(g_id)).name
        
        self.value = 7
        try:
            await self.dm_listener.pause_user_with_logic(guild_id=g_id, user_id=interaction.user.id, days=self.value)
            await self.generic_discord.reply_to_message(reply_to=interaction, content=f"Confirmed! You won't be chosen as the author for the next week in {guild_name}!\n\nIf you change your mind before then, run `/join` to unpause yourself!")
        except storybot_exceptions.NotAnAuthorException:
            await self.generic_discord.reply_to_message(reply_to=interaction, content=f"You aren't currently an author in {guild_name}, so you can't pause yourself!")
        
        
        await self.cleanup()
        
        
    @discord.ui.button(label='Leave', style=discord.ButtonStyle.danger, custom_id="ask_for_pause:leave")
    async def leave(self, interaction: discord.Interaction, button: discord.ui.Button):
        await interaction.response.defer(thinking=True)
        g_id = await self.file_manager.get_guild_id_for_persistent_view(interaction.message.id)
        if g_id == None:
            await self.generic_discord.reply_to_message(reply_to=interaction, content="I'm sorry, but this interaction has expired!", error=True)
            return
        
        guild_name = (await self.dm_listener.bot.fetch_guild(g_id)).name
        
        await self.dm_listener.remove_user(guild_id=g_id, user_id=interaction.user.id)
        await self.generic_discord.reply_to_message(reply_to=interaction, content=f"Confirmed! You have been removed as an author in {guild_name}!\n\nIf you change your mind later, run `/join` in {guild_name} to rejoin!")
        
        await self.cleanup()
        
        
    @discord.ui.button(label='Do nothing', style=discord.ButtonStyle.grey, custom_id="ask_for_pause:donothing")
    async def do_nothing(self, interaction: discord.Interaction, button: discord.ui.Button):
        g_id = await self.file_manager.get_guild_id_for_persistent_view(interaction.message.id)
        if g_id == None:
            await self.generic_discord.reply_to_message(reply_to=interaction, content="I'm sorry, but this interaction has expired!", error=True)
            return
        
        guild_name = (await self.dm_listener.bot.fetch_guild(g_id)).name
        
        await self.generic_discord.reply_to_message(reply_to=interaction, content=f"Confirmed! You are still an author in {guild_name}!")
        # The log makes sure the user won't get DMed next time they skip
        await self.file_manager.log_action(user_id=interaction.user.id, guild_id=self.guild_id, XSS_WARNING_action="confirm")
        await self.cleanup()
        
    async def cleanup(self):
        if self.msg != None: await self.msg.delete()
        #self.stop()
        
        
class NormalTurnMessage(discord.ui.View):
    def __init__(self, server_name: str, guild_id: int, dml, user_manager: user_manager, file_manager: file_manager, generic_discord):
        super().__init__(timeout=None)
        self.value = None
        self.guild_id = guild_id
        self.dm_listener = dml
        self.umr = user_manager
        self.file_manager = file_manager
        self.generic_discord = generic_discord
        
    async def set_message_id(self, message_id: int):
        await self.file_manager.set_persistent_message_guild(message_id, self.guild_id)
        
        
    @discord.ui.button(label='Skip me', style=discord.ButtonStyle.red, custom_id="normal_turn_message:skip")
    async def leave(self, interaction: discord.Interaction, button: discord.ui.Button):
        await interaction.response.defer(thinking=True)
        g_id = await self.file_manager.get_guild_id_for_persistent_view(interaction.message.id)
        if g_id == None:
            await self.generic_discord.reply_to_message(reply_to=interaction, content="I'm sorry, but this interaction has expired!", error=True)
            return
        
        guild_name = (await self.dm_listener.bot.fetch_guild(g_id)).name
        
        
        
        if (await self.umr.get_current_user(guild_id=g_id)) == interaction.user.id:
            await self.dm_listener.new_user(guild_id=g_id, log_skip = True)
            await self.generic_discord.reply_to_message(reply_to=interaction, content=f"You have been skipped in {guild_name}!")
            
        else:
            await self.generic_discord.reply_to_message(reply_to=interaction, content=f"It's not currently your turn in {guild_name}!")
        
        await self.cleanup()

    @discord.ui.button(label='Pause for a week', style=discord.ButtonStyle.grey, custom_id="normal_turn_message:pause7")
    async def pause_for_a_week(self, interaction: discord.Interaction, button: discord.ui.Button):
        await interaction.response.defer(thinking=True)
        g_id = await self.file_manager.get_guild_id_for_persistent_view(interaction.message.id)
        if g_id == None:
            await self.generic_discord.reply_to_message(reply_to=interaction, content="I'm sorry, but this interaction has expired!", error=True)
            return
        
        guild_name = (await self.dm_listener.bot.fetch_guild(g_id)).name
        
        self.value = 7
        try:
            await self.dm_listener.pause_user_with_logic(guild_id=g_id, user_id=interaction.user.id, days=self.value)
            
            await self.generic_discord.reply_to_message(reply_to=interaction, content=f"Confirmed! You won't be chosen as the author for the next week in {guild_name}!\n\nIf you change your mind before then, run `/join` to unpause yourself!")
            
        except storybot_exceptions.NotAnAuthorException:
            await self.generic_discord.reply_to_message(reply_to=interaction, content=f"You aren't currently an author in {guild_name}, so you can't pause yourself!")
        
        await self.cleanup()
        
    async def cleanup(self):
        #self.stop()
        pass


class JoinButton(discord.ui.View):
    def __init__(self, guild_id: int, dml, file_manager: file_manager, generic_discord):
        super().__init__(timeout=None)
        self.guild_id = guild_id
        self.dm_listener = dml
        self.file_manager = file_manager
        self.generic_discord = generic_discord
        
    async def set_message_id(self, message_id: int):
        await self.file_manager.set_persistent_message_guild(message_id, self.guild_id)

    @discord.ui.button(label='Join', style=discord.ButtonStyle.green, custom_id="joinbutton:add")
    async def add(self, interaction: discord.Interaction, button: discord.ui.Button):
        g_id = await self.file_manager.get_guild_id_for_persistent_view(interaction.message.id)
        if g_id == None:
            await self.generic_discord.reply_to_message(reply_to=interaction, content="I'm sorry, but this interaction has expired!", error=True)
            return
        
        await self.dm_listener.add_via_interaction(interaction = interaction, guild_id = g_id, public = False)
        
        await self.cleanup()
        
    async def cleanup(self):
        # Don't delete/remove the button, as it can be used by other users
        pass


class LinkToSupportServer(discord.ui.View):
    def __init__(self):
        super().__init__()
        # we need to quote the query string to make a valid url. Discord will raise an error if it isn't valid.
        url = config.SERVER_INVITE_LINK

        # Link buttons cannot be made with the decorator
        # Therefore we have to manually create one.
        # We add the quoted url to the button, and add the button to the view.
        self.add_item(discord.ui.Button(label='Support Server', url=url))


class InviteAndSupportServerLinks(discord.ui.View):
    def __init__(self):
        super().__init__()
        # we need to quote the query string to make a valid url. Discord will raise an error if it isn't valid.
        
        url = config.BOT_INVITE_LINK
        self.add_item(discord.ui.Button(label='Invite this bot!', url=url, style=discord.ButtonStyle.green))
        
        url = config.SERVER_INVITE_LINK
        self.add_item(discord.ui.Button(label='Support server', url=url))


# Define a simple View that gives us a confirmation menu
class Confirm(discord.ui.View):
    def __init__(self, enabled: bool=True):
        super().__init__()
        self.value = None
        self.interaction = None
        self.timeout = 60
        self.enab = enabled

    # When the confirm button is pressed, set the inner value to `True` and
    # stop the View from listening to more input.
    # We also send the user an ephemeral message that we're confirming their choice.
    @discord.ui.button(label='Confirm', style=discord.ButtonStyle.green)
    async def confirm(self, interaction: discord.Interaction, button: discord.ui.Button):
        if not self.enab:
            await interaction.response.send_message("I'm sorry, but this interaction has expired!")
        self.value = True
        self.interaction = interaction
        self.cleanup()

    # This one is similar to the confirmation button except sets the inner value to `False`
    @discord.ui.button(label='Cancel', style=discord.ButtonStyle.red)
    async def cancel(self, interaction: discord.Interaction, button: discord.ui.Button):
        if not self.enab:
            await interaction.response.send_message("I'm sorry, but this interaction has expired!")
        self.value = False
        self.interaction = interaction
        self.cleanup()
        

    def cleanup(self):
        self.enab = False
        self.stop()
        
class DropdownView(discord.ui.View):
    def __init__(self, server_json, dropdown_placeholder='Which server is this story for?'):
        super().__init__(timeout=300)

        # Adds the dropdown to our view object.
        self.add_item(ServerChooser(server_json, self, dropdown_placeholder))
        self.guild_id = None
        self.value = None
        
    async def set_message_id(self, guild_id: int):
        pass

class ServerChooser(discord.ui.Select):
    def __init__(self, guild_json, view, dropdown_placeholder):
        guilds = []

        for item in guild_json:
            option = discord.SelectOption(label=item["name"],
                                          value=item["id"])
            
            guilds.append(option)
            
        self.vv = view
        super().__init__(placeholder=dropdown_placeholder, min_values=1, max_values=1, options=guilds)
        
    async def callback(self, interaction: discord.Interaction):
        self.vv.value = self.values[0]
        self.vv.guild_id = self.values[0]
        self.vv.stop()

