"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GameRoom = void 0;
const chance_1 = __importDefault(require("chance"));
const colyseus_1 = require("colyseus");
const Config_1 = require("./Config");
const GameSchema_1 = require("./GameSchema");
class Player {
}
class GameRoom extends colyseus_1.Room {
    onCreate(options) {
        console.log(`${this.constructor.name} created!`);
        this.chance = chance_1.default();
        const state = new GameSchema_1.GameSchema();
        this.buildMap(state);
        this.setState(state);
        this.setPatchRate(10);
        this.players = new Array();
        this.playersByID = new Map();
        this.onMessage('closeDoor', this.onCloseDoorMessage.bind(this));
        this.onMessage('openDoor', this.onOpenDoorMessage.bind(this));
        this.onMessage('moveSpy', this.onMoveSpyMessage.bind(this));
    }
    onJoin(client, options) {
        console.log(`Client ${client.sessionId} joined ${this.constructor.name}.`);
        const player = new Player();
        player.client = client;
        this.players.push(player);
        this.playersByID.set(client.sessionId, player);
        if (this.players.length == 1) {
            player.role = 'spy';
            player.client.send('role', player.role);
        }
        else {
            player.role = 'guard';
            player.client.send('role', player.role);
            this.state.whosTurn = 'spy';
            this.lock();
            this.broadcast('ready');
        }
    }
    onLeave(client, consented) {
        console.log(`Client ${client.sessionId} left ${this.constructor.name}.`);
        for (let i = 0; i < this.players.length; ++i) {
            if (this.players[i].client.sessionId == client.sessionId) {
                this.players.splice(i, 1);
                break;
            }
        }
        this.playersByID.delete(client.sessionId);
    }
    buildMap(state) {
        state.facilitySize = Config_1.Config.FACILITY_SIZE;
        const door0 = new GameSchema_1.DoorSchema();
        door0.connectsRooms = [0, 1];
        state.doors.push(door0);
        door0.index = state.doors.length - 1;
        const door1 = new GameSchema_1.DoorSchema();
        door1.connectsRooms = [1, 2];
        state.doors.push(door1);
        door1.index = state.doors.length - 1;
        const door2 = new GameSchema_1.DoorSchema();
        door2.connectsRooms = [0, 3];
        state.doors.push(door2);
        door2.index = state.doors.length - 1;
        const door3 = new GameSchema_1.DoorSchema();
        door3.connectsRooms = [1, 4];
        state.doors.push(door3);
        door3.index = state.doors.length - 1;
        const door4 = new GameSchema_1.DoorSchema();
        door4.connectsRooms = [2, 5];
        state.doors.push(door4);
        door4.index = state.doors.length - 1;
        const door5 = new GameSchema_1.DoorSchema();
        door5.connectsRooms = [3, 4];
        state.doors.push(door5);
        door5.index = state.doors.length - 1;
        const door6 = new GameSchema_1.DoorSchema();
        door6.connectsRooms = [4, 5];
        state.doors.push(door6);
        door6.index = state.doors.length - 1;
        const door7 = new GameSchema_1.DoorSchema();
        door7.connectsRooms = [3, 6];
        state.doors.push(door7);
        door7.index = state.doors.length - 1;
        const door8 = new GameSchema_1.DoorSchema();
        door8.connectsRooms = [4, 7];
        state.doors.push(door8);
        door8.index = state.doors.length - 1;
        const door9 = new GameSchema_1.DoorSchema();
        door9.connectsRooms = [5, 8];
        state.doors.push(door9);
        door9.index = state.doors.length - 1;
        const door10 = new GameSchema_1.DoorSchema();
        door10.connectsRooms = [6, 7];
        state.doors.push(door10);
        door10.index = state.doors.length - 1;
        const door11 = new GameSchema_1.DoorSchema();
        door11.connectsRooms = [7, 8];
        state.doors.push(door11);
        door11.index = state.doors.length - 1;
        const room0 = new GameSchema_1.RoomSchema();
        room0.roomNumber = 0;
        room0.doors.set('right', door0);
        room0.doors.set('bottom', door2);
        state.rooms.push(room0);
        const room1 = new GameSchema_1.RoomSchema();
        room1.roomNumber = 1;
        room1.doors.set('left', door0);
        room1.doors.set('right', door1);
        room1.doors.set('bottom', door3);
        state.rooms.push(room1);
        const room2 = new GameSchema_1.RoomSchema();
        room2.roomNumber = 2;
        room2.doors.set('left', door1);
        room2.doors.set('bottom', door4);
        state.rooms.push(room2);
        const room3 = new GameSchema_1.RoomSchema();
        room3.roomNumber = 3;
        room3.doors.set('top', door2);
        room3.doors.set('right', door5);
        room3.doors.set('bottom', door7);
        state.rooms.push(room3);
        const room4 = new GameSchema_1.RoomSchema();
        room4.roomNumber = 4;
        room4.doors.set('left', door5);
        room4.doors.set('top', door3);
        room4.doors.set('right', door6);
        room4.doors.set('bottom', door8);
        state.rooms.push(room4);
        const room5 = new GameSchema_1.RoomSchema();
        room5.roomNumber = 5;
        room5.doors.set('left', door6);
        room5.doors.set('top', door4);
        room5.doors.set('bottom', door9);
        state.rooms.push(room5);
        const room6 = new GameSchema_1.RoomSchema();
        room6.roomNumber = 6;
        room6.doors.set('top', door7);
        room6.doors.set('right', door10);
        state.rooms.push(room6);
        const room7 = new GameSchema_1.RoomSchema();
        room7.roomNumber = 7;
        room7.doors.set('left', door10);
        room7.doors.set('top', door8);
        room7.doors.set('right', door11);
        state.rooms.push(room7);
        const room8 = new GameSchema_1.RoomSchema();
        room8.roomNumber = 8;
        room8.doors.set('left', door11);
        room8.doors.set('top', door9);
        state.rooms.push(room8);
        state.vaccineRoomNumber = this.chance.natural({ 'max': 8 });
        state.spyRoomNumber = -1;
        while (state.spyRoomNumber == -1) {
            const roomNum = this.chance.natural({ 'max': 8 });
            const room = state.rooms[roomNum];
            let vaccineInAdjacentRoom = false;
            room.doors.forEach((door, key) => {
                door.connectsRooms.forEach((roomNumber) => {
                    if (roomNumber == state.vaccineRoomNumber) {
                        vaccineInAdjacentRoom = true;
                        return;
                    }
                });
                if (vaccineInAdjacentRoom)
                    return;
            });
            if (!vaccineInAdjacentRoom) {
                state.spyRoomNumber = roomNum;
            }
        }
        state.spySpawnRoomNumber = state.spyRoomNumber;
    }
    onAnyGuardTurn() {
        this.state.doors.forEach((door) => {
            --door.lockedForTurns;
            if (door.lockedForTurns < 0)
                door.lockedForTurns = 0;
        });
    }
    onCloseDoorMessage(client, doorIndex) {
        const state = this.state;
        const player = this.playersByID.get(client.sessionId);
        if (player.role != 'guard' || state.whosTurn != 'guard')
            return;
        if (doorIndex < 0 || doorIndex > state.doors.length - 1)
            return;
        this.onAnyGuardTurn();
        const door = state.doors[doorIndex];
        if (!door.isOpened || door.lockedForTurns > 0)
            return;
        door.isOpened = false;
        // checking whether spy is locked in room
        const room = state.rooms[state.spyRoomNumber];
        let hasOpenedDoor = false;
        room.doors.forEach((door, dir) => {
            if (door.isOpened) {
                hasOpenedDoor = true;
                return true;
            }
        });
        if (!hasOpenedDoor) {
            this.broadcast('winner', 'guard');
            this.disconnect();
        }
        state.whosTurn = 'spy';
    }
    onOpenDoorMessage(client, doorIndex) {
        const player = this.playersByID.get(client.sessionId);
        if (player.role != 'spy' || this.state.whosTurn != 'spy')
            return;
        if (doorIndex < 0 || doorIndex > this.state.doors.length - 1)
            return;
        const door = this.state.doors[doorIndex];
        if (door.isOpened)
            return;
        door.isOpened = true;
        door.lockedForTurns = Config_1.Config.LOCK_OPENED_DOOR_FOR_TURNS;
        this.state.whosTurn = 'guard';
    }
    onMoveSpyMessage(client, dir) {
        const state = this.state;
        const player = this.playersByID.get(client.sessionId);
        if (player.role != 'spy' || state.whosTurn != 'spy')
            return;
        const currentSpyRoom = state.rooms[state.spyRoomNumber];
        if (currentSpyRoom.doors.has(dir)) {
            const door = currentSpyRoom.doors.get(dir);
            if (door.isOpened) {
                door.connectsRooms.some((roomNumber) => {
                    if (roomNumber != state.spyRoomNumber) {
                        state.spyRoomNumber = roomNumber;
                        this.state.whosTurn = 'guard';
                        if (!state.vaccineIsStolen && state.spyRoomNumber == state.vaccineRoomNumber) {
                            state.vaccineIsStolen = true;
                        }
                        else if (state.vaccineIsStolen && state.spyRoomNumber == state.spySpawnRoomNumber) {
                            this.broadcast('winner', 'spy');
                            this.disconnect();
                        }
                        return true;
                    }
                });
            }
        }
        state.whosTurn = 'guard';
    }
}
exports.GameRoom = GameRoom;
//# sourceMappingURL=GameRoom.js.map