import json
import socket
from Classes.Game.Player import Player


class GameManager:
    __players:dict
    __playingPlayer:Player
    __state:str
    __round:str

    def __init__(self, logger):
        self.__players = {}
        self.__playingPlayer = None
        self.__state = "waiting"
        self.__round = "none"
        self.logger = logger
        pass

    def getLogger(self):
        return self.logger

    # game round management
    # this section manages the flow of rounds this should inherit itself
    # =============================================================================
    
    # this function iterates all 
    def progressRound(self):
        # phases
        # - playerPrep => playing player switches, gets a mana point and gets verified
        if self.__playingPlayer != None:
            for player in self.__players:
                if self.__playingPlayer != player:
                    self.__playingPlayer = player
        else:
            self.__playingPlayer = next(iter(self.__players))
        # - playerDraw => player draws a card
        # - playerPlay => player can place cards and active effects
        # - playerEnd => player ends his turn and the code reiterates with the remaining player
        pass

    # game state management
    # this section mostly only used by the networking and event handling classes
    # other parts should never need to interface with this unless really required
    # =============================================================================
    def startGame(self, tcpSocket:socket):
        self.__state = "running"

        players = list(self.__serverWorld.getPlayers)

        print("game starts")
        self.logger.info("game manager is starting the game")
        for userAddr in self.__users.keys():
            try:
                user = self.__serverWorld.getPlayers[userAddr]["player"]
                user.addMana(1000)
                user.adjustHP(1000)
                user.shuffleDeck()
                cards = user.getDeck()
                user.setHand(cards[:5])

                enemy = players[0]["player"]

                if enemy == user:
                    enemy = players[1]["player"]
                
                payload = {
                    "event":"startgame",
                    "player": {
                        "mana":user.getMana(),
                        "hp": user.getHP(),
                        "hand": user.getHand()
                    },
                    "enemy": {
                        "id": enemy.getID(),
                        "name": enemy.getName(),
                        "hp": enemy.getHP(),
                    },
                }

                tcpSocket.send(json.dumps(payload).encode())
            except Exception as e:
                self.logger.error(f"failed to start game due to error: {e}")
                break
        # handles notifying all players that the game starts
        pass

    def stopGame(self):
        # handles notifying all players that the game stops
        # handles stoping the game itself and notifies server to stop itself
        pass

    # player management
    # the network manager will create a player instance
    # =============================================================

    # gets all player known to the game manager and returns them
    def getPlayers(self) -> dict:
        return self.__players

    # creates a player and handles counting all players and if conditions met starting the game
    # returns the new dict in which the new player now is added
    def addPlayers(self, player:Player, socket:socket, clientAddr) -> dict:
        
        self.logger.info(f"creating user with id: {player.getID}")
        self.__players[clientAddr] = {
            "player": player,
            "socket":socket
        }
        self.logger.info(f"new length of user dictionary: {len(self.__players)}")

        # counts participating players and starts the game if enough have joined
        if len(self.__players) == 2:
            self.logger.info("2 players have join game starts")
            self.startGame(socket)

        return self.__players
    
    def removePlayers(self, clientAddr):
        self.logger.info(f"removing player with address '{clientAddr}' from players database")
        del self.__players[clientAddr]