"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.hasMinionBattlecry = exports.triggerBattlecry = exports.computeBattlecryMultiplier = void 0;
const reference_data_1 = require("@firestone-hs/reference-data");
const card_interface_1 = require("../cards/card.interface");
const _card_mappings_1 = require("../cards/impl/_card-mappings");
const taunt_1 = require("../keywords/taunt");
const utils_1 = require("../services/utils");
const utils_2 = require("../utils");
const attack_1 = require("./attack");
const cards_in_hand_1 = require("./cards-in-hand");
const damage_to_hero_1 = require("./damage-to-hero");
const deathrattle_spawns_1 = require("./deathrattle-spawns");
const spawns_1 = require("./spawns");
const stats_1 = require("./stats");
const golden_1 = require("./utils/golden");
const DOUBLE_BATTLECRY_CARD_IDS = [
    "BG_LOE_077",
    "BG27_518",
    "BG28_509",
    "BG34_Giant_376",
];
const TRIPLE_BATTLECRY_CARD_IDS = [
    "TB_BaconUps_045",
    "BG27_518_G",
    "BG34_Giant_376_G",
];
const computeBattlecryMultiplier = (board, boardHero, sharedState) => {
    var _a, _b, _c, _d, _e, _f;
    const cardIds = [...board.map((e) => e.cardId), ...((_b = (_a = boardHero.secrets) === null || _a === void 0 ? void 0 : _a.map((e) => e.cardId)) !== null && _b !== void 0 ? _b : [])];
    const triggerMult = cardIds.some((cardId) => TRIPLE_BATTLECRY_CARD_IDS.includes(cardId))
        ? 3
        : cardIds.some((cardId) => DOUBLE_BATTLECRY_CARD_IDS.includes(cardId))
            ? 2
            : 1;
    const gilneanWarHorns = (_e = (_d = (_c = boardHero.questRewardEntities) === null || _c === void 0 ? void 0 : _c.filter((entity) => entity.cardId === "BG27_Reward_802")) === null || _d === void 0 ? void 0 : _d.length) !== null && _e !== void 0 ? _e : 0;
    const echoesOfArgus = sharedState.anomalies.includes("BG27_Anomaly_802") ? 1 : 0;
    const warDrum = (_f = boardHero.trinkets) === null || _f === void 0 ? void 0 : _f.find((t) => t.cardId === "BG32_MagicItem_416" && t.scriptDataNum1 > 0);
    let multiplier = echoesOfArgus + triggerMult + gilneanWarHorns;
    if (warDrum) {
        multiplier = multiplier * 2;
        warDrum.scriptDataNum1--;
    }
    return multiplier;
};
exports.computeBattlecryMultiplier = computeBattlecryMultiplier;
const triggerBattlecry = (board, hero, entity, otherBoard, otherHero, gameState) => {
    var _a, _b, _c, _d, _e, _f, _g, _h, _j;
    hero.globalInfo.CardsPlayedThisTurn = ((_a = hero.globalInfo.CardsPlayedThisTurn) !== null && _a !== void 0 ? _a : 0) + 1;
    const allMinions = [...board, ...otherBoard];
    const totalTriggers = (0, exports.computeBattlecryMultiplier)(board, hero, gameState.sharedState);
    for (let z = 0; z < totalTriggers; z++) {
        let hasTriggered = true;
        const battlecryImpl = _card_mappings_1.cardMappings[entity.cardId];
        let hasBattlecryTrigger = false;
        if ((0, card_interface_1.hasBattlecry)(battlecryImpl)) {
            hasBattlecryTrigger = battlecryImpl.battlecry(entity, {
                hero: hero,
                board: board,
                otherHero: otherHero,
                otherBoard: otherBoard,
                gameState,
            });
        }
        if (!hasBattlecryTrigger) {
            switch (entity.cardId) {
                case "BG_UNG_073":
                case "TB_BaconUps_061":
                    const rockPoolTarget = (0, utils_2.getRandomAliveMinion)(board, hero, reference_data_1.Race.MURLOC, gameState);
                    if (!!rockPoolTarget) {
                        const rockpoolStats = entity.cardId === "BG_UNG_073" ? 1 : 2;
                        (0, stats_1.modifyStats)(rockPoolTarget, entity, rockpoolStats, rockpoolStats, board, hero, gameState);
                    }
                    break;
                case "BGS_082":
                case "TB_BaconUps_144":
                    const menagerieMugStats = entity.cardId === "BGS_082" ? 1 : 2;
                    (0, utils_2.grantStatsToMinionsOfEachType)(entity, board, hero, menagerieMugStats, menagerieMugStats, gameState, 3);
                    break;
                case "BG_AT_069":
                case "BG_AT_069_G":
                    const sparringPartnersTargets = allMinions.filter((e) => !e.taunt);
                    const sparringPartnersTarget = (0, utils_1.pickRandom)(sparringPartnersTargets);
                    if (sparringPartnersTarget) {
                        (0, taunt_1.updateTaunt)(sparringPartnersTarget, true, board, hero, otherHero, gameState);
                    }
                    break;
                case "BGS_038":
                case "TB_BaconUps_108":
                    const twilightEmissaryTarget = (0, utils_2.getRandomAliveMinion)(board, hero, reference_data_1.Race.DRAGON, gameState);
                    if (!!twilightEmissaryTarget) {
                        const twilightEmissaryStats = entity.cardId === "BGS_038" ? 2 : 4;
                        (0, stats_1.modifyStats)(twilightEmissaryTarget, entity, twilightEmissaryStats, twilightEmissaryStats, board, hero, gameState);
                    }
                    break;
                case "BGS_053":
                case "TB_BaconUps_138":
                    (0, utils_2.addStatsToBoard)(entity, board.filter((e) => e.entityId != entity.entityId), hero, entity.cardId === "BGS_053" ? 3 : 6, 0, gameState, reference_data_1.Race[reference_data_1.Race.PIRATE]);
                    break;
                case "BG29_502":
                case "BG29_502_G":
                    (0, utils_2.addStatsToBoard)(entity, board.filter((e) => e.entityId != entity.entityId), hero, 0, entity.cardId === "BG29_502" ? 4 : 8, gameState, reference_data_1.Race[reference_data_1.Race.PIRATE]);
                    break;
                case "BG_EX1_103":
                case "TB_BaconUps_064":
                    (0, utils_2.addStatsToBoard)(entity, board.filter((e) => e.entityId != entity.entityId), hero, 0, entity.cardId === "BG_EX1_103" ? 2 : 4, gameState, reference_data_1.Race[reference_data_1.Race.MURLOC]);
                    break;
                case "BG26_522":
                case "BG26_522_G":
                    const numberOfTimesToTrigger = entity.cardId === "BG26_522" ? 1 : 2;
                    for (let i = 0; i < numberOfTimesToTrigger; i++) {
                        (0, utils_2.addStatsToBoard)(entity, board.filter((e) => e.entityId != entity.entityId), hero, 2, 2, gameState, reference_data_1.Race[reference_data_1.Race.DEMON]);
                        (0, damage_to_hero_1.dealDamageToHero)(entity, hero, board, 2, gameState);
                    }
                    break;
                case "BG21_021":
                case "BG21_021_G":
                    const smoggerLoops = entity.cardId === "BG21_021" ? 1 : 2;
                    for (let i = 0; i < smoggerLoops; i++) {
                        const smoggerTarget = (0, utils_2.getRandomAliveMinion)(board, hero, reference_data_1.Race.ELEMENTAL, gameState);
                        const smoggerStats = (_b = hero.tavernTier) !== null && _b !== void 0 ? _b : 3;
                        (0, stats_1.modifyStats)(smoggerTarget, entity, smoggerStats, smoggerStats, board, hero, gameState);
                    }
                    break;
                case "BGS_010":
                    const startingHp = hero.cardId === "TB_BaconShop_HERO_34" ? 60 : 30;
                    const hpMissing = startingHp - hero.hpLeft;
                    const annihilanStats = (entity.cardId === "BGS_010" ? 2 : 4) * hpMissing;
                    (0, stats_1.modifyStats)(entity, entity, 0, annihilanStats, board, hero, gameState);
                    break;
                case "BG_ICC_807":
                case "TB_BaconUps_072":
                    const strongshellScavengerStats = entity.cardId === "BG_ICC_807" ? 2 : 4;
                    const strongshellScavengerTargets = board
                        .filter((e) => e.entityId != entity.entityId)
                        .filter((e) => e.taunt);
                    strongshellScavengerTargets.forEach((target) => {
                        (0, stats_1.modifyStats)(target, entity, strongshellScavengerStats, strongshellScavengerStats, board, hero, gameState);
                    });
                    break;
                case "BGS_043":
                case "TB_BaconUps_110":
                    const murozondCardsToAdd = entity.cardId === "BGS_043"
                        ? ["BG28_810"]
                        : ["BG28_810", "BG28_810"];
                    (0, cards_in_hand_1.addCardsInHand)(hero, board, murozondCardsToAdd, gameState);
                    break;
                case "BGS_123":
                case "TB_BaconUps_162":
                    const tavernTempestCardsToAdd = entity.cardId === "BGS_123"
                        ? ["BG28_810"]
                        : ["BG28_810", "BG28_810"];
                    (0, cards_in_hand_1.addCardsInHand)(hero, board, tavernTempestCardsToAdd, gameState);
                    break;
                case "BG23_190":
                case "BG23_190_G":
                    const utherTarget = (0, utils_1.pickRandom)(allMinions);
                    const utherStats = entity.cardId === "BG23_190" ? 15 : 30;
                    utherTarget.attack = utherStats;
                    utherTarget.health = utherStats;
                    utherTarget.maxHealth = utherStats;
                    break;
                case "BG27_001":
                case "BG27_001_G":
                    const differentTypes = extractUniqueTribes(board, gameState.allCards);
                    const livingConstellationStats = (entity.cardId === "BG27_001" ? 1 : 2) * differentTypes.length;
                    const livingConstellationTarget = (0, utils_1.pickRandom)(allMinions);
                    const boardForTarget = board.includes(livingConstellationTarget) ? board : otherBoard;
                    (0, stats_1.modifyStats)(livingConstellationTarget, entity, livingConstellationStats, livingConstellationStats, boardForTarget, hero, gameState);
                    break;
                case "BG27_018":
                case "BG27_018_G":
                    const emergentFlameTarget = (0, utils_1.pickRandom)(allMinions.filter((e) => (0, utils_2.hasCorrectTribe)(e, hero, reference_data_1.Race.ELEMENTAL, gameState.anomalies, gameState.allCards)));
                    if (!!emergentFlameTarget) {
                        const targetBoard = board.includes(emergentFlameTarget) ? board : otherBoard;
                        const targetHero = board.includes(emergentFlameTarget) ? hero : otherHero;
                        const emergentFlameMultiplier = entity.cardId === "BG27_018" ? 1 : 2;
                        const emergentFlameStats = ((_c = entity.scriptDataNum1) !== null && _c !== void 0 ? _c : 1) * emergentFlameMultiplier;
                        (0, stats_1.modifyStats)(emergentFlameTarget, entity, emergentFlameStats, emergentFlameStats, targetBoard, targetHero, gameState);
                    }
                    break;
                case "BG_SCH_149":
                case "TB_BaconUps_308":
                    const highestAttack = Math.max(...allMinions.map((minion) => minion.attack));
                    const highestHealth = Math.max(...allMinions.map((minion) => minion.health));
                    const argentBraggartMultiplier = entity.cardId === "BG_SCH_149" ? 1 : 2;
                    entity.attack = argentBraggartMultiplier * highestAttack;
                    entity.health = argentBraggartMultiplier * highestHealth;
                    break;
                case "BG25_034":
                case "BG25_034_G":
                    const captainSandersTarget = (0, utils_1.pickRandom)(board.filter((e) => !(0, golden_1.isMinionGolden)(e, gameState.allCards) && e.tavernTier <= 6));
                    if (captainSandersTarget) {
                        (0, golden_1.makeMinionGolden)(captainSandersTarget, entity, board, hero, otherBoard, otherHero, gameState);
                    }
                    break;
                case "BG23_017":
                case "BG23_017_G":
                    const sanguineChampionStats = entity.cardId === "BG23_017" ? 1 : 2;
                    hero.globalInfo.BloodGemAttackBonus += sanguineChampionStats;
                    hero.globalInfo.BloodGemHealthBonus += sanguineChampionStats;
                    break;
                case "BG24_719":
                case "BG24_719_G":
                    const target = (0, utils_1.pickRandom)(allMinions.filter((e) => !e.definitelyDead && e.health > 0));
                    if (target) {
                        gameState.spectator.registerPowerTarget(entity, target, board, hero, otherHero);
                        const minionTier = gameState.cardsData.getTavernLevel(target.cardId);
                        const targetTier = entity.cardId === "BG24_719" ? minionTier + 1 : minionTier + 2;
                        const maxTier = !!((_d = gameState.anomalies) === null || _d === void 0 ? void 0 : _d.includes("BG27_Anomaly_504")) ||
                            ((_e = hero.questRewardEntities) === null || _e === void 0 ? void 0 : _e.some((r) => r.cardId === "BG33_Reward_010"))
                            ? 7
                            : 6;
                        const newMinionId = gameState.cardsData.getRandomMinionForTavernTier(Math.min(maxTier, targetTier));
                        const targetBoard = board.includes(target) ? board : otherBoard;
                        const targetHero = board.includes(target) ? hero : otherHero;
                        const newMinion = (0, utils_2.buildSingleBoardEntity)(newMinionId, hero, board, gameState.allCards, targetHero.friendly, gameState.sharedState.currentEntityId++, false, gameState.cardsData, gameState.sharedState, null);
                        const index = targetBoard.indexOf(target);
                        targetBoard.splice(index, 1, newMinion);
                        gameState.spectator.registerPowerTarget(entity, newMinion, targetBoard, hero, otherHero);
                    }
                    break;
                case "BG28_630":
                case "BG28_630_G":
                    const eagillMultiplier = entity.cardId === "BG28_630" ? 1 : 2;
                    const eagillBoardTarget = (0, utils_1.pickRandom)(board.filter((e) => e.entityId !== entity.entityId));
                    if (eagillBoardTarget) {
                        (0, stats_1.modifyStats)(eagillBoardTarget, entity, 2 * eagillMultiplier, 3 * eagillMultiplier, board, hero, gameState);
                    }
                    const eagillHandTarget = (0, utils_1.pickRandom)(hero.hand.filter((e) => { var _a; return ((_a = gameState.allCards.getCard(e.cardId).type) === null || _a === void 0 ? void 0 : _a.toUpperCase()) === reference_data_1.CardType[reference_data_1.CardType.MINION]; }));
                    if (eagillHandTarget) {
                        (0, stats_1.modifyStats)(eagillHandTarget, entity, 2 * eagillMultiplier, 3 * eagillMultiplier, board, hero, gameState);
                    }
                    break;
                case "BG26_045":
                case "BG26_045_G":
                    const shellWhistlerCardsToAdd = entity.cardId === "BG26_045_G" ? [null] : [null, null];
                    (0, cards_in_hand_1.addCardsInHand)(hero, board, shellWhistlerCardsToAdd, gameState);
                    break;
                case "BGDUO_104":
                case "BGDUO_104_G":
                    const playerState = (0, utils_2.getPlayerState)(gameState.gameState, hero);
                    if (playerState) {
                        const cardsToAdd = entity.cardId === "BGDUO_104"
                            ? ["BG28_810"]
                            : ["BG28_810", "BG28_810"];
                        (0, cards_in_hand_1.addCardsInHand)(playerState.player, playerState.board, cardsToAdd, gameState);
                    }
                    break;
                case "BGDUO_111":
                case "BGDUO_111_G":
                    const cardsToAdd = entity.cardId === "BGDUO_111"
                        ? ["BG20_GEM"]
                        : ["BG20_GEM", "BG20_GEM"];
                    (0, cards_in_hand_1.addCardsInHand)(gameState.gameState.player.player, gameState.gameState.player.board, cardsToAdd, gameState);
                    if (gameState.gameState.player.teammate) {
                        (0, cards_in_hand_1.addCardsInHand)(gameState.gameState.player.teammate.player, gameState.gameState.player.teammate.board, cardsToAdd, gameState);
                    }
                    break;
                case "BGDUO_119":
                case "BGDUO_119_G":
                    const conductorTarget = (0, utils_1.pickRandom)(allMinions.filter((e) => (0, utils_2.hasCorrectTribe)(e, hero, reference_data_1.Race.ELEMENTAL, gameState.anomalies, gameState.allCards)));
                    if (!!conductorTarget) {
                        const targetBoard = board.includes(conductorTarget) ? board : otherBoard;
                        const targetHero = board.includes(conductorTarget) ? hero : otherHero;
                        const multiplier = entity.cardId === "BGDUO_119" ? 1 : 2;
                        const attackStats = 2 * ((_f = entity.scriptDataNum1) !== null && _f !== void 0 ? _f : 1) * multiplier;
                        const healthStats = 2 * ((_g = entity.scriptDataNum1) !== null && _g !== void 0 ? _g : 1) * multiplier;
                        (0, stats_1.modifyStats)(conductorTarget, entity, attackStats, healthStats, targetBoard, targetHero, gameState);
                    }
                    break;
                case "BGDUO_HERO_100_Buddy":
                case "BGDUO_HERO_100_Buddy_G":
                    const facelessOneCardsToAdd = entity.cardId === "BGDUO_HERO_100_Buddy" ? [null] : [null, null];
                    (0, cards_in_hand_1.addCardsInHand)(hero, board, facelessOneCardsToAdd, gameState);
                    break;
                case "TB_BaconShop_HERO_91_Buddy":
                case "TB_BaconShop_HERO_91_Buddy_G":
                    const phyreszCardsToAdd = entity.cardId === "TB_BaconShop_HERO_91_Buddy" ? [null] : [null, null];
                    (0, cards_in_hand_1.addCardsInHand)(hero, board, phyreszCardsToAdd, gameState);
                    break;
                case "TB_BaconShop_HERO_23_Buddy":
                case "TB_BaconShop_HERO_23_Buddy_G":
                    const muckslingerCardsToAdd = entity.cardId === "TB_BaconShop_HERO_23_Buddy"
                        ? [(0, utils_1.pickRandom)(gameState.cardsData.battlecryMinions)]
                        : [
                            (0, utils_1.pickRandom)(gameState.cardsData.battlecryMinions),
                            (0, utils_1.pickRandom)(gameState.cardsData.battlecryMinions),
                        ];
                    (0, cards_in_hand_1.addCardsInHand)(hero, board, muckslingerCardsToAdd, gameState);
                    break;
                case "BG29_861":
                case "BG29_861_G":
                    const barrendsBrawlerCardsToAdd = entity.cardId === "BG29_861"
                        ? [(0, utils_1.pickRandom)(gameState.cardsData.deathrattleMinions)]
                        : [
                            (0, utils_1.pickRandom)(gameState.cardsData.deathrattleMinions),
                            (0, utils_1.pickRandom)(gameState.cardsData.deathrattleMinions),
                        ];
                    (0, cards_in_hand_1.addCardsInHand)(hero, board, barrendsBrawlerCardsToAdd, gameState);
                    break;
                case "BG23_HERO_306_Buddy":
                case "BG23_HERO_306_Buddy_G":
                    const nathanosTarget = (0, utils_1.pickRandom)(board);
                    if (nathanosTarget) {
                        gameState.spectator.registerPowerTarget(entity, nathanosTarget, board, null, null);
                        nathanosTarget.definitelyDead = true;
                        const buffMultiplier = entity.cardId === "BG23_HERO_306_Buddy" ? 1 : 2;
                        const attackBuff = nathanosTarget.attack * buffMultiplier;
                        const healthBuff = nathanosTarget.health * buffMultiplier;
                        const buffTargets = (0, attack_1.getNeighbours)(board, nathanosTarget);
                        buffTargets.forEach((e) => {
                            (0, stats_1.modifyStats)(e, entity, attackBuff, healthBuff, board, hero, gameState);
                        });
                    }
                    break;
                case "BG30_104":
                case "BG30_104_G":
                    if (board.length > 0) {
                        const transformedInto = gameState.cardsData.getRandomMinionForTavernTier(3);
                        const premiumDbfId = gameState.allCards.getCard(transformedInto).battlegroundsPremiumDbfId;
                        const goldenCardId = gameState.allCards.getCard(premiumDbfId).id;
                        const currentIndex = board.findIndex((e) => e.entityId === entity.entityId);
                        const currentIndexFromRight = board.length - currentIndex - 1;
                        board.splice(currentIndex, 1);
                        const newMinions = (0, deathrattle_spawns_1.spawnEntities)(goldenCardId, 1, board, hero, otherBoard, otherHero, gameState, entity.friendly, false);
                        const spawns = (0, spawns_1.performEntitySpawns)(newMinions, board, hero, entity, currentIndexFromRight, otherBoard, otherHero, gameState);
                    }
                    break;
                case "BG30_850":
                case "BG30_850_G":
                    const newMinions = (0, deathrattle_spawns_1.spawnEntities)(entity.cardId === "BG30_850_G"
                        ? "BG_ICC_026t_G"
                        : "BG_ICC_026t", 1, board, hero, otherBoard, otherHero, gameState, entity.friendly, false);
                    const indexFromRight = board.length - board.findIndex((e) => e.entityId === entity.entityId) - 1;
                    const spawns = (0, spawns_1.performEntitySpawns)(newMinions, board, hero, entity, indexFromRight, otherBoard, otherHero, gameState);
                    break;
                default:
                    const hasBattlecry = (_j = (_h = gameState.allCards
                        .getCard(entity.cardId)) === null || _h === void 0 ? void 0 : _h.mechanics) === null || _j === void 0 ? void 0 : _j.includes(reference_data_1.GameTag[reference_data_1.GameTag.BATTLECRY]);
                    hasTriggered = hasBattlecry;
                    break;
            }
        }
        if (hasTriggered) {
            afterBattlecryTriggered(entity, board, hero, otherBoard, otherHero, gameState);
        }
    }
};
exports.triggerBattlecry = triggerBattlecry;
const afterBattlecryTriggered = (entity, board, hero, otherBoard, otherHero, gameState) => {
    for (const boardEntity of board) {
        const onBattlecryTriggeredImpl = _card_mappings_1.cardMappings[boardEntity.cardId];
        if ((0, card_interface_1.hasOnBattlecryTriggered)(onBattlecryTriggeredImpl)) {
            onBattlecryTriggeredImpl.onBattlecryTriggered(boardEntity, {
                board: board,
                hero: hero,
                otherBoard: otherBoard,
                otherHero: otherHero,
                gameState: gameState,
            });
        }
    }
};
const extractUniqueTribes = (board, allCards) => {
    const boardReferenceCards = board.map((m) => allCards.getCard(m.cardId));
    const minionsPlayedWithTribes = boardReferenceCards.filter((c) => { var _a; return !!((_a = c.races) === null || _a === void 0 ? void 0 : _a.length); });
    const minionsToProcess = [
        ...minionsPlayedWithTribes
            .filter((c) => !c.races.includes(reference_data_1.Race[reference_data_1.Race.ALL]))
            .map((c) => ({ ...c, races: [...c.races] })),
    ];
    const uniqueTribes = [];
    const maxTribesPerMinion = 2;
    for (let i = 1; i <= maxTribesPerMinion; i++) {
        let dirty = true;
        while (dirty) {
            dirty = false;
            for (let j = 0; j < minionsToProcess.length; j++) {
                const minion = minionsToProcess[j];
                if (!minion.picked && minion.races.length > 0 && minion.races.length <= i) {
                    const raceToAdd = minion.races[0];
                    uniqueTribes.push(reference_data_1.Race[raceToAdd]);
                    for (const m of minionsToProcess) {
                        m.races = m.races.filter((r) => r !== raceToAdd);
                    }
                    minion.picked = true;
                    dirty = true;
                    j = 0;
                }
            }
        }
    }
    uniqueTribes.push(...minionsPlayedWithTribes
        .filter((m) => m.races.includes(reference_data_1.Race[reference_data_1.Race.ALL]))
        .flatMap((m) => m.races)
        .map((r) => reference_data_1.Race[r]));
    return uniqueTribes;
};
const hasMinionBattlecry = (entity, gameState) => {
    var _a, _b, _c;
    return (_c = (_b = (_a = gameState.allCards.getCard(entity.cardId)) === null || _a === void 0 ? void 0 : _a.mechanics) === null || _b === void 0 ? void 0 : _b.includes(reference_data_1.GameTag[reference_data_1.GameTag.BATTLECRY])) !== null && _c !== void 0 ? _c : false;
};
exports.hasMinionBattlecry = hasMinionBattlecry;
//# sourceMappingURL=battlecries.js.map