import { theme as themeToken } from '../../theme-provider';
/**
 * Subscription for {@link ThemeStyleSheetBehavior}
 */
class ThemeStyleSheetBehaviorSubscription {
    constructor(value, styles, source) {
        this.value = value;
        this.styles = styles;
        this.source = source;
    }
    handleChange() {
        const theme = themeToken.getValueFor(this.source);
        if (Array.isArray(this.value)
            ? this.value.includes(theme)
            : this.value === theme) {
            this.source.$fastController.addStyles(this.styles);
        }
        else {
            this.source.$fastController.removeStyles(this.styles);
        }
    }
}
/**
 * Behavior to conditionally apply theme-based stylesheets.
 */
class ThemeStyleSheetBehavior {
    constructor(theme, styles) {
        this.theme = theme;
        this.styles = styles;
        this.cache = new WeakMap();
    }
    /**
     * @internal
     */
    bind(source) {
        const subscriber = this.cache.get(source)
            || new ThemeStyleSheetBehaviorSubscription(this.theme, this.styles, source);
        // Currently subscriber from cache may have gone through unbind
        // but still be in cache so always resubscribe
        // See: https://github.com/microsoft/fast/issues/3246#issuecomment-1030424876
        themeToken.subscribe(subscriber, source);
        subscriber.handleChange();
        this.cache.set(source, subscriber);
    }
    /**
     * @internal
     */
    unbind(source) {
        const subscriber = this.cache.get(source);
        if (subscriber) {
            themeToken.unsubscribe(subscriber);
        }
        // Currently does not evict subscriber from cache
        // See: https://github.com/microsoft/fast/issues/3246#issuecomment-1030424876
    }
}
/**
 * Behavior to conditionally apply theme-based stylesheets. To determine which to apply,
 * the behavior will use the nearest ThemeProvider's 'theme' design system value.
 *
 * @public
 * @example
 * ```ts
 * css`
 *     // ...
 * `.withBehaviors(
 *     themeBehavior(Theme.light, css` ... `),
 *     // Apply style for both dark and color theme
 *     themeBehavior([Theme.dark, Theme.color], css` ... `)
 * )
 * ```
 */
export const themeBehavior = (theme, styles) => new ThemeStyleSheetBehavior(theme, styles);
/* eslint-enable max-classes-per-file */
//# sourceMappingURL=theme.js.map