"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resolveReferences = resolveReferences;
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-explicit-any */
// This function works on any object, so we need to use any here
const util_1 = require("../util");
const _deep_map_values_1 = require("./_deep-map-values");
const get_prop_1 = require("./get-prop");
/**
 * Resolve all $use references in an object graph.
 * The $use syntax is relative to an entire object so
 * the developer must ensure they resolve the references
 * on the same graph they were defined on.
 * Put another way, you can't resolve references on a subset
 * of an object graph.
 * @param obj
 * @param ctx
 * @returns
 */
function resolveReferences(obj, ctx) {
    const keys = Object.keys(obj);
    ctx = ctx || (0, util_1.cloneObject)(obj);
    const newObject = keys.reduce(function (acc, currentKey) {
        // if the value is an array, map over it
        if (Array.isArray(obj[currentKey])) {
            acc[currentKey] = obj[currentKey].map((entry) => {
                return resolveReferences(entry, ctx);
            });
        }
        // if the value is an object, resolve it's references
        else if (obj[currentKey] &&
            (0, _deep_map_values_1._isObject)(obj[currentKey]) &&
            !(0, _deep_map_values_1._isDate)(obj[currentKey]) &&
            !(0, _deep_map_values_1._isRegExp)(obj[currentKey]) &&
            !(0, _deep_map_values_1._isFunction)(obj[currentKey])) {
            // if the value is an object it may be a reference
            if (obj[currentKey] && obj[currentKey].$use) {
                // use getProp to resolve the reference
                const useRef = (0, get_prop_1.getProp)(ctx, obj[currentKey].$use);
                if ((0, _deep_map_values_1._isObject)(useRef)) {
                    // references could contain references, so resolve them
                    acc[currentKey] = resolveReferences(useRef, ctx);
                }
                else {
                    acc[currentKey] = useRef;
                }
            }
            else {
                acc[currentKey] = resolveReferences(obj[currentKey], ctx);
            }
        }
        else {
            // assign value
            acc[currentKey] = obj[currentKey];
        }
        return acc;
    }, {});
    return newObject;
}
//# sourceMappingURL=resolveReferences.js.map