/*
 * Application Insights JavaScript SDK - Core, 3.2.0
 * Copyright (c) Microsoft and contributors. All rights reserved.
 */


import { asString, isArray, isDefined, isNullOrUndefined, isObject, isPlainObject, isUndefined, objForEachKey, objHasOwn } from "@nevware21/ts-utils";
import { _DYN_BLK_VAL, _DYN_LENGTH, _DYN_RD_ONLY } from "../__DynamicConstants";
function _isConfigDefaults(value) {
    return (value && isObject(value) && (value.isVal || value.fb || objHasOwn(value, "v") || objHasOwn(value, "mrg") || objHasOwn(value, "ref") || value.set));
}
function _getDefault(dynamicHandler, theConfig, cfgDefaults) {
    var defValue;
    var isDefaultValid = cfgDefaults.dfVal || isDefined;
    // There is a fallback config key so try and grab that first
    if (theConfig && cfgDefaults.fb) {
        var fallbacks = cfgDefaults.fb;
        if (!isArray(fallbacks)) {
            fallbacks = [fallbacks];
        }
        for (var lp = 0; lp < fallbacks[_DYN_LENGTH /* @min:%2elength */]; lp++) {
            var fallback = fallbacks[lp];
            var fbValue = theConfig[fallback];
            if (isDefaultValid(fbValue)) {
                defValue = fbValue;
            }
            else if (dynamicHandler) {
                // Needed to ensure that the fallback value (and potentially) new field is also dynamic even if null/undefined
                fbValue = dynamicHandler.cfg[fallback];
                if (isDefaultValid(fbValue)) {
                    defValue = fbValue;
                }
                // Needed to ensure that the fallback value (and potentially) new field is also dynamic even if null/undefined
                dynamicHandler.set(dynamicHandler.cfg, asString(fallback), fbValue);
            }
            if (isDefaultValid(defValue)) {
                // We have a valid default so break out of the look
                break;
            }
        }
    }
    // If the value is still not defined and we have a default value then use that
    if (!isDefaultValid(defValue) && isDefaultValid(cfgDefaults.v)) {
        defValue = cfgDefaults.v;
    }
    return defValue;
}
/**
 * Recursively resolve the default value
 * @param dynamicHandler
 * @param theConfig
 * @param cfgDefaults
 * @returns
 */
function _resolveDefaultValue(dynamicHandler, theConfig, cfgDefaults) {
    var theValue = cfgDefaults;
    if (cfgDefaults && _isConfigDefaults(cfgDefaults)) {
        theValue = _getDefault(dynamicHandler, theConfig, cfgDefaults);
    }
    if (theValue) {
        if (_isConfigDefaults(theValue)) {
            theValue = _resolveDefaultValue(dynamicHandler, theConfig, theValue);
        }
        var newValue_1;
        if (isArray(theValue)) {
            newValue_1 = [];
            newValue_1[_DYN_LENGTH /* @min:%2elength */] = theValue[_DYN_LENGTH /* @min:%2elength */];
        }
        else if (isPlainObject(theValue)) {
            newValue_1 = {};
        }
        if (newValue_1) {
            objForEachKey(theValue, function (key, value) {
                if (value && _isConfigDefaults(value)) {
                    value = _resolveDefaultValue(dynamicHandler, theConfig, value);
                }
                newValue_1[key] = value;
            });
            theValue = newValue_1;
        }
    }
    return theValue;
}
/**
 * Applies the default value on the config property and makes sure that it's dynamic
 * @param theConfig
 * @param name
 * @param defaultValue
 */
export function _applyDefaultValue(dynamicHandler, theConfig, name, defaultValue) {
    // Resolve the initial config value from the provided value or use the defined default
    var isValid;
    var setFn;
    var defValue;
    var cfgDefaults = defaultValue;
    var mergeDf;
    var reference;
    var readOnly;
    var blkDynamicValue;
    if (_isConfigDefaults(cfgDefaults)) {
        // looks like a IConfigDefault
        isValid = cfgDefaults.isVal;
        setFn = cfgDefaults.set;
        readOnly = cfgDefaults[_DYN_RD_ONLY /* @min:%2erdOnly */];
        blkDynamicValue = cfgDefaults[_DYN_BLK_VAL /* @min:%2eblkVal */];
        mergeDf = cfgDefaults.mrg;
        reference = cfgDefaults.ref;
        if (!reference && isUndefined(reference)) {
            reference = !!mergeDf;
        }
        defValue = _getDefault(dynamicHandler, theConfig, cfgDefaults);
    }
    else {
        defValue = defaultValue;
    }
    if (blkDynamicValue) {
        // Mark the property so that any value assigned will be blocked from conversion, we need to do this
        // before assigning or fetching the value to ensure it's not converted
        dynamicHandler[_DYN_BLK_VAL /* @min:%2eblkVal */](theConfig, name);
    }
    // Set the value to the default value;
    var theValue;
    var usingDefault = true;
    var cfgValue = theConfig[name];
    // try and get and user provided values
    if (cfgValue || !isNullOrUndefined(cfgValue)) {
        // Use the defined theConfig[name] value
        theValue = cfgValue;
        usingDefault = false;
        // The values are different and we have a special default value check, which is used to
        // override config values like empty strings to continue using the default
        if (isValid && theValue !== defValue && !isValid(theValue)) {
            theValue = defValue;
            usingDefault = true;
        }
        if (setFn) {
            theValue = setFn(theValue, defValue, theConfig);
            usingDefault = theValue === defValue;
        }
    }
    if (!usingDefault) {
        if (isPlainObject(theValue) || isArray(defValue)) {
            // we are using the user supplied value and it's an object
            if (mergeDf && defValue && (isPlainObject(defValue) || isArray(defValue))) {
                // Resolve/apply the defaults
                objForEachKey(defValue, function (dfName, dfValue) {
                    // Sets the value and makes it dynamic (if it doesn't already exist)
                    _applyDefaultValue(dynamicHandler, theValue, dfName, dfValue);
                });
            }
        }
    }
    else if (defValue) {
        // Just resolve the default
        theValue = _resolveDefaultValue(dynamicHandler, theConfig, defValue);
    }
    else {
        theValue = defValue;
    }
    // if (theValue && usingDefault && (isPlainObject(theValue) || isArray(theValue))) {
    //     theValue = _cfgDeepCopy(theValue);
    // }
    // Needed to ensure that the (potentially) new field is dynamic even if null/undefined
    dynamicHandler.set(theConfig, name, theValue);
    if (reference) {
        dynamicHandler.ref(theConfig, name);
    }
    if (readOnly) {
        dynamicHandler[_DYN_RD_ONLY /* @min:%2erdOnly */](theConfig, name);
    }
}
//# sourceMappingURL=ConfigDefaults.js.map