var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
// If `opacity` exists, we apply a `color-mix` formula to blend colors
// If `multiple` exists, we apply the `calc()` function to multiply the reference value
// Otherwise, we simply replace the reference with its corresponding variable
function processTokenValue(value, refs, multiple, opacity) {
    // Remove `mapping` from token.name
    const cleanName = refs.name.replace(/mapping-?/g, '');
    if (opacity) {
        return `color-mix(in srgb, var(--${cleanName}), transparent calc(100% - ${opacity}))`;
    }
    else if (multiple) {
        return value.replace(refs.value, `calc(var(--${cleanName}) * ${multiple})`);
    }
    else {
        return value.replace(refs.value, `var(--${cleanName})`);
    }
}
// Helper function to resolve references for both `multiple` and `opacity` and return the updated value
function resolveTokenReferences(token, unfilteredTokens, usesReferences, getReferences) {
    var _a, _b, _c, _d;
    let multiple = (_b = (_a = token.original) === null || _a === void 0 ? void 0 : _a.attributes) === null || _b === void 0 ? void 0 : _b.multiple;
    let opacity = (_d = (_c = token.original) === null || _c === void 0 ? void 0 : _c.attributes) === null || _d === void 0 ? void 0 : _d.opacity;
    // Resolve references in `multiple` and `opacity`
    multiple = resolveAndReplaceReferences(multiple, unfilteredTokens, usesReferences, getReferences);
    opacity = resolveAndReplaceReferences(opacity, unfilteredTokens, usesReferences, getReferences);
    return { multiple, opacity };
}
// Helper function to resolve references and return the token name
function resolveAndReplaceReferences(attribute, unfilteredTokens, usesReferences, getReferences) {
    if (attribute && usesReferences(attribute, unfilteredTokens)) {
        const refs = getReferences(attribute, unfilteredTokens);
        refs.forEach(ref => {
            // Replace the reference with the resolved token name
            attribute = `var(--${ref.name})`;
        });
    }
    return attribute;
}
const cssVarCalcMixFormatter = (usesReferences, getReferences) => ({
    name: 'wm-calc-colormix-format',
    format: function ({ dictionary, options }) {
        const { selector } = options;
        // Generate CSS variable definitions
        const variables = dictionary.allTokens
            .map((token) => {
            // Remove `mapping` from token.name
            const cleanName = token.name.replace(/mapping-?/g, '');
            let value = getProcessedTokenValue(token, dictionary, usesReferences, getReferences);
            return `--${cleanName}: ${value};`;
        })
            .join(`\n`);
        // Return correctly formatted output based on selector
        return selector && selector.trim()
            ? `${selector} {\n${variables}\n}\n` // Wrap in selector
            : `${variables}\n`; // No selector, no closing bracket
    },
});
function getProcessedTokenValue(token, dictionary, usesReferences, getReferences) {
    let value = String(token.value);
    // Checking if the token has references
    if (usesReferences(token.original.value, dictionary.unfilteredTokens)) {
        const refs = getReferences(token.original.value, dictionary.unfilteredTokens);
        refs.forEach((ref) => {
            // Resolve references for `multiple` and `opacity`
            const { multiple, opacity } = resolveTokenReferences(token, dictionary.unfilteredTokens, usesReferences, getReferences);
            // Process the value based on resolved references
            value = processTokenValue(value, ref, multiple, opacity);
        });
    }
    else {
        value = token.original.value || token.value;
    }
    return value;
}
const componentVariantsFormatter = (usesReferences, getReferences, platform, options = {}) => ({
    name: 'css/component-variants',
    format: function (_a) {
        var { dictionary, file } = _a, rest = __rest(_a, ["dictionary", "file"]);
        const componentRootKey = Object.keys(dictionary.tokens)[0];
        if (!componentRootKey) {
            console.warn(`[Style Dictionary] Could not derive component name from source ${file.destination}`);
            return '';
        }
        const groupedVariants = groupTokensByVariantType(dictionary, componentRootKey, platform);
        const cssBlocks = Object.values(groupedVariants).map(group => generateCssBlockFromGroup(group, dictionary, usesReferences, getReferences, platform));
        // --- README GENERATION ---
        const generateReadmeFn = options.generateComponentReadme;
        if (generateReadmeFn) {
            generateReadmeFn(componentRootKey, groupedVariants, platform, dictionary, Object.assign({}, rest.options));
        }
        // --- END README GENERATION ---
        return cssBlocks.join('\n\n');
    }
});
const groupTokensByVariantType = (dictionary, componentRootKey, platform) => {
    const groups = {};
    const isMobile = platform === 'mobile';
    const mappingStore = {};
    dictionary.allTokens.forEach((token) => {
        var _a, _b, _c, _d, _e, _f;
        const path = token.path;
        const appearanceIndex = path.indexOf('appearances');
        const variantGroupIndex = path.indexOf('variantGroups');
        const stateIndex = path.indexOf('states');
        const isState = stateIndex !== -1;
        const state = isState ? path[stateIndex + 1] : null;
        const appearance = appearanceIndex !== -1 ? path[appearanceIndex + 1] : null;
        const groupType = variantGroupIndex !== -1 ? path[variantGroupIndex + 1] : null;
        const variant = variantGroupIndex !== -1 ? path[variantGroupIndex + 2] : null;
        const isVariantToken = appearance && groupType && variant;
        const isTopLevelMapping = appearanceIndex === -1 && path[1] === 'mapping';
        const isAppearanceMapping = appearanceIndex !== -1 && path[appearanceIndex + 2] === 'mapping';
        let key, type, group;
        if (isVariantToken) {
            key = `${componentRootKey}-${appearance}-${groupType}-${variant}${isState ? `-${state}` : ''}`;
            type = isState ? 'state-variant' : 'variant';
            group = {
                type,
                component: componentRootKey,
                appearance,
                groupType,
                variant,
                state,
            };
            if (!groups[key]) {
                groups[key] = Object.assign(Object.assign({}, group), { tokens: [] });
                if (isMobile && mappingStore[appearance]) {
                    groups[key].tokens.push(...mappingStore[appearance]);
                }
            }
        }
        else if (isTopLevelMapping) {
            key = `${componentRootKey}-mapping${isState ? `-${state}` : ''}`;
            type = isState ? 'state-mapping' : 'mapping';
            group = {
                type,
                component: componentRootKey,
                appearance: 'mapping',
                state,
                isRootMapping: true,
            };
        }
        else if (isAppearanceMapping) {
            const appearanceDef = (_c = (_b = (_a = dictionary.tokens) === null || _a === void 0 ? void 0 : _a[componentRootKey]) === null || _b === void 0 ? void 0 : _b.appearances) === null || _c === void 0 ? void 0 : _c[appearance];
            const hasVariants = (appearanceDef === null || appearanceDef === void 0 ? void 0 : appearanceDef.variantGroups) && Object.keys(appearanceDef.variantGroups).length > 0;
            // If mobile + variants exist, skip creating this class — mapping will be merged
            if (isMobile && hasVariants && !isState) {
                (_d = mappingStore[appearance]) !== null && _d !== void 0 ? _d : (mappingStore[appearance] = []);
                mappingStore[appearance].push(token);
                return; // skip adding mapping like .btn-outlined
            }
            // Else proceed to generate a separate class for mapping
            key = `${componentRootKey}-${appearance}-mapping${isState ? `-${state}` : ''}`;
            type = isState ? 'state-mapping' : 'mapping';
            group = {
                type,
                component: componentRootKey,
                appearance,
                state,
            };
            if (isMobile && !isState) {
                (_e = mappingStore[appearance]) !== null && _e !== void 0 ? _e : (mappingStore[appearance] = []);
                mappingStore[appearance].push(token);
            }
        }
        if (key) {
            (_f = groups[key]) !== null && _f !== void 0 ? _f : (groups[key] = Object.assign(Object.assign({}, group), { tokens: [] }));
            groups[key].tokens.push(token);
        }
    });
    return groups;
};
// output: a selector string based on the group type and state
const getStateSelector = (dictionary, component, appearance, state, groupType, variant, type, platform, isRootMapping) => {
    var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
    const meta = (_b = (_a = dictionary.unfilteredTokens) === null || _a === void 0 ? void 0 : _a[component]) === null || _b === void 0 ? void 0 : _b.meta;
    const appearanceMeta = (_c = meta === null || meta === void 0 ? void 0 : meta.appearances) === null || _c === void 0 ? void 0 : _c[appearance];
    const selectors = [];
    if (type === 'state-variant') {
        selectors.push((_j = (_h = (_g = (_f = (_e = (_d = appearanceMeta === null || appearanceMeta === void 0 ? void 0 : appearanceMeta.variantGroups) === null || _d === void 0 ? void 0 : _d[groupType]) === null || _e === void 0 ? void 0 : _e[variant]) === null || _f === void 0 ? void 0 : _f.states) === null || _g === void 0 ? void 0 : _g[state]) === null || _h === void 0 ? void 0 : _h.selector) === null || _j === void 0 ? void 0 : _j[platform]);
    }
    if (type === 'state-mapping' || type === 'state-variant') {
        selectors.push((_o = (_m = (_l = (_k = appearanceMeta === null || appearanceMeta === void 0 ? void 0 : appearanceMeta.mapping) === null || _k === void 0 ? void 0 : _k.states) === null || _l === void 0 ? void 0 : _l[state]) === null || _m === void 0 ? void 0 : _m.selector) === null || _o === void 0 ? void 0 : _o[platform], (_s = (_r = (_q = (_p = meta === null || meta === void 0 ? void 0 : meta.mapping) === null || _p === void 0 ? void 0 : _p.states) === null || _q === void 0 ? void 0 : _q[state]) === null || _r === void 0 ? void 0 : _r.selector) === null || _s === void 0 ? void 0 : _s[platform]);
    }
    const selector = (platform === "mobile" && (type === "state-variant" || (type == "state-mapping" && !isRootMapping))
        ? `${(_u = (_t = meta === null || meta === void 0 ? void 0 : meta.mapping) === null || _t === void 0 ? void 0 : _t.selector) === null || _u === void 0 ? void 0 : _u[platform]}${selectors.find(Boolean)}`
        : selectors.find(Boolean)) || `:${state}`;
    // Return the first defined selector or fallback to pseudo-class
    return selector;
};
const getSelectorFromGroup = (group, dictionary, platform) => {
    var _a, _b, _c, _d, _e, _f, _g;
    const { component, appearance, type, groupType, variant, state, isRootMapping } = group;
    const meta = (_b = (_a = dictionary.unfilteredTokens) === null || _a === void 0 ? void 0 : _a[component]) === null || _b === void 0 ? void 0 : _b.meta;
    const appearanceMeta = (_c = meta === null || meta === void 0 ? void 0 : meta.appearances) === null || _c === void 0 ? void 0 : _c[appearance];
    const defaultBase = `.${component}-${appearance}`;
    const rootMappingSelector = ((_e = (_d = meta === null || meta === void 0 ? void 0 : meta.mapping) === null || _d === void 0 ? void 0 : _d.selector) === null || _e === void 0 ? void 0 : _e[platform]) || `.${component}`;
    const appearanceMappingSelector = ((_g = (_f = appearanceMeta === null || appearanceMeta === void 0 ? void 0 : appearanceMeta.mapping) === null || _f === void 0 ? void 0 : _f.selector) === null || _g === void 0 ? void 0 : _g[platform]) || defaultBase;
    const getCombinedVariantSelector = () => {
        var _a, _b, _c, _d;
        const selector = (_d = (_c = (_b = (_a = appearanceMeta === null || appearanceMeta === void 0 ? void 0 : appearanceMeta.variantGroups) === null || _a === void 0 ? void 0 : _a[groupType]) === null || _b === void 0 ? void 0 : _b[variant]) === null || _c === void 0 ? void 0 : _c.selector) === null || _d === void 0 ? void 0 : _d[platform];
        if (platform === 'mobile') {
            return selector || `${[
                appearanceMappingSelector || [component, appearance].filter(Boolean).join('-'),
                variant
            ].filter(Boolean).join('-')}`;
        }
        return selector
            ? expandSelectors(platform, appearanceMappingSelector, selector)
            : expandSelectors(platform, appearanceMappingSelector, `.${component}-${variant}`);
    };
    const getStateSelectorWrapper = () => getStateSelector(dictionary, component, appearance, state, groupType, variant, type, platform, isRootMapping);
    switch (type) {
        case 'mapping':
            return isRootMapping ? rootMappingSelector : appearanceMappingSelector;
        case 'variant':
            return getCombinedVariantSelector();
        case 'state-mapping':
            return isRootMapping
                ? expandSelectors(platform, rootMappingSelector, getStateSelectorWrapper())
                : expandSelectors(platform, appearanceMappingSelector, getStateSelectorWrapper());
        case 'state-variant':
            return expandSelectors(platform, getCombinedVariantSelector(), getStateSelectorWrapper());
        default:
            return '';
    }
};
const expandSelectors = (platform, baseSelectors, stateSelectors = ['']) => {
    if (platform == "web") {
        const bases = baseSelectors.split(',').filter(Boolean);
        const states = stateSelectors.split(',').filter(Boolean);
        const combos = [];
        for (const base of bases) {
            for (const state of states) {
                combos.push(`${base}${state}`);
            }
        }
        return combos.join(',');
    }
    else {
        return `${baseSelectors}${stateSelectors}`;
    }
};
// takes a group object and a dictionary, and returns a CSS block
// Example output:
// .btn-filled-status-primary {
//   --wm-btn-filled-status-primary-color: #fff;
//}
const generateCssBlockFromGroup = (group, dictionary, usesReferences, getReferences, platform) => {
    const { tokens, component, appearance, groupType, variant } = group;
    let selector = getSelectorFromGroup(group, dictionary, platform);
    if (platform === 'web' && selector) {
        selector = selector
            .split(',')
            .map(s => s.startsWith('.wm-app') ? s : `.wm-app ${s}`)
            .join(', ');
    }
    if (!selector)
        return '';
    const cssProps = tokens
        .map((token) => {
        const value = getProcessedTokenValue(token, dictionary, usesReferences, getReferences);
        const baseProp = getBasePropertyName(token.path, component, appearance, groupType, variant);
        const cssVarName = `--wm-${component}${baseProp ? `-${baseProp}` : ''}`.replace(/-+$/, '');
        return `  ${cssVarName}: ${value};`;
    })
        .join('\n');
    return `${selector} {\n${cssProps}\n}`;
};
/**
 * Derives a clean CSS variable suffix from the token path.
 * Removes known structural segments like component name, appearance, state, variant, etc.
 *
 * @param tokenPath - The full token path array
 * @param componentRootKey - e.g., "btn"
 * @param appearance - e.g., "filled"
 * @param groupType - e.g., "status" or "size"
 * @param variant - e.g., "primary", "lg"
 * @returns A kebab-case string like "color-background" to append to --wm-btn
 */
const getBasePropertyName = (tokenPath, componentRootKey, appearance, groupType, variant) => {
    const stateIndex = tokenPath.indexOf('states');
    const stateName = stateIndex !== -1 ? tokenPath[stateIndex + 1] : null;
    // All known structural segments to exclude from final name
    const ignoreSegments = new Set([
        componentRootKey,
        'appearances',
        appearance,
        'mapping',
        'states',
        stateName,
        'variantGroups',
        groupType,
        variant
    ]);
    // Sanitize helper: removes illegal characters like @ and trims leading/trailing dashes
    const sanitize = (segment) => segment.replace(/[^a-zA-Z0-9-_]/g, '-').replace(/^-+|-+$/g, '').trim();
    // Build property name from remaining segments
    const propertyName = tokenPath
        .filter(segment => segment && !ignoreSegments.has(segment))
        .map(sanitize)
        .join('-');
    return propertyName;
};
export { cssVarCalcMixFormatter, componentVariantsFormatter, getSelectorFromGroup };
//# sourceMappingURL=style-dictionary-utils.js.map