"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.RoomHistory = void 0;
const cachedClasses_1 = require("../../../core/cachedClasses");
const decorators_1 = require("../../../decorators");
const ModCallbackCustom_1 = require("../../../enums/ModCallbackCustom");
const dimensions_1 = require("../../../functions/dimensions");
const roomData_1 = require("../../../functions/roomData");
const Feature_1 = require("../../private/Feature");
const v = {
    run: {
        roomHistory: [],
    },
};
class RoomHistory extends Feature_1.Feature {
    /** @internal */
    v = v;
    /** @internal */
    constructor() {
        super();
        this.customCallbacksUsed = [
            [ModCallbackCustom_1.ModCallbackCustom.POST_NEW_ROOM_EARLY, this.postNewRoomEarly],
        ];
    }
    // ModCallbackCustom.POST_NEW_ROOM_EARLY
    postNewRoomEarly = () => {
        const level = cachedClasses_1.game.GetLevel();
        const stage = level.GetStage();
        const stageType = level.GetStageType();
        const room = cachedClasses_1.game.GetRoom();
        const roomType = room.GetType();
        const seeds = cachedClasses_1.game.GetSeeds();
        const startSeedString = seeds.GetStartSeedString();
        const stageID = (0, roomData_1.getRoomStageID)();
        const dimension = (0, dimensions_1.getDimension)();
        const roomVariant = (0, roomData_1.getRoomVariant)();
        const roomSubType = (0, roomData_1.getRoomSubType)();
        const roomName = (0, roomData_1.getRoomName)();
        const roomGridIndex = (0, roomData_1.getRoomGridIndex)();
        const roomListIndex = (0, roomData_1.getRoomListIndex)();
        const roomVisitedCount = (0, roomData_1.getRoomVisitedCount)();
        const roomDescription = {
            startSeedString,
            stage,
            stageType,
            stageID,
            dimension,
            roomType,
            roomVariant,
            roomSubType,
            roomName,
            roomGridIndex,
            roomListIndex,
            roomVisitedCount,
        };
        v.run.roomHistory.push(roomDescription);
    };
    /**
     * Helper function to manually delete the last room description from the internal array. This is
     * useful if a mod needs to send the player to a room temporarily and the room should not count as
     * the player having traveled to that room.
     *
     * @public
     */
    deleteLastRoomDescription() {
        v.run.roomHistory.pop();
    }
    /**
     * Helper function to get the total number of rooms that the player has entered thus far on the
     * run. (Re-entering the same room will increment the number returned.)
     *
     * In order to use this function, you must upgrade your mod with `ISCFeature.ROOM_HISTORY`.
     *
     * @public
     */
    getNumRoomsEntered() {
        return v.run.roomHistory.length;
    }
    /**
     * Helper function to get information about all of the rooms that a player has visited thus far on
     * this run.
     *
     * In order to use this function, you must upgrade your mod with `ISCFeature.ROOM_HISTORY`.
     *
     * @public
     */
    getRoomHistory() {
        return v.run.roomHistory;
    }
    /**
     * Helper function to get information about the room that was previously visited.
     *
     * In the special case of only one room having been visited thus far (i.e. the starting room of
     * the run), the starting room will be returned.
     *
     * In order to use this function, you must upgrade your mod with `ISCFeature.ROOM_HISTORY`.
     *
     * @public
     */
    getPreviousRoomDescription() {
        const previousRoomDescription = v.run.roomHistory.at(-2);
        if (previousRoomDescription !== undefined) {
            return previousRoomDescription;
        }
        const startingRoomDescription = v.run.roomHistory[0];
        if (startingRoomDescription !== undefined) {
            return startingRoomDescription;
        }
        error("Failed to find a room description for any rooms thus far on this run.");
    }
    /**
     * Helper function to get information about the most recent room that is stored in the room
     * history array.
     *
     * This is useful in the `POST_ENTITY_REMOVE` callback; see the `isLeavingRoom` function.
     *
     * Note that this function can return undefined in the case where it is called on the first room
     * of the run.
     *
     * In order to use this function, you must upgrade your mod with `ISCFeature.ROOM_HISTORY`.
     *
     * @public
     */
    getLatestRoomDescription() {
        return v.run.roomHistory.at(-1);
    }
    /**
     * Helper function to detect if the player is on the first room of the room.
     *
     * @public
     */
    inFirstRoom() {
        return v.run.roomHistory.length === 1;
    }
    /**
     * Helper function to detect if the game is in the state where the room index has changed to a new
     * room, but the entities from the previous room are currently in the process of despawning. (At
     * this point, the `POST_NEW_ROOM` callback and the `POST_NEW_ROOM_EARLY` callback will not have
     * fired yet, and there will not be an entry in the room history array for the current room.)
     *
     * This function is intended to be used in the `POST_ENTITY_REMOVE` callback to detect when an
     * entity is despawning.
     *
     * In order to use this function, you must upgrade your mod with `ISCFeature.ROOM_HISTORY`.
     *
     * @public
     */
    isLeavingRoom() {
        const level = cachedClasses_1.game.GetLevel();
        const stage = level.GetStage();
        const stageType = level.GetStageType();
        const seeds = cachedClasses_1.game.GetSeeds();
        const startSeedString = seeds.GetStartSeedString();
        const roomListIndex = (0, roomData_1.getRoomListIndex)();
        const roomVisitedCount = (0, roomData_1.getRoomVisitedCount)();
        const latestRoomDescription = this.getLatestRoomDescription();
        // Sometimes, this function can be called in situations where entities from the previous run are
        // being despawned. If this is the case, then the room history will currently be empty.
        if (latestRoomDescription === undefined) {
            return false;
        }
        return (startSeedString !== latestRoomDescription.startSeedString ||
            stage !== latestRoomDescription.stage ||
            stageType !== latestRoomDescription.stageType ||
            roomListIndex !== latestRoomDescription.roomListIndex ||
            roomVisitedCount !== latestRoomDescription.roomVisitedCount);
    }
}
exports.RoomHistory = RoomHistory;
__decorate([
    decorators_1.Exported
], RoomHistory.prototype, "deleteLastRoomDescription", null);
__decorate([
    decorators_1.Exported
], RoomHistory.prototype, "getNumRoomsEntered", null);
__decorate([
    decorators_1.Exported
], RoomHistory.prototype, "getRoomHistory", null);
__decorate([
    decorators_1.Exported
], RoomHistory.prototype, "getPreviousRoomDescription", null);
__decorate([
    decorators_1.Exported
], RoomHistory.prototype, "getLatestRoomDescription", null);
__decorate([
    decorators_1.Exported
], RoomHistory.prototype, "inFirstRoom", null);
__decorate([
    decorators_1.Exported
], RoomHistory.prototype, "isLeavingRoom", null);
