"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.serializeIsaacAPIClass = exports.isSerializedIsaacAPIClass = exports.isCopyableIsaacAPIClass = exports.deserializeIsaacAPIClass = exports.copyIsaacAPIClass = void 0;
const isaacAPIClassTypeToBrand_1 = require("../objects/isaacAPIClassTypeToBrand");
const isaacAPIClassTypeToFunctions_1 = require("../objects/isaacAPIClassTypeToFunctions");
const isaacAPIClass_1 = require("./isaacAPIClass");
const types_1 = require("./types");
const utils_1 = require("./utils");
/**
 * Helper function to generically copy an Isaac API class without knowing what specific type of
 * class it is. (This is used by the save data manager.)
 *
 * For the list of supported classes, see the `CopyableIsaacAPIClassType` enum.
 */
function copyIsaacAPIClass(isaacAPIClass) {
    if (!(0, types_1.isUserdata)(isaacAPIClass)) {
        error(`Failed to copy an Isaac API class since the provided object was of type: ${typeof isaacAPIClass}`);
    }
    const isaacAPIClassType = (0, isaacAPIClass_1.getIsaacAPIClassName)(isaacAPIClass);
    (0, utils_1.assertDefined)(isaacAPIClassType, "Failed to copy an Isaac API class since it does not have a class type.");
    const copyableIsaacAPIClassType = isaacAPIClassType;
    const functions = isaacAPIClassTypeToFunctions_1.ISAAC_API_CLASS_TYPE_TO_FUNCTIONS[copyableIsaacAPIClassType];
    (0, utils_1.assertDefined)(functions, `Failed to copy an Isaac API class since the associated functions were not found for Isaac API class type: ${copyableIsaacAPIClassType}`);
    return functions.copy(isaacAPIClass);
}
exports.copyIsaacAPIClass = copyIsaacAPIClass;
/**
 * Helper function to generically deserialize an Isaac API class without knowing what specific type
 * of class it is. (This is used by the save data manager when reading data from the "save#.dat"
 * file.)
 *
 * For the list of supported classes, see the `CopyableIsaacAPIClassType` enum.
 */
function deserializeIsaacAPIClass(serializedIsaacAPIClass) {
    if (!(0, types_1.isTable)(serializedIsaacAPIClass)) {
        error(`Failed to deserialize an Isaac API class since the provided object was of type: ${typeof serializedIsaacAPIClass}`);
    }
    const copyableIsaacAPIClassType = getSerializedTableType(serializedIsaacAPIClass);
    (0, utils_1.assertDefined)(copyableIsaacAPIClassType, "Failed to deserialize an Isaac API class since a valid class type brand was not found.");
    const functions = isaacAPIClassTypeToFunctions_1.ISAAC_API_CLASS_TYPE_TO_FUNCTIONS[copyableIsaacAPIClassType];
    (0, utils_1.assertDefined)(functions, `Failed to deserialize an Isaac API class since the associated functions were not found for class type: ${copyableIsaacAPIClassType}`);
    return functions.deserialize(serializedIsaacAPIClass);
}
exports.deserializeIsaacAPIClass = deserializeIsaacAPIClass;
/**
 * In order to find out what type of serialized Isaac API class this is, we search through the
 * serialized table for brands.
 */
function getSerializedTableType(serializedIsaacAPIClass) {
    for (const [copyableIsaacAPIClassType, serializationBrand] of Object.entries(isaacAPIClassTypeToBrand_1.ISAAC_API_CLASS_TYPE_TO_BRAND)) {
        if (serializedIsaacAPIClass.has(serializationBrand)) {
            return copyableIsaacAPIClassType;
        }
    }
    return undefined;
}
/**
 * Helper function to generically check if a given object is a copyable Isaac API class. (This is
 * used by the save data manager when determining what is safe to copy.)
 *
 * For the list of supported classes, see the `CopyableIsaacAPIClassType` enum.
 */
function isCopyableIsaacAPIClass(object) {
    const allFunctions = Object.values(isaacAPIClassTypeToFunctions_1.ISAAC_API_CLASS_TYPE_TO_FUNCTIONS);
    const isFunctions = allFunctions.map((functions) => functions.is);
    return isFunctions.some((identityFunction) => identityFunction(object));
}
exports.isCopyableIsaacAPIClass = isCopyableIsaacAPIClass;
/**
 * Helper function to generically check if a given Lua table is a serialized Isaac API class. (This
 * is used by the save data manager when reading data from the "save#.dat" file.)
 *
 * For the list of supported classes, see the `CopyableIsaacAPIClassType` enum.
 */
function isSerializedIsaacAPIClass(object) {
    const allFunctions = Object.values(isaacAPIClassTypeToFunctions_1.ISAAC_API_CLASS_TYPE_TO_FUNCTIONS);
    const isSerializedFunctions = allFunctions.map((functions) => functions.isSerialized);
    return isSerializedFunctions.some((identityFunction) => identityFunction(object));
}
exports.isSerializedIsaacAPIClass = isSerializedIsaacAPIClass;
/**
 * Helper function to generically serialize an Isaac API class without knowing what specific type of
 * class it is. (This is used by the save data manager when writing data to the "save#.dat" file.)
 *
 * For the list of supported classes, see the `CopyableIsaacAPIClassType` enum.
 */
function serializeIsaacAPIClass(isaacAPIClass) {
    if (!(0, types_1.isUserdata)(isaacAPIClass)) {
        error(`Failed to serialize an Isaac API class since the provided object was of type: ${typeof isaacAPIClass}`);
    }
    const isaacAPIClassType = (0, isaacAPIClass_1.getIsaacAPIClassName)(isaacAPIClass);
    (0, utils_1.assertDefined)(isaacAPIClassType, "Failed to serialize an Isaac API class since it does not have a class name.");
    const copyableIsaacAPIClassType = isaacAPIClassType;
    const functions = isaacAPIClassTypeToFunctions_1.ISAAC_API_CLASS_TYPE_TO_FUNCTIONS[copyableIsaacAPIClassType];
    (0, utils_1.assertDefined)(functions, `Failed to serialize an Isaac API class since the associated functions were not found for class type: ${copyableIsaacAPIClassType}`);
    return functions.serialize(isaacAPIClass);
}
exports.serializeIsaacAPIClass = serializeIsaacAPIClass;
