"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var getColorFromString_1 = require("../../utilities/color/getColorFromString");
var shades_1 = require("../../utilities/color/shades");
var Utilities_1 = require("../../Utilities");
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