import datetime
import discord
import asyncio
from funcs import logThis
from enum import Enum

minimumPlayers = 1
minimumPlayersWithAI = 5

class Team(Enum):
    Villager = 1
    Werewolf = 2

class Role():
    def __init__(self,team,isWerewolf=False,isSeer=False,isSorcerer=False):
        self.alive = True
        self.team = team
        self.isWerewolf = isWerewolf
        self.isSeer = isSeer
        self.isSorcerer = isSorcerer

class VillagerRole(Role):
    def __init__(self):
        super().__init__(Team.Villager)

class WerewolfRole(Role):
    def __init__(self):
        super.__init__(Team.Werewolf,isWerewolf=True)

class SeerRole(Role):
    def __init__(self):
        super.__init__(Team.Villager,isSeer=True)

class SorcererRole(Role):
    def __init__(self):
        super.__init__(Team.Werewolf,isSorcerer=True)

class SorcererWerewolfRole(Role):
    def __init__(self):
        super.__init__(Team.Werewolf,isWerewolf=True,isSorcerer=True)

class Werewolf():
    def __init__(self,bot):
        self.bot = bot

    # Starts a game of werewolf
    def werewolfStart(self,channel:str):
        game = self.bot.database["werewolf games"].find_one({"_id":channel})

        logThis("Trying to start a werewolf game in "+channel)

        if game == None:

            gameID = datetime.datetime.now().strftime('%Y%m%d%H%M%S')

            newGame = {"_id":channel,"users": {},"round":0,"turn":0,"turnOrder":[],"current message":None,"gameID":gameID}

            self.bot.database["werewolf games"].insert_one(newGame)

            return "Started a game of werewolf. Use \"!werewolf join\" to join the game", True
        else:
            logThis("There is already a werewolf game going on in "+channel)
            return "There's already a werewolf game going on in this channel. Try again in a few minutes.", False

    # Stops the game of werewolf
    def werewolfStop(self,channel:str):
        game = self.bot.database["werewolf games"].find_one({"_id":channel})

        if game != None:
            self.bot.database["werewolf games"].delete_one({"_id":channel})
            return "Ended the werewolf game"
        else:
            return "There's no game going on right now"

    def allotRoles(self,channel):
        game = self.bot.database["werewolf games"].find_one({"_id":channel})
        players = len(game["users"])

    async def werewolfLoop(self,ctx,round):
        logThis(f"Starting loop {round} of Werewolf game")
        channel = "#"+str(ctx.channel.id)
        if round == 0:
            await asyncio.sleep(90)

            game = self.bot.database["werewolf games"].find_one({"_id":channel})
            if len(game["users"].keys()) >= minimumPlayers:
                while len(game["users"].keys()) < minimumPlayersWithAI:
                    user = {"role": None}
                    self.bot.database["werewolf games"].update_one({"_id":"#"+str(ctx.channel.id)},
                    {"$set":{"users."+self.bot.generator.nameGen()[:-1]+" (AI player)":user}})
                    game = self.bot.database["werewolf games"].find_one({"_id":channel})

                if game["current message"] != None:
                    await ctx.channel.fetch_message(game["current message"]).delete()
                users = ""
                for x, user in enumerate(list(game["users"].keys())):
                    users += str(x+1)+") "+self.bot.funcs.getName(user)+"\n"

                em = discord.Embed(title="Game started with the following players:",description=users,colour=0x00FF00)
                oldMessage = await ctx.send(embed=em)

                self.bot.database["werewolf games"].update_one({"_id":channel},{"$set":{"current message":oldMessage.id}})

                self.allotRoles(channel)

                self.bot.database["werewolf games"].update_one({"_id":channel},{"$inc":{"round":1}})
                await self.werewolfLoop(ctx,round+1)
            else:
                ctx.send("Not enough players. Ending game.")
                self.werewolfStop("#"+str(ctx.channel.id))
        else:
            await asyncio.sleep(30)


    async def werewolfJoin(self,ctx):
        currentGames = list(self.bot.database["werewolf games"].find({}))
        for game in currentGames:
            if "#"+str(ctx.message.author.id) in game["users"].keys():
                return f"{ctx.message.author.display_name} is already in a werewolf game", False

        game = self.bot.database["werewolf games"].find_one({"_id":"#"+str(ctx.channel.id)})
        if game["round"] == 0:
            user = {"role": None}
            self.bot.database["werewolf games"].update_one({"_id":"#"+str(ctx.channel.id)},
                {"$set":{"users."+"#"+str(ctx.message.author.id):user}})
            return "You joined the werewolf game", True
        else:
            return "It's too late to join", False

    async def parseWerewolf(self,ctx,content):
        if content == "start":
            response, started = self.werewolfStart("#"+str(ctx.channel.id))
            await ctx.send(response)
            if started:
                await self.werewolfLoop(ctx,0)

        elif content == "stop":
            await ctx.send(self.werewolfStop("#"+str(ctx.channel.id)))

        elif content == "join":
            response, joined = await self.werewolfJoin(ctx)
            await ctx.send(response)
            if joined:
                game = self.bot.database["werewolf games"].find_one({"_id":"#"+str(ctx.channel.id)})
                if game["current message"] != None:
                    await ctx.channel.fetch_message(game["current message"]).delete()
                users = ""
                for x, user in enumerate(list(game["users"].keys())):
                    users += str(x+1)+") "+self.bot.funcs.getName(user)+"\n"

                if len(list(game["users"].keys())) < minimumPlayers:
                    users += f"You need at least {minimumPlayers} players to play werewolf."
                em = discord.Embed(title="Current Players",description=users,colour=0x00FF00)
                oldMessage = await ctx.send(embed=em)
                self.bot.database["werewolf games"].update_one({"_id":"#"+str(ctx.channel.id)},{"$set":{"current message":oldMessage.id}})
