"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PlayerCollectibleTracking = void 0;
const decorators_1 = require("../../../decorators");
const ModCallbackCustom_1 = require("../../../enums/ModCallbackCustom");
const array_1 = require("../../../functions/array");
const collectibles_1 = require("../../../functions/collectibles");
const playerDataStructures_1 = require("../../../functions/playerDataStructures");
const DefaultMap_1 = require("../../DefaultMap");
const Feature_1 = require("../../private/Feature");
const v = {
    run: {
        playersCollectibleTypes: new DefaultMap_1.DefaultMap(() => []),
    },
};
class PlayerCollectibleTracking extends Feature_1.Feature {
    /** @internal */
    v = v;
    /** @internal */
    constructor() {
        super();
        this.customCallbacksUsed = [
            [
                ModCallbackCustom_1.ModCallbackCustom.POST_PLAYER_COLLECTIBLE_ADDED,
                this.postPlayerCollectibleAdded,
            ],
            [
                ModCallbackCustom_1.ModCallbackCustom.POST_PLAYER_COLLECTIBLE_REMOVED,
                this.postPlayerCollectibleRemoved,
            ],
        ];
    }
    // ModCallbackCustom.POST_PLAYER_COLLECTIBLE_ADDED
    postPlayerCollectibleAdded = (player, collectibleType) => {
        const collectibleTypes = (0, playerDataStructures_1.defaultMapGetPlayer)(v.run.playersCollectibleTypes, player, player);
        collectibleTypes.push(collectibleType);
    };
    // ModCallbackCustom.POST_PLAYER_COLLECTIBLE_REMOVED
    postPlayerCollectibleRemoved = (player, collectibleType) => {
        const collectibleTypes = (0, playerDataStructures_1.defaultMapGetPlayer)(v.run.playersCollectibleTypes, player, player);
        (0, array_1.arrayRemoveInPlace)(collectibleTypes, collectibleType);
    };
    /**
     * Helper function to get all of the collectible types that the player has gotten so far on this
     * run, in order.
     *
     * In the case of items given on the first frame of the run or the case where the player rerolls
     * their build in the middle of the run (e.g. with D4), the order of the collectible types will
     * not correspond to the order that the items were actually given to the player. In this case, the
     * order will be from the lowest `CollectibleType` to the highest.
     *
     * Under the hood, this feature works by tracking the number of collectibles that a player has on
     * every frame. Thus, in a situation where a collectible was both added and removed to the player
     * on the same frame, the amount of total collectibles would stay the same, and the collectible
     * types would not be updated. In vanilla, this situation would never happen, but another mod
     * might do this for some reason. (With that said, the next time that a collectible is normally
     * added or removed, it would trigger a re-scan, and the previous changes would be picked up.)
     *
     * In order to use this function, you must upgrade your mod with
     * `ISCFeature.PLAYER_COLLECTIBLE_TRACKING`.
     *
     * @param player The player to get the collectible types for.
     * @param includeActiveCollectibles Optional. If true, will include all active collectibles.
     *                                Default is true.
     * @public
     */
    getPlayerCollectibleTypes(player, includeActiveCollectibles = true) {
        const collectibleTypes = (0, playerDataStructures_1.defaultMapGetPlayer)(v.run.playersCollectibleTypes, player, player);
        if (includeActiveCollectibles) {
            return collectibleTypes;
        }
        return collectibleTypes.filter((collectibleType) => !(0, collectibles_1.isActiveCollectible)(collectibleType));
    }
    /**
     * Helper function to get the last passive collectible type that the player picked up. In most
     * cases, this will be the passive that would be removed if the player used Clicker.
     *
     * Returns undefined if the player does not have any passive collectibles.
     *
     * In order to use this function, you must upgrade your mod with
     * `ISCFeature.PLAYER_COLLECTIBLE_TRACKING`.
     *
     * @public
     */
    getPlayerLastPassiveCollectibleType(player) {
        const collectibleTypes = this.getPlayerCollectibleTypes(player, false);
        return collectibleTypes.at(-1);
    }
}
exports.PlayerCollectibleTracking = PlayerCollectibleTracking;
__decorate([
    decorators_1.Exported
], PlayerCollectibleTracking.prototype, "getPlayerCollectibleTypes", null);
__decorate([
    decorators_1.Exported
], PlayerCollectibleTracking.prototype, "getPlayerLastPassiveCollectibleType", null);
