"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.runDeepCopyTests = void 0;
const DefaultMap_1 = require("../classes/DefaultMap");
const SerializationBrand_1 = require("../enums/private/SerializationBrand");
const SerializationType_1 = require("../enums/SerializationType");
const array_1 = require("./array");
const deepCopy_1 = require("./deepCopy");
const log_1 = require("./log");
const tstlClass_1 = require("./tstlClass");
const types_1 = require("./types");
/**
 * Run the suite of tests that prove that the "deepCopy" helper function works properly.
 *
 * This function is only useful if you are troubleshooting the "deepCopy" function.
 */
function runDeepCopyTests() {
    copiedObjectIsTable();
    copiedObjectHasKeyAndValueString();
    copiedTableHasKeyAndValueNumber();
    copiedTableDoesNotCoerceTypes();
    copiedObjectHasNoReferencesForPrimitivesForward();
    copiedObjectHasNoReferencesForPrimitivesBackward();
    copiedObjectHasNoReferencesForArray();
    copiedObjectHasChildObject();
    copiedMapIsMap();
    copiedMapHasValue();
    copiedSetIsSet();
    copiedSetHasValue();
    copiedMapHasChildMap();
    copiedDefaultMapHasChildDefaultMap();
    copiedDefaultMapHasBrand();
    copiedSerializedMapHasStringKey();
    copiedSerializedMapHasNumberKey();
    copiedSerializedDefaultMapHasStringKey();
    copiedSerializedDefaultMapHasNumberKey();
    const successText = "All deep copy tests passed!";
    (0, log_1.log)(successText);
    print(successText);
}
exports.runDeepCopyTests = runDeepCopyTests;
function copiedObjectIsTable() {
    const oldObject = {
        abc: "def",
    };
    const newObject = (0, deepCopy_1.deepCopy)(oldObject, SerializationType_1.SerializationType.NONE, "copiedObjectIsTable");
    if (!(0, types_1.isTable)(newObject)) {
        error(`The copied object had a type of: ${typeof newObject}`);
    }
}
function copiedObjectHasKeyAndValueString() {
    const keyToLookFor = "abc";
    const valueToLookFor = "def";
    const oldObject = {
        abc: valueToLookFor,
    };
    const newObject = (0, deepCopy_1.deepCopy)(oldObject, SerializationType_1.SerializationType.NONE, "copiedObjectHasKeyAndValueString");
    const value = newObject[keyToLookFor];
    if (value === undefined) {
        error(`The copied object did not have a key of: ${keyToLookFor}`);
    }
    if (!(0, types_1.isString)(value)) {
        error(`The copied object had a value type of: ${typeof value}`);
    }
    if (value !== valueToLookFor) {
        error(`The copied object had a value of: ${value}`);
    }
}
function copiedTableHasKeyAndValueNumber() {
    const keyToLookFor = 123;
    const valueToLookFor = 456;
    const oldTable = new LuaMap();
    oldTable.set(keyToLookFor, valueToLookFor);
    const newTable = (0, deepCopy_1.deepCopy)(oldTable, SerializationType_1.SerializationType.NONE, "copiedTableHasKeyAndValueNumber");
    const value = newTable.get(keyToLookFor);
    if (value === undefined) {
        error(`The copied object did not have a key of: ${keyToLookFor}`);
    }
    if (!(0, types_1.isNumber)(value)) {
        error(`The copied object had a value type of: ${typeof value}`);
    }
    if (value !== valueToLookFor) {
        error(`The copied object had a value of: ${value}`);
    }
}
function copiedTableDoesNotCoerceTypes() {
    const keyToLookFor = 123;
    const valueToLookFor = 456;
    const oldTable = new LuaMap();
    oldTable.set(keyToLookFor, valueToLookFor);
    const newTable = (0, deepCopy_1.deepCopy)(oldTable, SerializationType_1.SerializationType.NONE, "copiedTableDoesNotCoerceTypes");
    const keyString = tostring(keyToLookFor);
    const valueString = tostring(valueToLookFor);
    const valueFromString = newTable.get(keyString);
    if (valueFromString !== undefined) {
        error(`The copied object had a string key of: ${keyString}`);
    }
    const value = newTable.get(keyToLookFor);
    if (value === valueString) {
        error(`The copied object had a value that incorrectly matched the string of: ${valueString}`);
    }
}
/** In this context, a reference is a pointer. */
function copiedObjectHasNoReferencesForPrimitivesForward() {
    const originalStringValue = "abcdef";
    const originalNumberValue = 123;
    const oldObject = {
        abc: originalStringValue,
        def: originalNumberValue,
    };
    const newObject = (0, deepCopy_1.deepCopy)(oldObject, SerializationType_1.SerializationType.NONE, "copiedObjectHasNoReferencesForPrimitivesForward");
    oldObject.abc = "newValue";
    if (oldObject.abc === newObject.abc) {
        error("The copied object has a string reference going forward.");
    }
    oldObject.def = 456;
    if (oldObject.def === newObject.def) {
        error("The copied object has a number reference going forward.");
    }
}
function copiedObjectHasNoReferencesForPrimitivesBackward() {
    const originalStringValue = "abcdef";
    const originalNumberValue = 123;
    const oldObject = {
        abc: originalStringValue,
        def: originalNumberValue,
    };
    const newObject = (0, deepCopy_1.deepCopy)(oldObject, SerializationType_1.SerializationType.NONE, "copiedObjectHasNoReferencesForPrimitivesBackward");
    newObject.abc = "newValue";
    if (newObject.abc === oldObject.abc) {
        error("The copied object has a string reference going backward.");
    }
    newObject.def = 456;
    if (newObject.def === oldObject.def) {
        error("The copied object has a number reference going backward.");
    }
}
/** In this context, a reference is a pointer. */
function copiedObjectHasNoReferencesForArray() {
    const oldObject = {
        abc: [1, 2, 3],
    };
    const newObject = (0, deepCopy_1.deepCopy)(oldObject, SerializationType_1.SerializationType.NONE, "copiedObjectHasNoReferencesForArray");
    if (oldObject.abc === newObject.abc) {
        error("The copied object has the same point to the child array.");
    }
    if (!(0, array_1.arrayEquals)(oldObject.abc, newObject.abc)) {
        error("The copied object does not have an equal array.");
    }
    oldObject.abc[0]++;
    if ((0, array_1.arrayEquals)(oldObject.abc, newObject.abc)) {
        error("The copied object has an equal array after a modification to the old array.");
    }
    oldObject.abc[0]--;
    newObject.abc[0]++;
    if ((0, array_1.arrayEquals)(oldObject.abc, newObject.abc)) {
        error("The copied object has an equal array after a modification to the new array.");
    }
    newObject.abc[0]--;
}
function copiedObjectHasChildObject() {
    const childObjectIndex = "abc";
    const keyToLookFor = "def";
    const valueToLookFor = "ghi";
    const oldObject = {
        abc: {
            def: valueToLookFor,
        },
    };
    const newObject = (0, deepCopy_1.deepCopy)(oldObject, SerializationType_1.SerializationType.NONE, "copiedObjectHasChildObject");
    const childObject = newObject[childObjectIndex];
    if (childObject === undefined) {
        error(`Failed to find the child object at index: ${childObjectIndex}`);
    }
    if (!(0, types_1.isTable)(childObject)) {
        error(`The copied child object had a type of: ${typeof childObject}`);
    }
    const value = childObject[keyToLookFor];
    if (value === undefined) {
        error(`The child object did not have a key of: ${keyToLookFor}`);
    }
    if (!(0, types_1.isString)(value)) {
        error(`The child object value had a type of: ${typeof value}`);
    }
    if (value !== valueToLookFor) {
        error(`The child object value was: ${valueToLookFor}`);
    }
}
function copiedMapIsMap() {
    const keyToLookFor = "abc";
    const valueToLookFor = "def";
    const oldMap = new Map();
    oldMap.set(keyToLookFor, valueToLookFor);
    const newMap = (0, deepCopy_1.deepCopy)(oldMap, SerializationType_1.SerializationType.NONE, "copiedMapIsMap");
    if (!(0, tstlClass_1.isTSTLMap)(newMap)) {
        error(`The copied Map was not a Map and has a type of: ${typeof newMap}`);
    }
}
function copiedMapHasValue() {
    const keyToLookFor = "abc";
    const valueToLookFor = "def";
    const oldMap = new Map();
    oldMap.set(keyToLookFor, valueToLookFor);
    const newMap = (0, deepCopy_1.deepCopy)(oldMap, SerializationType_1.SerializationType.NONE, "copiedMapHasValue");
    if (!(0, tstlClass_1.isTSTLMap)(newMap)) {
        error(`The copied Map was not a Map and has a type of: ${typeof newMap}`);
    }
    const value = newMap.get(keyToLookFor);
    if (value === undefined) {
        error(`The copied Map did not have a key of: ${keyToLookFor}`);
    }
    if (value !== valueToLookFor) {
        error(`The copied Map did not have a value of: ${valueToLookFor}`);
    }
}
function copiedSetIsSet() {
    const valueToLookFor = "abc";
    const oldSet = new Set();
    oldSet.add(valueToLookFor);
    const newSet = (0, deepCopy_1.deepCopy)(oldSet, SerializationType_1.SerializationType.NONE, "copiedSetIsSet");
    if (!(0, tstlClass_1.isTSTLSet)(newSet)) {
        error(`The copied Set was not a Set and has a type of: ${typeof newSet}`);
    }
}
function copiedSetHasValue() {
    const valueToLookFor = "abc";
    const oldSet = new Set();
    oldSet.add(valueToLookFor);
    const newSet = (0, deepCopy_1.deepCopy)(oldSet, SerializationType_1.SerializationType.NONE, "copiedSetHasValue");
    if (!(0, tstlClass_1.isTSTLSet)(newSet)) {
        error(`The copied Set was not a Set and has a type of: ${typeof newSet}`);
    }
    const hasValue = newSet.has(valueToLookFor);
    if (!hasValue) {
        error(`The copied Set did not have a value of: ${valueToLookFor}`);
    }
}
function copiedMapHasChildMap() {
    const childMapKey = 123;
    const childMapValue = 456;
    const oldChildMap = new Map();
    oldChildMap.set(childMapKey, childMapValue);
    const keyToLookFor = "childMap";
    const oldMap = new Map();
    oldMap.set(keyToLookFor, oldChildMap);
    const newMap = (0, deepCopy_1.deepCopy)(oldMap, SerializationType_1.SerializationType.NONE, "copiedMapHasChildMap");
    if (!(0, tstlClass_1.isTSTLMap)(newMap)) {
        error(`The copied Map was not a Map and had a type of: ${typeof newMap}`);
    }
    const newChildMap = newMap.get(keyToLookFor);
    if (newChildMap === undefined) {
        error(`The copied Map did not have a child map at key: ${keyToLookFor}`);
    }
    if (!(0, tstlClass_1.isTSTLMap)(newChildMap)) {
        error(`The copied child Map was not a Map and had a type of: ${typeof newChildMap}`);
    }
    const value = newChildMap.get(childMapKey);
    if (value === undefined) {
        error(`The copied child Map did not have a key of: ${childMapKey}`);
    }
    if (value !== childMapValue) {
        error(`The copied child Map did not have a value of: ${childMapValue}`);
    }
}
function copiedDefaultMapHasChildDefaultMap() {
    const parentMapKey = "abc";
    const childMapKey1 = 123;
    const childMapKey2 = 456;
    const childMapDefaultValue = 1;
    const childMapCustomValue = 2;
    const oldParentMap = new DefaultMap_1.DefaultMap(() => new DefaultMap_1.DefaultMap(childMapDefaultValue));
    const oldChildMap = oldParentMap.getAndSetDefault(parentMapKey);
    oldChildMap.getAndSetDefault(childMapKey1);
    oldChildMap.set(childMapKey2, childMapCustomValue);
    const newParentMap = (0, deepCopy_1.deepCopy)(oldParentMap, SerializationType_1.SerializationType.NONE, "copiedDefaultMapHasChildDefaultMap");
    if (!(0, tstlClass_1.isDefaultMap)(newParentMap)) {
        error(`The copied parent DefaultMap was not a DefaultMap and had a type of: ${typeof newParentMap}`);
    }
    const newChildMap = newParentMap.get(parentMapKey);
    if (newChildMap === undefined) {
        error(`The copied DefaultMap did not have a child map at key: ${parentMapKey}`);
    }
    if (!(0, tstlClass_1.isDefaultMap)(newChildMap)) {
        error(`The copied child DefaultMap was not a DefaultMap and had a type of: ${typeof newChildMap}`);
    }
    const newChildMapValue1 = newChildMap.get(childMapKey1);
    if (newChildMapValue1 === undefined) {
        error(`The copied child DefaultMap did not have a key of: ${childMapKey1}`);
    }
    if (newChildMapValue1 !== childMapDefaultValue) {
        error(`The copied child Map did not have a default value of: ${childMapDefaultValue}`);
    }
    const newChildMapValue2 = newChildMap.get(childMapKey2);
    if (newChildMapValue2 === undefined) {
        error(`The copied child DefaultMap did not have a key of: ${childMapKey2}`);
    }
    if (newChildMapValue2 !== childMapCustomValue) {
        error(`The copied child Map did not have a custom value of: ${childMapCustomValue}`);
    }
}
function copiedDefaultMapHasBrand() {
    const oldDefaultValue = "foo";
    const oldDefaultMap = new DefaultMap_1.DefaultMap(oldDefaultValue);
    const newTable = (0, deepCopy_1.deepCopy)(oldDefaultMap, SerializationType_1.SerializationType.SERIALIZE, "copiedDefaultMapHasBrand");
    if (!(0, types_1.isTable)(newTable)) {
        error(`The copied DefaultMap was not a table and had a type of: ${typeof newTable}`);
    }
    if (!newTable.has(SerializationBrand_1.SerializationBrand.DEFAULT_MAP)) {
        error(`The copied DefaultMap does not have the brand: ${SerializationBrand_1.SerializationBrand.DEFAULT_MAP}`);
    }
}
function copiedSerializedMapHasStringKey() {
    const mapKey = "123";
    const mapValue = 456;
    const oldMap = new Map();
    oldMap.set(mapKey, mapValue);
    const serializedOldMap = (0, deepCopy_1.deepCopy)(oldMap, SerializationType_1.SerializationType.SERIALIZE, "copiedSerializedMapHasStringKey-serialize");
    const newTable = (0, deepCopy_1.deepCopy)(serializedOldMap, SerializationType_1.SerializationType.DESERIALIZE, "copiedSerializedMapHasStringKey-deserialize");
    const newMap = newTable;
    if (!newMap.has(mapKey)) {
        const keyType = type(mapKey);
        error(`The copied Map did not have a key of: ${mapKey} with type ${keyType}`);
    }
}
function copiedSerializedMapHasNumberKey() {
    const mapKey = 123;
    const mapValue = 456;
    const oldMap = new Map();
    oldMap.set(mapKey, mapValue);
    const serializedOldMap = (0, deepCopy_1.deepCopy)(oldMap, SerializationType_1.SerializationType.SERIALIZE, "copiedSerializedMapHasNumberKey-serialize");
    const newTable = (0, deepCopy_1.deepCopy)(serializedOldMap, SerializationType_1.SerializationType.DESERIALIZE, "copiedSerializedMapHasNumberKey-deserialize");
    const newMap = newTable;
    if (!newMap.has(mapKey)) {
        const keyType = type(mapKey);
        error(`The copied Map did not have a key of: ${mapKey} with type ${keyType}`);
    }
}
function copiedSerializedDefaultMapHasStringKey() {
    const mapKey = "123";
    const oldDefaultMap = new DefaultMap_1.DefaultMap(456);
    oldDefaultMap.getAndSetDefault(mapKey);
    const serializedOldDefaultMap = (0, deepCopy_1.deepCopy)(oldDefaultMap, SerializationType_1.SerializationType.SERIALIZE, "copiedSerializedDefaultMapHasStringKey-serialize");
    const newTable = (0, deepCopy_1.deepCopy)(serializedOldDefaultMap, SerializationType_1.SerializationType.DESERIALIZE, "copiedSerializedDefaultMapHasStringKey-deserialize");
    const newDefaultMap = newTable;
    if (!newDefaultMap.has(mapKey)) {
        const keyType = type(mapKey);
        error(`The copied DefaultMap did not have a key of "${mapKey}" with type: ${keyType}`);
    }
}
function copiedSerializedDefaultMapHasNumberKey() {
    const mapKey = 123;
    const oldDefaultMap = new DefaultMap_1.DefaultMap(456);
    oldDefaultMap.getAndSetDefault(mapKey);
    const serializedOldDefaultMap = (0, deepCopy_1.deepCopy)(oldDefaultMap, SerializationType_1.SerializationType.SERIALIZE, "copiedSerializedDefaultMapHasNumberKey-serialize");
    const newTable = (0, deepCopy_1.deepCopy)(serializedOldDefaultMap, SerializationType_1.SerializationType.DESERIALIZE, "copiedSerializedDefaultMapHasNumberKey-deserialize");
    const newDefaultMap = newTable;
    if (!newDefaultMap.has(mapKey)) {
        const keyType = type(mapKey);
        error(`The copied DefaultMap did not have a key of: ${mapKey} with type ${keyType}`);
    }
}
