"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Spectator = void 0;
const game_action_1 = require("./game-action");
const MAX_SAMPLES = 1;
class Spectator {
    constructor(enabled) {
        this.enabled = enabled;
        this.actionsForCurrentBattle = [];
        this.wonBattles = [];
        this.tiedBattles = [];
        this.lostBattles = [];
    }
    prune() {
        this.wonBattles = this.wonBattles.slice(0, MAX_SAMPLES);
        this.lostBattles = this.lostBattles.slice(0, MAX_SAMPLES);
        this.tiedBattles = this.tiedBattles.slice(0, MAX_SAMPLES);
    }
    buildOutcomeSamples(gameState) {
        var _a, _b, _c;
        if (!this.enabled) {
            return {
                won: [],
                lost: [],
                tied: [],
            };
        }
        return {
            won: (_a = this.wonBattles) === null || _a === void 0 ? void 0 : _a.map((battle) => this.cleanUpActions(battle, gameState)),
            lost: (_b = this.lostBattles) === null || _b === void 0 ? void 0 : _b.map((battle) => this.cleanUpActions(battle, gameState)),
            tied: (_c = this.tiedBattles) === null || _c === void 0 ? void 0 : _c.map((battle) => this.cleanUpActions(battle, gameState)),
        };
    }
    cleanUpActions(battle, gameState) {
        const collapsed = this.collapseActions(battle.actions);
        const result = {
            ...battle,
            actions: collapsed,
            anomalies: gameState.anomalies,
        };
        return result;
    }
    commitBattleResult(result) {
        if (!this.enabled) {
            this.actionsForCurrentBattle = [];
            return;
        }
        if (this.wonBattles.length >= MAX_SAMPLES &&
            this.lostBattles.length >= MAX_SAMPLES &&
            this.tiedBattles.length >= MAX_SAMPLES) {
            this.actionsForCurrentBattle = [];
            return;
        }
        const actionsForBattle = this.actionsForCurrentBattle;
        this.actionsForCurrentBattle = [];
        const battle = {
            actions: actionsForBattle,
            anomalies: [],
        };
        switch (result) {
            case 'won':
                this.wonBattles.push(battle);
                break;
            case 'lost':
                this.lostBattles.push(battle);
                break;
            case 'tied':
                this.tiedBattles.push(battle);
                break;
        }
    }
    registerAttack(attackingEntity, defendingEntity, attackingBoard, defendingBoard, attackingBoardHero, defendingBoardHero) {
        if (!this.enabled) {
            return;
        }
        const isAttackerFriendly = attackingBoard.every((entity) => entity.friendly);
        const playerHero = isAttackerFriendly ? attackingBoardHero : defendingBoardHero;
        const opponentHero = isAttackerFriendly ? defendingBoardHero : attackingBoardHero;
        const friendlyBoard = isAttackerFriendly ? attackingBoard : defendingBoard;
        const opponentBoard = isAttackerFriendly ? defendingBoard : attackingBoard;
        const action = (0, game_action_1.buildGameAction)(playerHero, opponentHero, {
            type: 'attack',
            sourceEntityId: attackingEntity.entityId,
            targetEntityId: defendingEntity.entityId,
            playerBoard: this.sanitize(friendlyBoard),
            playerHand: this.sanitize(playerHero.hand),
            opponentBoard: this.sanitize(opponentBoard),
            opponentHand: this.sanitize(opponentHero.hand),
        });
        this.addAction(action);
    }
    registerStartOfCombat(friendlyBoard, opponentBoard, friendlyHero, opponentHero) {
        if (!this.enabled) {
            return;
        }
        const action = (0, game_action_1.buildGameAction)(friendlyHero, opponentHero, {
            type: 'start-of-combat',
            playerBoard: this.sanitize(friendlyBoard),
            opponentBoard: this.sanitize(opponentBoard),
            playerHand: this.sanitize(friendlyHero.hand),
            opponentHand: this.sanitize(opponentHero.hand),
        });
        this.addAction(action);
    }
    registerPlayerAttack(friendlyBoard, opponentBoard, damage) {
        if (!this.enabled) {
            return;
        }
        const action = (0, game_action_1.buildGameAction)(null, null, {
            type: 'player-attack',
            playerBoard: this.sanitize(friendlyBoard),
            opponentBoard: this.sanitize(opponentBoard),
            playerHand: null,
            opponentHand: null,
            damages: [
                {
                    damage: damage,
                },
            ],
        });
        this.addAction(action);
    }
    registerOpponentAttack(friendlyBoard, opponentBoard, damage) {
        if (!this.enabled) {
            return;
        }
        const action = (0, game_action_1.buildGameAction)(null, null, {
            type: 'opponent-attack',
            playerBoard: this.sanitize(friendlyBoard),
            opponentBoard: this.sanitize(opponentBoard),
            playerHand: null,
            opponentHand: null,
            damages: [
                {
                    damage: damage,
                },
            ],
        });
        this.addAction(action);
    }
    registerDamageDealt(damagingEntity, damagedEntity, damageTaken, damagedEntityBoard) {
        if (!this.enabled) {
            return;
        }
        if (!damagingEntity.entityId) {
        }
        const friendlyBoard = damagedEntityBoard.every((entity) => entity.friendly) ? damagedEntityBoard : null;
        const opponentBoard = damagedEntityBoard.every((entity) => !entity.friendly) ? damagedEntityBoard : null;
        const action = (0, game_action_1.buildGameAction)(null, null, {
            type: 'damage',
            damages: [
                {
                    sourceEntityId: damagingEntity.entityId,
                    targetEntityId: damagedEntity.entityId,
                    damage: damageTaken,
                },
            ],
            playerBoard: this.sanitize(friendlyBoard),
            opponentBoard: this.sanitize(opponentBoard),
            playerHand: null,
            opponentHand: null,
        });
        this.addAction(action);
    }
    registerPowerTarget(sourceEntity, targetEntity, targetBoard, hero1, hero2) {
        if (!this.enabled) {
            return;
        }
        if (!targetEntity) {
            return;
        }
        const friendlyBoard = (targetBoard === null || targetBoard === void 0 ? void 0 : targetBoard.every((entity) => entity.friendly)) ? targetBoard : null;
        const opponentBoard = (targetBoard === null || targetBoard === void 0 ? void 0 : targetBoard.every((entity) => !entity.friendly)) ? targetBoard : null;
        const friendlyHero = (hero1 === null || hero1 === void 0 ? void 0 : hero1.friendly) ? hero1 : (hero2 === null || hero2 === void 0 ? void 0 : hero2.friendly) ? hero2 : null;
        const opponentHero = (hero1 === null || hero1 === void 0 ? void 0 : hero1.friendly) ? hero2 : (hero2 === null || hero2 === void 0 ? void 0 : hero2.friendly) ? hero1 : null;
        const action = (0, game_action_1.buildGameAction)(friendlyHero, opponentHero, {
            type: 'power-target',
            sourceEntityId: sourceEntity.entityId,
            targetEntityId: targetEntity.entityId,
            playerBoard: this.sanitize(friendlyBoard),
            opponentBoard: this.sanitize(opponentBoard),
            playerHand: this.sanitize(friendlyHero === null || friendlyHero === void 0 ? void 0 : friendlyHero.hand),
            opponentHand: this.sanitize(opponentHero === null || opponentHero === void 0 ? void 0 : opponentHero.hand),
        });
        this.addAction(action);
    }
    registerMinionsSpawn(sourceEntity, boardOnWhichToSpawn, spawnedEntities) {
        if (!this.enabled) {
            return;
        }
        if (!spawnedEntities || spawnedEntities.length === 0) {
            return;
        }
        if (!(sourceEntity === null || sourceEntity === void 0 ? void 0 : sourceEntity.entityId)) {
        }
        const friendlyBoard = boardOnWhichToSpawn.every((entity) => entity.friendly) ? boardOnWhichToSpawn : null;
        const opponentBoard = boardOnWhichToSpawn.every((entity) => !entity.friendly) ? boardOnWhichToSpawn : null;
        const action = (0, game_action_1.buildGameAction)(null, null, {
            type: 'spawn',
            spawns: this.sanitize(spawnedEntities),
            sourceEntityId: sourceEntity === null || sourceEntity === void 0 ? void 0 : sourceEntity.entityId,
            playerBoard: this.sanitize(friendlyBoard),
            opponentBoard: this.sanitize(opponentBoard),
            playerHand: null,
            opponentHand: null,
        });
        this.addAction(action);
    }
    registerDeadEntities(deadMinionIndexes1, deadEntities1, board1, deadMinionIndexes2, deadEntities2, board2) {
        if (!this.enabled) {
            return;
        }
        const deaths = [...(deadEntities1 || []), ...(deadEntities2 || [])];
        if (!deaths || deaths.length === 0) {
            return;
        }
        const action = (0, game_action_1.buildGameAction)(null, null, {
            type: 'minion-death',
            deaths: this.sanitize(deaths),
            deadMinionsPositionsOnBoard: [
                ...(deadMinionIndexes1 || []).map((i) => board1.length - i),
                ...(deadMinionIndexes2 || []).map((i) => board2.length - i),
            ],
        });
        this.addAction(action);
    }
    addAction(action) {
        this.actionsForCurrentBattle.push(action);
    }
    collapseActions(actions) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1;
        if (!this.enabled) {
            return [];
        }
        if (!actions || actions.length === 0) {
            return [];
        }
        const result = [];
        for (let i = 0; i < actions.length; i++) {
            const action = {
                ...actions[i],
                playerBoard: this.sanitize(actions[i].playerBoard),
                opponentBoard: this.sanitize(actions[i].opponentBoard),
                playerHand: this.sanitize(actions[i].playerHand),
                opponentHand: this.sanitize(actions[i].opponentHand),
                deaths: this.sanitize(actions[i].deaths),
                playerTrinkets: this.sanitizeTrinkets(actions[i].playerTrinkets),
                opponentTrinkets: this.sanitizeTrinkets(actions[i].opponentTrinkets),
            };
            const lastAction = result.length > 0 ? result[result.length - 1] : null;
            if (lastAction) {
                action.playerBoard = (_a = action.playerBoard) !== null && _a !== void 0 ? _a : lastAction.playerBoard;
                action.opponentBoard = (_b = action.opponentBoard) !== null && _b !== void 0 ? _b : lastAction.opponentBoard;
                action.playerHand = (_c = action.playerHand) !== null && _c !== void 0 ? _c : lastAction.playerHand;
                action.opponentHand = (_d = action.opponentHand) !== null && _d !== void 0 ? _d : lastAction.opponentHand;
                action.playerSecrets = (_e = action.playerSecrets) !== null && _e !== void 0 ? _e : lastAction.playerSecrets;
                action.opponentSecrets = (_f = action.opponentSecrets) !== null && _f !== void 0 ? _f : lastAction.opponentSecrets;
                action.playerRewardCardId = (_g = action.playerRewardCardId) !== null && _g !== void 0 ? _g : lastAction.playerRewardCardId;
                action.playerRewardEntityId = (_h = action.playerRewardEntityId) !== null && _h !== void 0 ? _h : lastAction.playerRewardEntityId;
                action.playerRewardData = (_j = action.playerRewardData) !== null && _j !== void 0 ? _j : lastAction.playerRewardData;
                action.opponentRewardCardId = (_k = action.opponentRewardCardId) !== null && _k !== void 0 ? _k : lastAction.opponentRewardCardId;
                action.opponentRewardEntityId = (_l = action.opponentRewardEntityId) !== null && _l !== void 0 ? _l : lastAction.opponentRewardEntityId;
                action.opponentRewardData = (_m = action.opponentRewardData) !== null && _m !== void 0 ? _m : lastAction.opponentRewardData;
                action.playerCardId = (_o = action.playerCardId) !== null && _o !== void 0 ? _o : lastAction.playerCardId;
                action.playerEntityId = (_p = action.playerEntityId) !== null && _p !== void 0 ? _p : lastAction.playerEntityId;
                action.playerHeroPowerCardId = (_q = action.playerHeroPowerCardId) !== null && _q !== void 0 ? _q : lastAction.playerHeroPowerCardId;
                action.playerHeroPowerEntityId = (_r = action.playerHeroPowerEntityId) !== null && _r !== void 0 ? _r : lastAction.playerHeroPowerEntityId;
                action.playerHeroPowerUsed = (_s = action.playerHeroPowerUsed) !== null && _s !== void 0 ? _s : lastAction.playerHeroPowerUsed;
                action.opponentCardId = (_t = action.opponentCardId) !== null && _t !== void 0 ? _t : lastAction.opponentCardId;
                action.opponentEntityId = (_u = action.opponentEntityId) !== null && _u !== void 0 ? _u : lastAction.opponentEntityId;
                action.opponentHeroPowerCardId = (_v = action.opponentHeroPowerCardId) !== null && _v !== void 0 ? _v : lastAction.opponentHeroPowerCardId;
                action.opponentHeroPowerEntityId =
                    (_w = action.opponentHeroPowerEntityId) !== null && _w !== void 0 ? _w : lastAction.opponentHeroPowerEntityId;
                action.opponentHeroPowerUsed = (_x = action.opponentHeroPowerUsed) !== null && _x !== void 0 ? _x : lastAction.opponentHeroPowerUsed;
                action.playerTrinkets = (_y = action.playerTrinkets) !== null && _y !== void 0 ? _y : lastAction.playerTrinkets;
                action.opponentTrinkets = (_z = action.opponentTrinkets) !== null && _z !== void 0 ? _z : lastAction.opponentTrinkets;
            }
            if (lastAction && action.type === 'damage' && lastAction.type === 'attack') {
                lastAction.damages = lastAction.damages || [];
                lastAction.damages.push({
                    damage: action.damages[0].damage,
                    sourceEntityId: action.damages[0].sourceEntityId,
                    targetEntityId: action.damages[0].targetEntityId,
                });
                lastAction.playerBoard = action.playerBoard;
                lastAction.opponentBoard = action.opponentBoard;
                lastAction.playerHand = action.playerHand;
                lastAction.opponentHand = action.opponentHand;
                lastAction.playerSecrets = action.playerSecrets;
                lastAction.opponentSecrets = action.opponentSecrets;
                lastAction.playerTrinkets = action.playerTrinkets;
                lastAction.opponentTrinkets = action.opponentTrinkets;
            }
            else if (lastAction && action.type === 'damage' && lastAction.type === 'damage') {
                lastAction.damages = lastAction.damages || [];
                lastAction.damages.push({
                    damage: action.damages[0].damage,
                    sourceEntityId: action.damages[0].sourceEntityId,
                    targetEntityId: action.damages[0].targetEntityId,
                });
                lastAction.playerBoard = action.playerBoard;
                lastAction.opponentBoard = action.opponentBoard;
                lastAction.playerHand = action.playerHand;
                lastAction.opponentHand = action.opponentHand;
                lastAction.playerSecrets = action.playerSecrets;
                lastAction.opponentSecrets = action.opponentSecrets;
                lastAction.playerTrinkets = action.playerTrinkets;
                lastAction.opponentTrinkets = action.opponentTrinkets;
            }
            else if (lastAction &&
                action.type === 'power-target' &&
                lastAction.type === 'power-target' &&
                action.sourceEntityId === lastAction.sourceEntityId) {
                lastAction.targetEntityIds =
                    (_0 = lastAction.targetEntityIds) !== null && _0 !== void 0 ? _0 : (lastAction.targetEntityId ? [lastAction.targetEntityId] : []);
                action.targetEntityIds =
                    (_1 = action.targetEntityIds) !== null && _1 !== void 0 ? _1 : (action.targetEntityId ? [action.targetEntityId] : []);
                lastAction.targetEntityIds.push(...action.targetEntityIds);
                lastAction.playerBoard = action.playerBoard;
                lastAction.opponentBoard = action.opponentBoard;
                lastAction.playerHand = action.playerHand;
                lastAction.opponentHand = action.opponentHand;
                lastAction.playerSecrets = action.playerSecrets;
                lastAction.opponentSecrets = action.opponentSecrets;
                lastAction.playerTrinkets = action.playerTrinkets;
                lastAction.opponentTrinkets = action.opponentTrinkets;
            }
            else {
                result.push(action);
            }
        }
        return result;
    }
    sanitize(board) {
        if (!board) {
            return undefined;
        }
        return board.map((entity) => ({
            entityId: entity.entityId,
            cardId: entity.cardId,
            friendly: entity.friendly,
            attack: entity.attack,
            health: entity.health,
            maxHealth: entity.maxHealth,
            taunt: entity.taunt,
            divineShield: entity.divineShield,
            poisonous: entity.poisonous,
            venomous: entity.venomous,
            reborn: entity.reborn,
            windfury: entity.windfury,
            stealth: entity.stealth,
        }));
    }
    sanitizeTrinkets(trinkets) {
        if (!(trinkets === null || trinkets === void 0 ? void 0 : trinkets.length)) {
            return undefined;
        }
        const result = trinkets.map((t) => ({
            cardId: t.cardId,
            entityId: t.entityId,
            scriptDataNum1: t.scriptDataNum1,
            scriptDataNum6: t.scriptDataNum6,
        }));
        return result;
    }
}
exports.Spectator = Spectator;
//# sourceMappingURL=spectator.js.map