"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PostPlayerChangeStat = void 0;
const cachedEnumValues_1 = require("../../arrays/cachedEnumValues");
const ModCallbackCustom_1 = require("../../enums/ModCallbackCustom");
const bitSet128_1 = require("../../functions/bitSet128");
const color_1 = require("../../functions/color");
const playerIndex_1 = require("../../functions/playerIndex");
const stats_1 = require("../../functions/stats");
const types_1 = require("../../functions/types");
const vector_1 = require("../../functions/vector");
const shouldFire_1 = require("../../shouldFire");
const DefaultMap_1 = require("../DefaultMap");
const CustomCallback_1 = require("../private/CustomCallback");
const v = {
    run: {
        playersStatMap: new DefaultMap_1.DefaultMap(() => new Map()),
    },
};
class PostPlayerChangeStat extends CustomCallback_1.CustomCallback {
    v = v;
    constructor() {
        super();
        this.customCallbacksUsed = [
            [
                ModCallbackCustom_1.ModCallbackCustom.POST_PEFFECT_UPDATE_REORDERED,
                this.postPEffectReordered,
            ],
        ];
    }
    shouldFire = shouldFire_1.shouldFirePlayer;
    // ModCallbackCustom.POST_PEFFECT_UPDATE_REORDERED
    postPEffectReordered = (player) => {
        // We call the "getPlayerIndex" function with the "differentiateForgottenAndSoul" argument. If
        // we don't differentiate between The Forgotten and The Soul, the callback will fire every time
        // the player switches between the two.
        const playerIndex = (0, playerIndex_1.getPlayerIndex)(player, true);
        const playerStatMap = v.run.playersStatMap.getAndSetDefault(playerIndex);
        for (const statType of cachedEnumValues_1.PLAYER_STAT_VALUES) {
            const storedStatValue = playerStatMap.get(statType);
            const currentStatValue = (0, stats_1.getPlayerStat)(player, statType);
            playerStatMap.set(statType, currentStatValue);
            if (storedStatValue === undefined) {
                continue;
            }
            if (!statEquals(storedStatValue, currentStatValue)) {
                const isNumberStat = (0, types_1.isNumber)(storedStatValue) && (0, types_1.isNumber)(currentStatValue);
                const difference = isNumberStat
                    ? currentStatValue - storedStatValue
                    : 0;
                this.fire(player, statType, difference, storedStatValue, currentStatValue);
            }
        }
    };
}
exports.PostPlayerChangeStat = PostPlayerChangeStat;
function statEquals(oldValue, newValue) {
    const isNumberStat = (0, types_1.isNumber)(oldValue) && (0, types_1.isNumber)(newValue);
    if (isNumberStat) {
        return oldValue === newValue;
    }
    const isBooleanStat = (0, types_1.isBoolean)(oldValue) && (0, types_1.isBoolean)(newValue);
    if (isBooleanStat) {
        return oldValue === newValue;
    }
    const isBitSet128Stat = (0, bitSet128_1.isBitSet128)(oldValue) && (0, bitSet128_1.isBitSet128)(newValue);
    if (isBitSet128Stat) {
        return oldValue === newValue; // The class has the "__eq" meta-method.
    }
    const isColorStat = (0, color_1.isColor)(oldValue) && (0, color_1.isColor)(newValue);
    if (isColorStat) {
        return (0, color_1.colorEquals)(oldValue, newValue);
    }
    const isVectorStat = (0, vector_1.isVector)(oldValue) && (0, vector_1.isVector)(newValue);
    if (isVectorStat) {
        return (0, vector_1.vectorEquals)(oldValue, newValue);
    }
    error('Failed to determine the type of a stat in the "POST_PLAYER_CHANGE_STAT" callback.');
}
