export class TicTacToe {

    gamestate_variable = 'gamestate';
    layer_moves = 'moves';
    layer_overlay = 'overlay';
    layer_game = 'game';
    layer_blue = 'blue';
    layer_green = 'green';
    layer_board = 'board';
    layer_exit = 'exit';
    popup = 'popup';
    board_x = 4;
    board_y = 3;
    blue_x = 3;
    blue_y = 2;
    green_x = 3;
    green_y = 6;

    gamestate = {};
    is_player = false;
    on_board = false;
    on_game = false;
    welcome = false;
    move_message;
    color;
    game_message;

    constructor(config) {
        this.gamestate_variable = config.gamestate_variable || 'gamestate';
        this.layer_moves = config.layer_moves || 'moves';
        this.layer_overlay = config.layer_overlay || 'overlay';
        this.layer_game = config.layer_game || 'game';
        this.layer_blue = config.layer_blue || 'blue';
        this.layer_green = config.layer_green || 'green';
        this.layer_board = config.layer_board || 'board';
        this.layer_exit = config.layer_exit || 'exit';
        this.popup = config.popup || 'popup';
        this.board_x = config.board_x || 4;
        this.board_y = config.board_y || 3;
        this.blue_x = config.blue_x || 3;
        this.blue_y = config.blue_y || 2;
        this.green_x = config.green_x || 3;
        this.green_y = config.green_y || 6;

        WA.onInit().then(() => {
            this.waInit();
        });
    }


    applyGameState = function () {
        this.is_player = false;
        this.color = '';
        if (this.gamestate.blue) {
            if (this.gamestate.blue == WA.player.id) {
                this.color = 'blue';
                this.is_player = true;
            }
            WA.room.setTiles([
                { x: this.blue_x, y: this.blue_y, tile: null, layer: this.layer_blue }
            ]);
        } else {
            WA.room.setTiles([
                { x: this.blue_x, y: this.blue_y, tile: 'blue', layer: this.layer_blue }
            ]);
        }

        if (this.gamestate.green) {
            if (this.gamestate.green == WA.player.id) {
                this.color = 'green';
                this.is_player = true;
            }
            WA.room.setTiles([
                { x: this.green_x, y: this.green_y, tile: null, layer: this.layer_green }
            ]);
        } else {
            WA.room.setTiles([
                { x: this.green_x, y: this.green_y, tile: 'green', layer: this.layer_green }
            ]);
        }

        for (let x = 0; x < 3; x++) {
            for (let y = 0; y < 3; y++) {
                let index = x + y * 3;
                if (this.gamestate.board && this.gamestate.board[index]) {
                    if (this.gamestate.board[index] == 'blue' || this.gamestate.board[index] == 'green') {
                        WA.room.setTiles([
                            { x: this.board_x + x, y: this.board_y + y, tile: this.gamestate.board[index], layer: this.layer_moves }
                        ]);
                    }
                } else {
                    WA.room.setTiles([
                        { x: this.board_x + x, y: this.board_y + y, tile: null, layer: this.layer_moves }
                    ]);
                }
            }
        }

        if (this.gamestate.win) {
            let win_text = this.gamestate.win_name + ' wins!';

            if (this.is_player) {
                if (this.gamestate.win_player == WA.player.id) {
                    win_text = 'You win!'
                } else {
                    win_text = 'You loose! ' + win_text;
                }
                this.newGame();
            }

            this.game_message = WA.ui.openPopup(this.popup, win_text, [{
                label: 'New Game',
                className: '',
                callback: (popup) => {
                    popup.close();
                }
            }]);
        } else if (this.gamestate.deuce) {
            if (this.is_player) {
                this.newGame();
            }
            this.game_message = WA.ui.openPopup(this.popup, 'Deuce!', [{
                label: 'New Game',
                className: '',
                callback: (popup) => {
                    popup.close();
                }
            }]);
        }
    }

    newGame = function () {
        this.gamestate = {};
        WA.state.saveVariable(this.gamestate_variable, this.gamestate);
    }

    waInit = function () {
        this.gamestate = WA.state.loadVariable(this.gamestate_variable) || {};
        this.applyGameState();

        WA.state.onVariableChange(this.gamestate_variable).subscribe((value) => {
            console.log("gamestate", value);
            this.gamestate = value || {};
            this.applyGameState();
        });

        WA.room.onEnterLayer(this.layer_game).subscribe(() => {
            this.on_game = true;
            if (!this.welcome && !this.is_player && (!this.gamestate.blue || !this.gamestate.green)) {
                this.welcome = true;
                let pickText = 'Pick a color to start game.';

                if (this.gamestate.blue) {
                    pickText = 'Pick green to join game.';
                } else if (this.gamestate.green) {
                    pickText = 'Pick blue to join game.';
                }

                this.game_message = WA.ui.openPopup(this.popup, pickText, [{
                    label: 'Ok',
                    className: '',
                    callback: (popup) => {
                        popup.close();
                        this.game_message = null;
                    }
                }]);
            }
        });


        WA.room.onLeaveLayer(this.layer_game).subscribe(() => {
            if (this.game_message) {
                this.game_message.close();
                this.game_message = null;
            }
        })

        WA.room.onEnterLayer(this.layer_exit).subscribe(() => {
            if (this.is_player && this.on_game) {
                this.newGame();
            }
            this.welcome = false;
        });

        WA.room.onEnterLayer(this.layer_blue).subscribe(() => {
            if (!this.gamestate.green || this.gamestate.green != WA.player.id) {
                this.gamestate.blue = WA.player.id;
                if (this.game_message) {
                    this.game_message.close();
                    this.game_message = null;
                }
                if (this.gamestate.green) {
                    this.gamestate.current = this.gamestate.green;
                }
                WA.state.saveVariable(this.gamestate_variable, this.gamestate);
            }
        });

        WA.room.onEnterLayer(this.layer_green).subscribe(() => {
            if (!this.gamestate.blue || this.gamestate.blue != WA.player.id) {
                this.gamestate.green = WA.player.id;
                if (this.game_message) {
                    this.game_message.close();
                    this.game_message = null;
                }
                if (this.gamestate.blue) {
                    this.gamestate.current = this.gamestate.blue;
                }
                WA.state.saveVariable(this.gamestate_variable, this.gamestate);
            }
        });


        WA.room.onEnterLayer(this.layer_board).subscribe(() => {
            this.on_board = true;
        });

        WA.room.onLeaveLayer(this.layer_board).subscribe(() => {
            this.on_board = false;
        });

        WA.player.onPlayerMove((event) => {
            if (this.on_board && WA.player.id) {
                for (let x = 0; x < 3; x++) {
                    for (let y = 0; y < 3; y++) {
                        WA.room.setTiles([
                            { x: this.board_x + x, y: this.board_y + y, tile: null, layer: this.layer_overlay }
                        ]);
                    }
                }

                if (!event.moving && this.on_board && this.gamestate.current == WA.player.id && !this.gamestate.win) {
                    const x = Math.ceil(event.x / 32) - this.board_x - 1;
                    const y = Math.ceil(event.y / 32) - this.board_y - 1;
                    const index = x + y * 3;
                    if (!this.gamestate.board) {
                        this.gamestate.board = [];
                    }
                    if (index >= 0 && index < 9 && !this.gamestate.board[index]) {
                        if (this.move_message) {
                            this.move_message.remove();
                        }

                        WA.room.setTiles([
                            { x: this.board_x + (index % 3), y: this.board_y + Math.floor(index / 3), tile: this.color + '_overlay', layer: this.layer_overlay }
                        ]);


                        this.move_message = WA.ui.displayActionMessage({
                            message: 'Press SPACE or touch here to place move',
                            callback: () => {
                                this.gamestate.board[index] = this.color;
                                if (this.color == 'blue') {
                                    this.gamestate.current = this.gamestate.green;
                                } else if (this.color == 'green') {
                                    this.gamestate.current = this.gamestate.blue;
                                }

                                var wins = [[0, 1, 2], [3, 4, 5], [6, 7, 8], [0, 3, 6], [1, 4, 7], [2, 5, 8], [0, 4, 8], [2, 4, 6]]

                                let win_move = false;
                                for (var i = 0; i < wins.length; i++) {
                                    let win = wins[i];
                                    let matches = 0;
                                    for (var j = 0; j < win.length; j++) {
                                        if (this.gamestate.board[win[j]] === this.color) {
                                            matches++
                                        }
                                    }
                                    if (matches == 3) {
                                        win_move = true;
                                        break;
                                    }
                                }

                                if (win_move) {
                                    this.gamestate.win = true;
                                    this.gamestate.win_player = WA.player.id;
                                    this.gamestate.win_name = WA.player.name;
                                    this.gamestate.win_color = this.color;
                                }

                                if (!this.gamestate.win) {
                                    let moves = 0;
                                    for (let i = 0; i < 9; i++) {
                                        if (this.gamestate.board[i]) {
                                            moves++;
                                        }
                                    }

                                    if (moves == 9) {
                                        this.gamestate.deuce = true;
                                    }
                                }

                                WA.state.saveVariable(this.gamestate_variable, this.gamestate);
                            }
                        });
                    }
                } else if (this.move_message) {
                    this.move_message.remove();
                }
            }
        });
    }

}