define(["require", "exports", "../../utilities/color/getColorFromString", "../../utilities/color/shades", "../../Utilities"], function (require, exports, getColorFromString_1, shades_1, Utilities_1) {
    "use strict";
    Object.defineProperty(exports, "__esModule", { value: true });
    var ThemeGenerator = /** @class */ (function () {
        function ThemeGenerator() {
        }
        /* Sets an IThemeSlotRule to the given color and cascades it to the rest of the theme, updating other IThemeSlotRules in the theme that
         *   inherit from that color.
         * isInverted: whether it's a dark theme or not, which affects the algorithm used to generate shades
         * isCustomization should be true only if it's a user action, and indicates overwriting the slot's inheritance (if any)
         * overwriteCustomColor: a slot could have a generated color based on its inheritance rules (isCustomized is false), or a custom color
                                  based on user input (isCustomized is true), this bool tells us whether to override existing customized colors */
        ThemeGenerator.setSlot = function (rule, color, isInverted, isCustomization, overwriteCustomColor) {
            if (isInverted === void 0) { isInverted = false; }
            if (isCustomization === void 0) { isCustomization = false; }
            if (overwriteCustomColor === void 0) { overwriteCustomColor = true; }
            if (!rule.color && rule.value) {
                // not a color rule
                return;
            }
            if (overwriteCustomColor) {
                var colorAsIColor = void 0;
                if (typeof color === 'string') {
                    colorAsIColor = getColorFromString_1.getColorFromString(color); // the ! is a lie here but we'll verify it in the next line
                    if (!colorAsIColor) {
                        throw 'color is invalid in setSlot(): ' + color;
                    }
                }
                else {
                    colorAsIColor = color;
                }
                ThemeGenerator._setSlot(rule, colorAsIColor, isInverted, isCustomization, overwriteCustomColor);
            }
            else if (rule.color) {
                ThemeGenerator._setSlot(rule, rule.color, isInverted, isCustomization, overwriteCustomColor);
            }
        };
        /* Sets the color of each slot based on its rule. Slots that don't inherit must have a color already.
         * If this completes without error, then the theme is ready to use. (All slots will have a color.)
         * setSlot() can be called before this, but this must be called before getThemeAs*().
         * Does not override colors of rules where isCustomized is true (i.e. doesn't override existing customizations).
         */
        ThemeGenerator.insureSlots = function (slotRules, isInverted) {
            // Get all the "root" rules, the ones which don't inherit. Then "set" them to trigger updating dependent slots.
            for (var ruleName in slotRules) {
                if (slotRules.hasOwnProperty(ruleName)) {
                    var rule = slotRules[ruleName];
                    if (!rule.inherits && !rule.value) {
                        if (!rule.color) {
                            throw 'A color slot rule that does not inherit must provide its own color.';
                        }
                        ThemeGenerator._setSlot(rule, rule.color, isInverted, false, false);
                    }
                }
            }
        };
        /* Gets the JSON-formatted blob that describes the theme, usable with the REST request endpoints
         * { [theme slot name as string] : [color as string],
         *  "tokenName": "#f00f00",
         *  "tokenName2": "#ba2ba2",
         *   ... }
         */
        ThemeGenerator.getThemeAsJson = function (slotRules) {
            var theme = {};
            for (var ruleName in slotRules) {
                if (slotRules.hasOwnProperty(ruleName)) {
                    var rule = slotRules[ruleName];
                    theme[rule.name] = rule.color ? rule.color.str : rule.value || '';
                }
            }
            return theme;
        };
        /*
         * Gets code-formatted load theme blob that can be copy and pasted.
         */
        ThemeGenerator.getThemeAsCode = function (slotRules) {
            var attributeTemplate = "    {0}: '{1}',\n";
            var output = '';
            output += 'loadTheme({\n  palette: {\n';
            for (var ruleName in slotRules) {
                if (slotRules.hasOwnProperty(ruleName)) {
                    var rule = slotRules[ruleName];
                    var camelCasedName = rule.name.charAt(0).toLowerCase() + rule.name.slice(1);
                    var outputColor = rule.color ? '#' + rule.color.hex : rule.value || '';
                    output += Utilities_1.format(attributeTemplate, camelCasedName, outputColor);
                }
            }
            output += '  }\n});';
            return output;
        };
        /* Gets the theme as a list of SASS variables that can be used in code
         * $tokenName: "[theme:tokenName, default:#f00f00]";
         * $tokenName2: "[theme:tokenName2, default:#ba2ba2]";
         * ...
         */
        ThemeGenerator.getThemeAsSass = function (slotRules) {
            var sassVarTemplate = '${0}Color: "[theme: {1}, default: {2}]";\n';
            var output = '';
            for (var ruleName in slotRules) {
                if (slotRules.hasOwnProperty(ruleName)) {
                    var rule = slotRules[ruleName];
                    var camelCasedName = rule.name.charAt(0).toLowerCase() + rule.name.slice(1);
                    output += Utilities_1.format(sassVarTemplate, camelCasedName, camelCasedName, rule.color ? rule.color.str : rule.value || '');
                }
            }
            return output;
        };
        /* Gets the theme formatted for PowerShell scripts
         * @{
         * "tokenName" = "#f00f00";
         * "tokenName2" = "#ba2ba2";
         * ...
         * }
         */
        ThemeGenerator.getThemeForPowerShell = function (slotRules) {
            var psVarTemplate = '"{0}" = "{1}";\n';
            var output = '';
            for (var ruleName in slotRules) {
                if (slotRules.hasOwnProperty(ruleName)) {
                    var rule = slotRules[ruleName];
                    if (rule.value) {
                        // skip this one, it's not a color
                        continue;
                    }
                    var camelCasedName = rule.name.charAt(0).toLowerCase() + rule.name.slice(1);
                    var outputColor = rule.color ? '#' + rule.color.hex : rule.value || '';
                    // powershell endpoint uses the RGBA format
                    if (rule.color && rule.color.a && rule.color.a !== 100) {
                        outputColor += String(rule.color.a.toString(16));
                    }
                    output += Utilities_1.format(psVarTemplate, camelCasedName, outputColor);
                }
            }
            return '@{\n' + output + '}';
        };
        /* Sets the given slot's color to the appropriate color, shading it if necessary.
           Then, iterates through all other rules (that are this rule's dependents) to update them accordingly.
           isCustomization=true means it's a user provided color, set it to that raw color
           isCustomization=false means the rule it's inheriting from changed, so updated using asShade */
        ThemeGenerator._setSlot = function (rule, color, isInverted, isCustomization, overwriteCustomColor) {
            if (overwriteCustomColor === void 0) { overwriteCustomColor = true; }
            if (!rule.color && rule.value) {
                // not a color rule
                return;
            }
            if (overwriteCustomColor || !rule.color || !rule.isCustomized || !rule.inherits) {
                // set the rule's color under these conditions
                if ((overwriteCustomColor || !rule.isCustomized) && !isCustomization && rule.inherits && shades_1.isValidShade(rule.asShade)) {
                    // it's inheriting by shade
                    if (rule.isBackgroundShade) {
                        rule.color = shades_1.getBackgroundShade(color, rule.asShade, isInverted);
                    }
                    else {
                        rule.color = shades_1.getShade(color, rule.asShade, isInverted);
                    }
                    rule.isCustomized = false;
                }
                else {
                    rule.color = color;
                    rule.isCustomized = true;
                }
                // then update dependent colors
                for (var _i = 0, _a = rule.dependentRules; _i < _a.length; _i++) {
                    var ruleToUpdate = _a[_i];
                    ThemeGenerator._setSlot(ruleToUpdate, rule.color, isInverted, false, overwriteCustomColor);
                }
            }
        };
        return ThemeGenerator;
    }());
    exports.ThemeGenerator = ThemeGenerator;
});
//# sourceMappingURL=ThemeGenerator.js.map