import asyncio
import datetime
import discord
from random import choice
from discord.ext import commands
from discord.ext.tasks import loop
from BotResources import write_config_file

#from phraseGenerator import PhraseGenerator


class WillieTimer(commands.Cog):
    def __init__(self, bot): #, mention_group='Superadmins', channel_id=757379843792044102):
        self.bot = bot
        self.mention_group = str(self.bot.Default_Mention_Group)
        self.channel_id = int(self.bot.Default_Channel_ID)
        self.channel = None
        self.guild = None
        self.lock = False
        self.current_420_phrase = None
        self.current_warm_up_phrase = None
        self.caller_name = None

        #self.PG = PhraseGenerator()

    @loop(minutes=1)
    async def bg_timer(self):
        # Get variables ready before waiting for the next minute, might take a few seconds
        await self.bot.wait_until_ready()
        output_string = self.get_output_string()

        seconds_until_next_minute = int(60 - int(datetime.datetime.now().strftime('%S')))

        if not seconds_until_next_minute <= 2:
            await asyncio.sleep(seconds_until_next_minute)

        # If it is 4:20pm
        if datetime.datetime.now().strftime('%H:%M') in "16:20":
            print(f"It's {datetime.datetime.now().strftime('%H:%M:%S')}!")
            await self.channel.send(output_string['420'])

        # A warm up to 4:20pm
        if datetime.datetime.now().strftime('%H:%M') in "16:17":
            print(f"It's {datetime.datetime.now().strftime('%H:%M:%S')}!")
            await self.channel.send(output_string['warm up'])

        del output_string

    @commands.command(help="Use this command to start the background task to wait for 4:20",
                      brief="Starts the 4:20 clock")
    async def start420(self, ctx, *, member: discord.Member = None):
        member = member or ctx.author.display_name
        if not self.lock:
            await ctx.send(f"Thanks {member}, Willie will be in touch soon...")
            self.channel = self.bot.get_channel(id=self.channel_id)
            self.guild = self.channel.guild
            self.lock = True
            self.caller_name = str(member)
            self.bg_timer.start()
        else:
            await ctx.send(f"I already told Willie {member}, if you want me to tell him to stop, @ me and say 'stop420'")

    @commands.command(help="", brief="Stops the 4:20 clock")
    async def stop420(self, ctx, *, member: discord.Member = None):
        member = member or ctx.author.display_name
        if self.lock:
            await ctx.send(f"Ok {member}, Willie will go back to writing music...")
            self.bg_timer.stop()
            self.lock = False
            self.caller_name = None
        else:
            await ctx.send(f"{member} I haven't told Willie yet. If you want me to, @ me and say 'start420'")

    @commands.command(name='420chchn', help="Example '@Greada chchn 757379843792044102'",
                      brief="Change the channel the bot chats in at 4:20")
    async def chchn(self, ctx, message, *, member: discord.Member = None):
        member = member or ctx.author.display_name
        try:
            message = int(message)
            if message and len(str(message)) == len(str(self.channel_id)):
                self.channel_id = message
                await ctx.send(f"Ok {member}, I'll let Willie know to reach you in "
                               f"{self.bot.get_channel(id=self.channel_id)}")
                print(message)
                write_config_file(Channel_ID=self.channel_id)
        except Exception as e:
            print(f"Exception in chchn:\t{e}")
            await ctx.send(f"{member}, {message} is not a valid channel ID, please try again")
            pass

    @commands.command(name='420chmtn', help="Example '@Greada chmtn 'Willies Friends'",
                      brief="Use this command to change who the bot mentions at 4:20")
    async def chmtn(self, ctx, message, *, member: discord.Member = None):
        member = member or ctx.author.display_name
        try:
            message = str(message)
            if message:
                self.mention_group = message
                await ctx.send(f"Ok {member}, I'll let Willie know to tell {self.bot_get_role()}")
                print(message)
                write_config_file(mention_group=self)
        except Exception as e:
            print(f"Exception in chmtn:\t{e}")
            await ctx.send(f"{member}, {message} is not a valid role, please try again")
            pass

    @commands.command(help='Test random choice')
    async def test_rchoice(self, ctx, *, member: discord.Member = None):
        member = member or ctx.author.display_name
        self.channel = self.bot.get_channel(id=self.channel_id)
        self.guild = self.channel.guild
        strings_dict = self.get_output_string()
        await ctx.send(f"420:\t{strings_dict['420']}\nWarning:\t{strings_dict['warm up']}", tts=True)

    def bot_get_role(self):
        role = discord.utils.get(self.guild.roles, name=self.mention_group)
        return role

    def bot_get_user(self, input_user=None):
        if self.caller_name is not None:
            user = discord.utils.get(self.guild.members, name=self.caller_name)
            return user
        elif input_user is not None:
            user = discord.utils.get(self.guild.members, name=input_user)
            return user

    def get_random_420_phrase(self):
        selected_phrase = None
        while not selected_phrase:
            with open('./modules/WillieTimer/Phrases.txt', 'r') as phrase_file:
                phrases = phrase_file.readlines()
                selected_phrase = choice(phrases)

            if selected_phrase is not None:
                if selected_phrase != self.current_420_phrase:
                    selected_phrase = selected_phrase.replace('\n', '')
                    self.current_420_phrase = selected_phrase
                    return selected_phrase
                else:
                    selected_phrase = None
                    continue

    def get_random_warm_up_phrase(self):
        selected_phrase = None
        while not selected_phrase:
            #selected_phrase = self.PG.pg_generate()
            with open('./modules/WillieTimer/lyrics.min.txt', 'r') as phrase_file:
                phrases = phrase_file.readlines()
                selected_phrase = choice(phrases)

            if selected_phrase is not None:
                if selected_phrase != self.current_warm_up_phrase:
                    selected_phrase = selected_phrase.replace('\n', '')
                    self.current_warm_up_phrase = selected_phrase
                    return selected_phrase
                else:
                    selected_phrase = None
                    continue

    def get_output_string(self):
        willie_time_string = ""
        warm_up_string = ""
        if self.caller_name is not None:
            willie_time_string += f"<@{self.bot_get_user().id}> & "
            warm_up_string += f"<@{self.bot_get_user().id}> & "

        willie_time_string += f"<@&{self.bot_get_role().id}>! "\
                              f"Willie wanted me to tell you:\n" \
                              f"\"{self.get_random_420_phrase()}\""

        warm_up_string += f"<@&{self.bot_get_role().id}>! Heads up! " \
                          f"Willie's passing an early message along:\n" \
                          f"\"{self.get_random_warm_up_phrase()}\""

        output_dict = {
            '420': str(willie_time_string),
            'warm up': str(warm_up_string)
        }

        return output_dict


def setup(bot: commands.Bot):
    bot.add_cog(WillieTimer(bot))
