//
//  GameVM.swift
//  DouShouQiIOS
//
//  Created by Pierre FERREIRA on 12/06/2024.
//

import Foundation
import DouShouQiModel
import SpriteKit
import SwiftUI
// Gestion de la boucle de jeu par la création d'une tache async<
// On s'abonne aux événements, notament game.addPlayerNotifiedListeneren.
// Les joueurs n'ont besoin que de nom


class GameVM : ObservableObject, Identifiable {
    
    ///Players
    let player1 : Player
    let player2 : Player
    
    var pieces : [ Owner : [Animal : SpriteMeeple]]
    let actualRules : Rules
    
    ///Error
    @Published var hasError : Bool = false
    
    //Message
    @Published var displayMessage : String = ""
    
    public init(withRules rules : Rules = ClassicRules(), andPlayer1 p1: Player, andPlayer2 p2 : Player?) {
        self.player1 = p1
        
        if let p2 {
            self.player2 = p2
        }
        else {
            self.player2 = RandomPlayer(withName: "Bobot", andId: .player2)!
        }
        
        self.actualRules = rules
        self.pieces =
        [ .player1 : [
            .rat : SpriteMeeple(imageName: "RatMeeple", size: CGSize(width: 120, height: 120), color: Color.player1),
                .cat : SpriteMeeple(imageName: "CatMeeple", size: CGSize(width: 120, height: 120), color: Color.player1),
                .dog : SpriteMeeple(imageName: "DogoMeeple", size: CGSize(width: 120, height: 120), color: Color.player1),
                .wolf : SpriteMeeple(imageName: "WolfMeeple", size: CGSize(width: 120, height: 120), color: Color.player1),
                .leopard : SpriteMeeple(imageName: "LeoMeeple", size: CGSize(width: 120, height: 120), color: Color.player1),
                .tiger : SpriteMeeple(imageName: "CatMeeple", size: CGSize(width: 120, height: 120), color: Color.player1),
                .lion : SpriteMeeple(imageName: "LionMeeple", size: CGSize(width: 120, height: 120), color: Color.player1),
                .elephant : SpriteMeeple(imageName: "ElphMeeple", size: CGSize(width: 120, height: 120), color: Color.player1),
            ],
          
          .player2: [
            .rat : SpriteMeeple(imageName: "RatMeeple", size: CGSize(width: 120, height: 120), color: Color.player2),
                .cat : SpriteMeeple(imageName: "CatMeeple", size: CGSize(width: 120, height: 120), color: Color.player2),
                .dog : SpriteMeeple(imageName: "DogoMeeple", size: CGSize(width: 120, height: 120), color: Color.player2),
                .wolf : SpriteMeeple(imageName: "WolfMeeple", size: CGSize(width: 120, height: 120), color: Color.player2),
                .leopard : SpriteMeeple(imageName: "LeoMeeple", size: CGSize(width: 120, height: 120), color: Color.player2),
                .tiger : SpriteMeeple(imageName: "CatMeeple", size: CGSize(width: 120, height: 120), color: Color.player2),
                .lion : SpriteMeeple(imageName: "LionMeeple", size: CGSize(width: 120, height: 120), color: Color.player2),
                .elephant : SpriteMeeple(imageName: "ElphMeeple", size: CGSize(width: 120, height: 120), color: Color.player2),
            ]
        ]

    }
    
    
    func readInt(withMessage message: String) -> Int {
        var temp: Int?
        while temp == nil {
            print(message)
            let result = readLine()
            temp = Int(result ?? "")
        }
        return temp!
    }
    
    func readMove(from player: HumanPlayer) -> Move? {
        var originRow, originCol, destRow, destCol : Int?
        
        originRow = readInt(withMessage: "\(player.name) please enter the origin row in which your piece is)")
        originCol = readInt(withMessage: "\(player.name) please enter the origin column in which your piece is)")
        destRow = readInt(withMessage: "\(player.name) please enter the destination row in which you want to move your piece)")
        destCol = readInt(withMessage: "\(player.name) please enter the destination column in which you want to move your piece)")
        
        return Move(of: player.id, fromRow: originRow!, andFromColumn: originCol!, toRow: destRow!, andToColumn: destCol!)
    }


    
    func startGame() async throws -> Int
    {
//        if (player1 == nil || player2 == nil){
//            //Affichage de l'erreur
//            return 1
//        }
        
        var game: Game = try Game(withRules: actualRules, andPlayer1: player1, andPlayer2: player2)

        for player in game.players {
            if player.value is HumanPlayer {
                let hp = player.value as! HumanPlayer
                hp.changeInput(input: readMove)
            }
        }
        
        game.addGameStartedListener {_ in
            self.displayMessage = "🎉 GAME STARTS! 🎉"
        }
        
        game.addPlayerNotifiedListener({ board, player in
            
            self.displayMessage = "Player \(player.id == .player1 ? "🟡 1" : "🔴 2") - \(player.name), it's your turn!"
            //try! await Persistance.saveGame(withName: "game", andGame: game2)
            
            _ = readLine()
            
            if player is HumanPlayer {
                var move = self.readMove(from: player as! HumanPlayer)
                try! await (player as! HumanPlayer).chooseMove(move)
            } else {
                _ = try! await player.chooseMove(in: board, with: game.rules)
            }
        })

        return 0
    }
}
