/*
 * Application Insights JavaScript SDK - Properties Plugin, 3.3.11
 * Copyright (c) Microsoft and contributors. All rights reserved.
 */
import { isNullOrUndefined, isObject, objExtend, objForEachKey, setValueByKey } from "@nevware21/ts-utils";
import { _DYN_FEATURE_OPT_IN } from "./__DynamicConstants";
/**
 * Delete a config key in the given cfg, if the config key exists in nonOverrideConfigs and its value is set to true
 * @param cfg - cfg to modify
 * @param nonOverrideConfigs - nonOverrideConfigs
 * @param curLevel - cur config level, starting at 0
 * @param maxLevel - max config level
 * @returns new copy of modified configs
 */
export function replaceByNonOverrideCfg(cfg, nonOverrideConfigs, curLevel, maxLevel) {
    try {
        var exceedMaxLevel = curLevel > maxLevel;
        if (exceedMaxLevel) {
            cfg = null;
        }
        var curCfg_1 = curLevel == 0 ? objExtend({}, cfg) : cfg; // only copy cfg at the begining level
        if (curCfg_1 && nonOverrideConfigs && !exceedMaxLevel) {
            objForEachKey(curCfg_1, function (key) {
                var nonOverrideVal = nonOverrideConfigs[key];
                if (!!nonOverrideVal) {
                    if (isObject(curCfg_1[key]) && isObject(nonOverrideVal)) {
                        curCfg_1[key] = replaceByNonOverrideCfg(curCfg_1[key], nonOverrideVal, ++curLevel, maxLevel);
                    }
                    else {
                        delete curCfg_1[key];
                    }
                }
            });
        }
        return curCfg_1;
    }
    catch (e) {
        // eslint-disable-next-line no-empty
    }
    // if errors happen, do nothing
    return cfg;
}
//                                                     CDN Mode, value = B (CDN value = B)
//                                |--------------------------------------------------------------------------|-----------|
//                                |                    | none        | disabled    | enabled     | forceOn   | forceOff  |
//                                | ------------------ | ----------- | ----------- | ----------- | --------- | --------- |
// | User Mode, value = A         | none               | none        | disabled    | enabled     | enabled   | disabled  |
// (user Value = A)               | disabled           | disabled    | disabled    | disabled    | enabled   | disabled  |
//                                | enabled            | enabled     | disabled    | enabled     | enabled   | disabled  |
//                                | none(blockCdn)     | none        | none        | none        | none      | none      |
//                                | disabled(blockCdn) | disabled    | disabled    | disabled    | disabled  | disabled  |
//                                | enabled(blockCdn)  | enabled     | enabled     | enabled     | enabled   | enabled   |
// This matrix identifies how feature based overrides are selected (if present)
//                                cdn Mode (cdn Value = B)
//                   |---------------------------------------------------------------------------|
//                   |                    | none     | disabled | enabled  | forceOn  | forceOff |
//                   | ------------------ | ---------| ---------| ---------| ---------|----------|
// | User Mode       | none               | A        | A        | A || B   | B || A   | B || A   |
// (user Value = A)  | disabled           | A        | A        | A        | B || A   | B || A   |
//                   | enabled            | A        | A        | A || B   | B || A   | B || A   |
//                   | none(blockCdn)     | A        | A        | A        | A        | A        |
//                   | disabled(blockCdn) | A        | A        | A        | A        | A        |
//                   | enabled(blockCdn)  | A        | A        | A        | A        | A        |
// Note:
// Where the "value" is an object (map) of encoded key/values which will be used to override the real configuration
// A = either the user supplied enable/disable value (via the `config.featureOptIn[name]`) or if not defined by the user the SDK defaults of the same.
// B = The enable/disable value obtained from the CDN for the named feature
// These are evaluated based on the above matrix to either
// - A (Always the user/sdk value)
// - B (Always the value from the CDN)
// - A || B (If A is null or undefined use the value from the CDN (B) otherwise A)
// - B || A (If B is null or undefined use the user/SDK value otherwise use the value from the CDN)
//
// The result of the value may also be null / undefined, which means there are no overrides to apply when the feature is enabled
var F = "featureOptIn.";
var M = ".mode";
var ON = ".onCfg";
var OFF = ".offCfg";
export function resolveCdnFeatureCfg(field, cdnCfg, userOptInDetails) {
    var _a;
    // cdn conifg value
    if (!cdnCfg || !cdnCfg.enabled) {
        return null;
    }
    var cdnFt = (cdnCfg[_DYN_FEATURE_OPT_IN /* @min:%2efeatureOptIn */] || {})[field] || { mode: 1 /* CdnFeatureMode.none */ };
    var cdnM = cdnFt.mode;
    var cdnOnV = cdnFt.onCfg;
    var cdnOffV = cdnFt.offCfg;
    var userFt = (userOptInDetails || {})[field] || { mode: 2 /* FeatureOptInMode.disable */ }; // default user mode is disable
    var userM = userFt.mode;
    var userOnV = userFt.onCfg;
    var userOffV = userFt.offCfg;
    var blockCdn = !!userFt.blockCdnCfg;
    var mFld = F + field + M;
    var onFld = F + field + ON;
    var offFld = F + field + OFF;
    var mode = userM;
    var onV = userOnV;
    var offV = userOffV;
    if (!blockCdn) {
        if (cdnM === 4 /* CdnFeatureMode.forceOn */ || cdnM === 5 /* CdnFeatureMode.forceOff */) {
            mode = (cdnM == 4 /* CdnFeatureMode.forceOn */ ? 3 /* FeatureOptInMode.enable */ : 2 /* FeatureOptInMode.disable */);
            onV = cdnOnV || userOnV;
            offV = cdnOffV || userOffV;
        }
        else if (cdnM === 2 /* CdnFeatureMode.disable */ || userM === 2 /* FeatureOptInMode.disable */) {
            mode = 2 /* FeatureOptInMode.disable */;
            onV = userOnV || cdnOnV;
            offV = userOffV || cdnOffV;
        }
        else if (cdnM === 3 /* CdnFeatureMode.enable */) {
            mode = 3 /* FeatureOptInMode.enable */;
            onV = userOnV || cdnOnV;
            offV = userOffV || cdnOffV;
        }
        else if (cdnM === 1 /* CdnFeatureMode.none */ && userM === 1 /* FeatureOptInMode.none */) {
            mode = 1 /* FeatureOptInMode.none */;
        }
    }
    return _a = {},
        _a[mFld] = mode,
        _a[onFld] = onV,
        _a[offFld] = offV,
        _a;
}
// helper function to get cdn config with opt-in features
export function applyCdnfeatureCfg(cdnCfg, core) {
    try {
        if (!cdnCfg || !cdnCfg.enabled) {
            return null;
        }
        if (!cdnCfg[_DYN_FEATURE_OPT_IN /* @min:%2efeatureOptIn */]) {
            return cdnCfg.config;
        }
        var optInMap = cdnCfg[_DYN_FEATURE_OPT_IN /* @min:%2efeatureOptIn */];
        var cdnConfig_1 = cdnCfg.config || {};
        objForEachKey(optInMap, function (key) {
            var featureVal = resolveCdnFeatureCfg(key, cdnCfg, core.config[_DYN_FEATURE_OPT_IN /* @min:%2efeatureOptIn */]);
            if (!isNullOrUndefined(featureVal)) {
                objForEachKey(featureVal, function (config, val) {
                    setValueByKey(cdnConfig_1, config, val);
                });
                _overrideCdnCfgByFeature(key, featureVal, cdnConfig_1);
            }
        });
        return cdnConfig_1;
    }
    catch (e) {
        // eslint-disable-next-line no-empty
    }
    return null;
}
function _overrideCdnCfgByFeature(field, ftVal, config) {
    var mode = ftVal[F + field + M];
    var val = ftVal[F + field + ON];
    var dVal = ftVal[F + field + OFF];
    var target = null;
    if (mode === 3 /* FeatureOptInMode.enable */) {
        target = val;
    }
    if (mode === 2 /* FeatureOptInMode.disable */) {
        target = dVal;
    }
    if (target) {
        objForEachKey(target, function (key, cfg) {
            setValueByKey(config, key, cfg);
        });
    }
}
//# sourceMappingURL=CfgSyncHelperFuncs.js.map