"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.logPtrHashes = exports.logPtrHash = exports.logGridEntity = exports.logGridEntities = exports.logEntity = exports.logEntities = exports.logAllGridEntities = exports.logAllEntities = void 0;
const isaac_typescript_definitions_1 = require("isaac-typescript-definitions");
const ReadonlySet_1 = require("../types/ReadonlySet");
const entities_1 = require("./entities");
const gridEntities_1 = require("./gridEntities");
const log_1 = require("./log");
const IGNORE_EFFECT_VARIANTS = new ReadonlySet_1.ReadonlySet([
    isaac_typescript_definitions_1.EffectVariant.BLOOD_EXPLOSION,
    isaac_typescript_definitions_1.EffectVariant.BLOOD_PARTICLE,
    isaac_typescript_definitions_1.EffectVariant.TINY_BUG,
    isaac_typescript_definitions_1.EffectVariant.TINY_FLY,
    isaac_typescript_definitions_1.EffectVariant.WATER_DROPLET,
    isaac_typescript_definitions_1.EffectVariant.WORM,
    isaac_typescript_definitions_1.EffectVariant.WALL_BUG,
    isaac_typescript_definitions_1.EffectVariant.FALLING_EMBER,
    isaac_typescript_definitions_1.EffectVariant.LIGHT,
    isaac_typescript_definitions_1.EffectVariant.MIST,
    isaac_typescript_definitions_1.EffectVariant.BACKDROP_DECORATION,
    isaac_typescript_definitions_1.EffectVariant.TADPOLE, // 158
]);
/** Helper function for printing out every entity (or filtered entity) in the current room. */
function logAllEntities(includeBackgroundEffects, entityTypeFilter) {
    let msg = "Entities in the room";
    if (entityTypeFilter !== undefined) {
        msg += ` (filtered to entity type ${entityTypeFilter})`;
    }
    else if (!includeBackgroundEffects) {
        msg += " (not including background effects)";
    }
    msg += ":\n";
    const entities = (0, entities_1.getEntities)();
    let numMatchedEntities = 0;
    for (const [i, entity] of entities.entries()) {
        // If a filter was specified, exclude all entities outside of the filter.
        if (entityTypeFilter !== undefined && entity.Type !== entityTypeFilter) {
            continue;
        }
        const effect = entity.ToEffect();
        if (!includeBackgroundEffects &&
            effect !== undefined &&
            IGNORE_EFFECT_VARIANTS.has(effect.Variant)) {
            continue;
        }
        msg += getEntityLogLine(entity, i + 1);
        numMatchedEntities++;
    }
    const zeroText = "(no entities matched)";
    const oneOrMoreText = `(${numMatchedEntities} total ${numMatchedEntities === 1 ? "entity" : "entities"})`;
    const text = numMatchedEntities === 0 ? zeroText : oneOrMoreText;
    msg += `${text}\n`;
    // We must log each line because otherwise the message can get truncated.
    for (const line of msg.trim().split("\n")) {
        (0, log_1.log)(line);
    }
}
exports.logAllEntities = logAllEntities;
/**
 * Helper function for printing out every grid entity (or filtered grid entity) in the current room.
 *
 * @param includeWalls Optional. Whether oto log the walls. Default is false.
 * @param gridEntityTypeFilter Optional. If specified, will only log the given `GridEntityType`.
 *                             Default is undefined.
 */
function logAllGridEntities(includeWalls = false, gridEntityTypeFilter) {
    let msg = "Grid entities in the room";
    if (gridEntityTypeFilter !== undefined) {
        msg += ` (filtered to grid entity type ${gridEntityTypeFilter})`;
    }
    else if (!includeWalls) {
        msg += " (not including walls)";
    }
    msg += ":\n";
    const gridEntities = (0, gridEntities_1.getGridEntities)();
    let numMatchedEntities = 0;
    for (const gridEntity of gridEntities) {
        const gridEntityIndex = gridEntity.GetGridIndex();
        const gridEntityType = gridEntity.GetType();
        // If a filter was specified, exclude all entities outside of the filter.
        if (gridEntityTypeFilter !== undefined &&
            gridEntityType !== gridEntityTypeFilter) {
            continue;
        }
        if (!includeWalls &&
            gridEntityType === isaac_typescript_definitions_1.GridEntityType.WALL &&
            gridEntityTypeFilter !== isaac_typescript_definitions_1.GridEntityType.WALL) {
            continue;
        }
        msg += getGridEntityLogLine(gridEntity, gridEntityIndex);
        numMatchedEntities++;
    }
    msg +=
        numMatchedEntities === 0
            ? "(no grid entities matched)\n"
            : `(${numMatchedEntities} total grid ${numMatchedEntities === 1 ? "entity" : "entities"})\n`;
    // We must log each line because otherwise the message can get truncated.
    for (const line of msg.trim().split("\n")) {
        (0, log_1.log)(line);
    }
}
exports.logAllGridEntities = logAllGridEntities;
/** Helper function for logging an array of specific entities. */
function logEntities(entities) {
    for (const entity of entities) {
        logEntity(entity);
    }
}
exports.logEntities = logEntities;
/** Helper function to log information about a specific entity. */
function logEntity(entity) {
    const msg = getEntityLogLine(entity);
    (0, log_1.log)(msg);
}
exports.logEntity = logEntity;
function getEntityLogLine(entity, num) {
    let msg = num === undefined ? "" : `${num}) `;
    msg += (0, entities_1.getEntityID)(entity);
    const bomb = entity.ToBomb();
    if (bomb !== undefined) {
        msg += ` (bomb - ${getBombVariantName(bomb)})`;
    }
    const effect = entity.ToEffect();
    if (effect !== undefined) {
        msg += ` (effect - ${getEffectVariantName(effect)}) (State: ${effect.State})`;
    }
    const familiar = entity.ToFamiliar();
    if (familiar !== undefined) {
        msg += ` (familiar - ${getFamiliarVariantName(familiar)}) (State: ${familiar.State})`;
    }
    const knife = entity.ToKnife();
    if (knife !== undefined) {
        msg += ` (knife - ${getKnifeVariantName(knife)})`;
    }
    const laser = entity.ToLaser();
    if (laser !== undefined) {
        msg += ` (laser - ${getLaserVariantName(laser)})`;
    }
    const npc = entity.ToNPC();
    if (npc !== undefined) {
        msg += ` (NPC - ${getEntityTypeName(npc)}) (State: ${npc.State})`;
    }
    const pickup = entity.ToPickup();
    if (pickup !== undefined) {
        msg += ` (pickup - ${getPickupVariantName(pickup)}) (State: ${pickup.State})`;
    }
    const player = entity.ToPlayer();
    if (player !== undefined) {
        msg += ` (player - ${getPlayerVariantName(player)})`;
    }
    const projectile = entity.ToProjectile();
    if (projectile !== undefined) {
        msg += ` (projectile - ${getProjectileVariantName(projectile)})`;
    }
    const tear = entity.ToTear();
    if (tear !== undefined) {
        msg += ` (tear - ${getTearVariantName(tear)})`;
    }
    msg += "\n";
    msg += `  - Index: ${entity.Index}\n`;
    msg += `  - InitSeed: ${entity.InitSeed}\n`;
    msg += `  - DropSeed: ${entity.DropSeed}\n`;
    msg += `  - Position: (${entity.Position.X}, ${entity.Position.Y})\n`;
    msg += `  - Velocity: (${entity.Velocity.X}, ${entity.Velocity.Y})\n`;
    msg += `  - HP: ${entity.HitPoints} / ${entity.MaxHitPoints}\n`;
    msg += `  - Parent: ${entity.Parent}\n`;
    msg += `  - Child: ${entity.Child}\n`;
    msg += `  - SpawnerEntity: ${entity.SpawnerEntity}\n`;
    msg += `  - SpawnerType / SpawnerVariant: ${entity.SpawnerType}.${entity.SpawnerVariant}\n`;
    msg += `  - FrameCount: ${entity.FrameCount}\n`;
    if (npc !== undefined) {
        msg += `  - CanShutDoors: ${npc.CanShutDoors}\n`;
    }
    return msg;
}
function getBombVariantName(bomb) {
    // Handle modded entities.
    const enumName = isaac_typescript_definitions_1.BombVariant[bomb.Variant];
    return enumName === undefined ? "unknown" : `BombVariant.${enumName}`;
}
function getEffectVariantName(effect) {
    // Handle modded entities.
    const enumName = isaac_typescript_definitions_1.EffectVariant[effect.Variant];
    return enumName === undefined ? "unknown" : `EffectVariant.${enumName}`;
}
function getFamiliarVariantName(familiar) {
    // Handle modded entities.
    const enumName = isaac_typescript_definitions_1.FamiliarVariant[familiar.Variant];
    return enumName === undefined ? "unknown" : `FamiliarVariant.${enumName}`;
}
function getKnifeVariantName(knife) {
    // Handle modded entities.
    const enumName = isaac_typescript_definitions_1.KnifeVariant[knife.Variant];
    return enumName === undefined ? "unknown" : `KnifeVariant.${enumName}`;
}
function getLaserVariantName(laser) {
    // Handle modded entities.
    const enumName = isaac_typescript_definitions_1.LaserVariant[laser.Variant];
    return enumName === undefined ? "unknown" : `LaserVariant.${enumName}`;
}
function getEntityTypeName(npc) {
    // Handle modded entities.
    const enumName = isaac_typescript_definitions_1.EntityType[npc.Type];
    return enumName === undefined ? "unknown" : `EntityType.${enumName}`;
}
function getPickupVariantName(pickup) {
    // Handle modded entities.
    const enumName = isaac_typescript_definitions_1.PickupVariant[pickup.Variant];
    return enumName === undefined ? "unknown" : `PickupVariant.${enumName}`;
}
function getPlayerVariantName(player) {
    // Handle modded entities.
    const enumName = isaac_typescript_definitions_1.PlayerVariant[player.Variant];
    return enumName === undefined ? "unknown" : `PlayerVariant.${enumName}`;
}
function getProjectileVariantName(projectile) {
    // Handle modded entities.
    const enumName = isaac_typescript_definitions_1.ProjectileVariant[projectile.Variant];
    return enumName === undefined ? "unknown" : `ProjectileVariant.${enumName}`;
}
function getTearVariantName(tear) {
    // Handle modded entities.
    const enumName = isaac_typescript_definitions_1.TearVariant[tear.Variant];
    return enumName === undefined ? "unknown" : `TearVariant.${enumName}`;
}
/** Helper function for logging an array of specific grid entities. */
function logGridEntities(gridEntities) {
    for (const gridEntity of gridEntities) {
        logGridEntity(gridEntity);
    }
}
exports.logGridEntities = logGridEntities;
/** Helper function for log information about a specific grid entity. */
function logGridEntity(gridEntity) {
    const msg = getGridEntityLogLine(gridEntity);
    (0, log_1.log)(msg);
}
exports.logGridEntity = logGridEntity;
function getGridEntityLogLine(gridEntity, num) {
    const gridEntityDesc = gridEntity.GetSaveState();
    let msg = num === undefined ? "" : `${num}) `;
    msg += (0, gridEntities_1.getGridEntityID)(gridEntity);
    const door = gridEntity.ToDoor();
    if (door !== undefined) {
        msg += " (door)";
    }
    const pit = gridEntity.ToPit();
    if (pit !== undefined) {
        msg += " (pit)";
    }
    const poop = gridEntity.ToPoop();
    if (poop !== undefined) {
        msg += " (poop)";
    }
    const pressurePlate = gridEntity.ToPressurePlate();
    if (pressurePlate !== undefined) {
        msg += " (pressurePlate)";
    }
    const rock = gridEntity.ToRock();
    if (rock !== undefined) {
        msg += " (rock)";
    }
    const spikes = gridEntity.ToSpikes();
    if (spikes !== undefined) {
        msg += " (spikes)";
    }
    const tnt = gridEntity.ToTNT();
    if (tnt !== undefined) {
        msg += " (TNT)";
    }
    msg += `  - State: ${gridEntity.State}\n`;
    msg += `  - VarData: ${gridEntity.VarData}\n`;
    msg += `  - Position: (${gridEntity.Position.X}, ${gridEntity.Position.Y})\n`;
    msg += `  - SpawnSeed: ${gridEntityDesc.SpawnSeed}\n`;
    msg += `  - VariableSeed: ${gridEntityDesc.VariableSeed})\n`;
    if (door !== undefined) {
        msg += `  - Slot: ${door.Slot}\n`;
        msg += `  - Direction: ${door.Direction}\n`;
        msg += `  - TargetRoomIndex: ${door.TargetRoomIndex}\n`;
        msg += `  - TargetRoomType: ${door.TargetRoomType}\n`;
    }
    return msg;
}
/**
 * Helper function to log information about the entity that corresponding to a pointer hash. (Only
 * use this when debugging, since retrieving the corresponding entity is expensive.)
 */
function logPtrHash(ptrHash) {
    (0, log_1.log)(`PtrHash: ${ptrHash}`);
    const entity = (0, entities_1.getEntityFromPtrHash)(ptrHash);
    if (entity === undefined) {
        (0, log_1.log)("No corresponding entity found.");
    }
    else {
        logEntity(entity);
    }
}
exports.logPtrHash = logPtrHash;
/**
 * Helper function to log information about the entity that corresponding to one or more pointer
 * hashes. (Only use this when debugging, since retrieving the corresponding entity is expensive.)
 */
function logPtrHashes(ptrHashes) {
    for (const ptrHash of ptrHashes) {
        logPtrHash(ptrHash);
    }
}
exports.logPtrHashes = logPtrHashes;
