@startuml
interface IServerMiddleware {
  ' Methods
  + refreshClient (Player player): void
  + refreshAllClients (GamePublic gamePublic): void
  + refreshGameState (GameState gameState): void
  + broadCastLeaderBoard(Map<PlayerDTO, int> leaderboard): void
  - message(String command, String [] args)
  - message(String command)

}
note left of ServerMiddleware
  Transform client WebSocket
  calls to Java methods
end note

class ServerMiddleware implements IServerMiddleware {
  ' Variables
  - clients: Map<String, ClientMiddleware>
  - server: GameServer
}

interface IGameServer {
  ' Methods
  + joinGame (String userId, String userName): boolean
  + leaveGame (String userId): void
  + startGame (): boolean
  + getGameState (): GameState
  ' Return if action valid
  + playCard(String playerId, Card card, Action action): boolean
  ' Resources have to be bought from neighbors (PlayerID, Resource, Quantity)
  + playCard(String playerId, Card card, Action action, List<Triplet<String, Resource, int>> buyFromNeighbors): boolean

}
note right of GameServer::getRoomState
  Get the state of the game Room
end note

class GameServer implements IGameServer{
  ' Variables
  - game: IGameManager
  - serverMiddleware: ServerMiddleware
  ' All the cards available for the game
  - allCards: List<Card card>
}

class GameDTO {
  - currentAge: Age
  - gameTurn: int
  - currentAgeCards: List<Card>
  - gameState: GameState
  - playersPublic: List<PlayerDTO>
  - server: IGameServer
}

interface IGameManager {
'Create a Player instance and add it to players
  + addPlayer(String userId, String userName)
  '
  ' Initialize and start the game (UseCase preparation)
  + startGame(): void
  '
  ' End the game 
  + endGame(): void
  '
  ' Get the current game with private informations hiden
  + getGamePublic(): GameDTO
  '
  ' Set card as currentCard and remove card from handCards
  + playCard(String playerId, Card card, Action action): void
  '
  'Get the player with playerId
  + getPlayer(String playerId): Player

  ' Buy raw material from a player (neighbor)
  - buyRessourceFrom(String buyerId, String sellerId, Resource resource): void
  '
  ' Start the age to set the cards pool
  - startAge(Age age): void
  '
  ' Fill every Player::handCards with default cards from currentAgeCards
  - distributeCards(): void
  '
  ' Get the 2 neighbors of the player
  - getNeighbors(Player p) : Pair<Player, Player>
  '
  ' Give Player::handCards to player neighbor 
  - nextTurn(): void
  '
  ' Give Player::handCards to player neighbor 
  - giveNeighbor(List<Card>): void
  '
  ' At the end of Age, compare the army of the 2 neighbors of the player and attribute victory points accordingly
  - fight(Player p): void
  '
  ' Get the leaderboard of the game
  - getLeaderboard(): Map<Player, int>
}
class GameManager implements IGameManager {
  - game: GameDTO
  - players: Player[*]
}
GameManager -- GameDTO

class PlayerDTO {
  - userId: String
  - userName: String
  '
  - wonder: Wonder
  '
  - victoryPoints: int 
  - defeatPoints: int
  - conlictPoints: int
  - money: int
  '
  ' Possessed resources
  - resources: Map<Resource, int>
  ' Built cards
  - builtCards: List<Card>
}
class Player {
  - player: PlayerDTO
  ' Available cards to choose in
  - handCards: List<Card>

  ' Methods
  ' Get the current player with private information hiden
  + getPlayerDTO(): PlayerDTO
  ' Change Wonder stage if enough resources
  + upgradeWonder(): boolean
  ' Calculate the sum of victory points at the end
  + calculateVictoryPoints(): int
}
Player -- PlayerDTO

interface IWonder {
  ' Change Wonder stage
  + upgradeWonder(): void
  ' Calculate the sum of victory points at the end
  + calculateVictoryPoints(): int
}

class Wonder implements IWonder {
  - priceStage1: Pair<Resource, int> 
  - priceStage2: Pair<Resource, int> 
  - priceStage3: Pair<Resource, int> 
  - stage2Effect: Pair<Effect, int>
  - victoryPointStage1: int 
  - victoryPointStage2: int 
  - victoryPointStage3: int 
  - currentStage: int 
  - defaultResource: Resource
}

enum WonderEffect {
  ADD_SHIELDS
  ADD_RAW_MATERIAL
  ADD_GOLD
  ' Add a science symbol chosen by the player at the end of the game
  ADD_SCIENCE_SYMBOL
  ' Build 1 building free
  BUILD_FREE
  ' Choose one card from the discard and build it for free
  CHOOSE_CARD_FROM_DISCARD_THEN_BUILD_FREE  
  ADD_VICTORY_POINTS
}

enum Age {
  AGE1
  AGE2
  AGE3
}

enum Action {
  USE_CARD
  UPGRADE_WONDER
  DISCARD
}

enum gameState {
  WAITING
  STARTED
  FULL
}

' Card enums
enum Resource  {
  '  Matières premières
  CLAY
  STONE
  WOOD
  ORE
  '  Produits manufacturés
  CLOTH
  GLASS
  PAPYRUS
}

interface ICard


ServerMiddleware -up- IGameServer
PlayerDTO -left- IWonder
PlayerDTO -right- ICard
GameDTO -- ICard
GameDTO -- PlayerDTO
IGameManager -- GameServer
GameManager -- Player
@enduml