export class ThemeService {
    constructor(api) {
        this.unsubscribe = () => { };
        this.onThemeChanged = () => {
            let currentTheme = this.api.themeApi.getCurrentThemeObject();
            currentTheme = this.mapOsTheme(currentTheme);
            this.applyNewThemeVariables(currentTheme);
            // this needs to be called after variables are set
            // as it may show the warning for a custom/runtime theme
            this.showMissingThemeFiles(currentTheme);
        };
        this.api = api;
        this.subscribe();
        if (!this.styleSheetObject) {
            this.styleSheetObject = new CSSStyleSheet();
            // ts does not know about adoptedStyleSheets
            document.adoptedStyleSheets = [
                ...(document.adoptedStyleSheets ?? []),
                this.styleSheetObject,
            ];
        }
    }
    destroy() {
        this.api = null;
        this.unsubscribe();
        document.adoptedStyleSheets = [...document.adoptedStyleSheets].filter((sheet) => sheet !== this.styleSheetObject);
    }
    subscribe() {
        const themeChangedUnsubscribe = this.api.eventApi.on('ThemeChanged', this.onThemeChanged);
        const prefferedColorSchemeUnsubscribe = this.attachPrefferedColorSchemeListener();
        this.unsubscribe = () => {
            themeChangedUnsubscribe();
            prefferedColorSchemeUnsubscribe();
        };
    }
    applyNewThemeVariables(theme) {
        const variables = theme.CSSVariables;
        if (!variables || Object.keys(variables).length === 0) {
            return;
        }
        let str = `html.${this.api.themeApi.internalApi.getThemeClassName(theme.Name)} {
      --ab-theme-loaded: ab--theme-${theme.Name};
    `;
        for (const [key, value] of Object.entries(variables)) {
            if (key.includes('--')) {
                str += `${key}: ${value};`;
            }
        }
        str += '}';
        this.styleSheetObject.replaceSync(str);
    }
    showMissingThemeFiles(theme) {
        // run time defined theme
        // because it may be an empty theme
        if (theme.Source === 'User') {
            return;
        }
        const themeName = theme.Name;
        const adaptable = this.api.internalApi.getAdaptableInstance();
        const logger = adaptable.logger;
        const documentElement = document.documentElement;
        const computedDocumentStyle = getComputedStyle(documentElement);
        const [abLoaded, abThemeLoaded] = ['--ab-loaded', '--ab-theme-loaded'].map((variable) => {
            let val = computedDocumentStyle.getPropertyValue(variable);
            if (typeof val === 'string' && val.trim) {
                val = val.trim();
            }
            return val;
        });
        if (abLoaded !== '777') {
            logger.consoleError('Please import Adaptable styles from "@adaptabletools/adaptable/index.css"');
        }
        const isCustomUserTheme = !this.api.themeApi.internalApi.isSystemTheme(themeName);
        if (!isCustomUserTheme && abThemeLoaded !== themeName) {
            logger.consoleWarn(`Theme "${themeName}" doesn't seem to be loaded! Make sure you import the css file for the "${themeName}" theme!

If it's an AdapTable system theme, try

import "@adaptabletools/adaptable/themes/${themeName}.css"`);
        }
    }
    // prefers-color-scheme
    getDOMPrefferedColorScheme() {
        return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
    }
    mapOsTheme(theme) {
        theme = typeof theme === 'string' ? this.api.themeApi.getThemeByName(theme) : theme;
        if ((typeof theme === 'string' && theme === 'os') ||
            (typeof theme === 'object' && theme.Name === 'os')) {
            return this.api.themeApi.getThemeByName(this.getDOMPrefferedColorScheme());
        }
        return theme;
    }
    attachPrefferedColorSchemeListener() {
        const handlePrefferedColorSchemeChange = () => {
            // we need to reapply the theme
            const currentTheme = this.api.themeApi.getCurrentThemeObject();
            if (currentTheme.Name === 'os') {
                this.api.themeApi.applyCurrentTheme();
            }
        };
        window
            .matchMedia('(prefers-color-scheme: dark)')
            .addEventListener('change', handlePrefferedColorSchemeChange);
        return () => {
            window
                .matchMedia('(prefers-color-scheme: dark)')
                .removeEventListener('change', handlePrefferedColorSchemeChange);
        };
    }
}
