package uk.mgrove.ac.soton.comp1206.scene;

import javafx.application.Platform;
import javafx.beans.property.MapProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleMapProperty;
import javafx.collections.FXCollections;
import javafx.geometry.Pos;
import javafx.scene.control.Separator;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.scene.text.TextAlignment;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import uk.mgrove.ac.soton.comp1206.component.*;
import uk.mgrove.ac.soton.comp1206.game.MultiplayerGame;
import uk.mgrove.ac.soton.comp1206.ui.GameWindow;

/**
 * Class for multiplayer game scene
 */
public class MultiplayerScene extends ChallengeScene {

    /**
     * Logger
     */
    private static final Logger logger = LogManager.getLogger(MultiplayerScene.class);

    /**
     * Chat container
     */
    private Chat chat;

    /**
     * Live leaderboard
     */
    private Leaderboard leaderboard;

    /**
     * Other players' live boards
     */
    private final MapProperty<String, SimpleIntegerProperty[][]> playerBoards = new SimpleMapProperty<>(FXCollections.observableHashMap());

    /**
     * Grid of other players' live boards
     */
    private final GridPane playerBoardGrid = new GridPane();

    /**
     * Create a new multiplayer challenge scene
     *
     * @param gameWindow the Game Window
     */
    public MultiplayerScene(GameWindow gameWindow) {
        super(gameWindow);
    }

    /**
     * Set up the game object and model
     */
    @Override
    public void setupGame() {
        logger.info("Starting a new challenge");

        //Start new game
        game = new MultiplayerGame(5, 5, gameWindow.getCommunicator());
        game.setOnGameFail(() -> Platform.runLater(gameWindow::startMenu));

        game.setOnPlayerBoardAdded((username, gridProperties) -> {
            Platform.runLater(() -> {
                var newGameBoard = new GameBoard(gridProperties.length, gridProperties[0].length, 100, 100);
                newGameBoard.enableFocus(false);
                for (var x = 0; x < gridProperties.length; x++) {
                    for (var y = 0; y < gridProperties[0].length; y++) {
                        newGameBoard.getGridProperty(x,y).bindBidirectional(gridProperties[x][y]);
                    }
                }
                var leaderboardScores = game.leaderboardScoresProperty();

                var boardGridDimensions = (int) Math.sqrt(leaderboardScores.size());
                var playerIndex = -1;
                for (var player : leaderboardScores) {
                    playerIndex++;
                    if (player.getKey().equals(username)) break;
                }
                var rowIndex = playerIndex / boardGridDimensions;
                var columnIndex = playerIndex - rowIndex * boardGridDimensions;
                var newBoardTitle = new Text(username);
                newBoardTitle.setTextAlignment(TextAlignment.CENTER);
                newBoardTitle.getStyleClass().add("heading");
                logger.debug("Creating board for: {} at row index: {}, column index: {}", username, rowIndex, columnIndex);
                var newBoardContainer = new VBox(newBoardTitle, newGameBoard);
                newBoardContainer.setAlignment(Pos.CENTER);
                newBoardContainer.setSpacing(4);
                playerBoardGrid.add(newBoardContainer, 1, 1);
            });
        });

        gameWindow.getCommunicator().send("SCORES");
    }

    /**
     * Build the Multiplayer Challenge window
     */
    @Override
    public void build() {
        super.build();
        var leftMenu = new VBox();
        leftMenu.setSpacing(8);
        leftMenu.setMaxWidth(200);
        leftMenu.setPrefWidth(200);
        var viewOtherBoards = new Text("See others");
        viewOtherBoards.getStyleClass().add("channelItem");
        viewOtherBoards.setOnMouseClicked((event) -> {
            Platform.runLater(() -> {
                var returnButton = new Text("Back");
                returnButton.getStyleClass().add("channelItem");
                var playerBoardTitle = new Text("All Boards");
                playerBoardTitle.getStyleClass().add("title");
                playerBoardTitle.setTextAlignment(TextAlignment.CENTER);
                var playerBoardGridContainer = new VBox(returnButton, playerBoardTitle, playerBoardGrid);
                playerBoardGridContainer.setAlignment(Pos.CENTER);
                playerBoardGridContainer.setFillWidth(true);
                playerBoardGridContainer.setPrefHeight(Double.MAX_VALUE);
                playerBoardGridContainer.setSpacing(12);
                playerBoardGridContainer.getStyleClass().add("overlay");
                returnButton.setOnMouseClicked((returnEvent) -> Platform.runLater(() -> challengePane.getChildren().remove(playerBoardGridContainer)));
                playerBoardGrid.setAlignment(Pos.CENTER);
                challengePane.getChildren().add(playerBoardGridContainer);
            });
        });
        chat = new Chat(gameWindow.getCommunicator(), true);
        chat.setChatFocusTraversable(false);
        leaderboard = new Leaderboard("Leaderboard");
        var chatTitle = new Text("Chat");
        chatTitle.getStyleClass().add("heading");
        leftMenu.getChildren().addAll(viewOtherBoards, leaderboard, new Separator(), chatTitle, chat);
        mainPane.setLeft(leftMenu);
        leaderboard.bindLeaderboardScores(game.leaderboardScoresProperty());
        mainPane.requestFocus();
    }

}
