/*---------------------------------------------------------------------------------------------
 * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
 * See LICENSE.md in the project root for license terms and full copyright notice.
 *--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module State
 */
import * as React from "react";
import { connect } from "react-redux";
import { ThemeProvider } from "@itwin/itwinui-react";
import { UiFramework } from "../UiFramework";
/** System preferred color theme.
 * @public
 */
export const SYSTEM_PREFERRED_COLOR_THEME = "SYSTEM_PREFERRED";
/** Enum for the Color Theme string.
 * @public
 */
export var ColorTheme;
(function (ColorTheme) {
    /** Will use iTwinUI `light` theme. */
    ColorTheme["Light"] = "light";
    /** Will use iTwinUI `dark` theme. */
    ColorTheme["Dark"] = "dark";
    /** Will use iTwinUI `os` theme. */
    ColorTheme["System"] = "SYSTEM_PREFERRED";
    /** Will use iTwinUI wrapping `ThemeProvider` if provided, or default to 'Light' */
    ColorTheme["Inherit"] = "inherit";
    /** Will use iTwinUI `light` theme with `highContrast` set to `true` */
    ColorTheme["HighContrastLight"] = "high-contrast-light";
    /** Will use iTwinUI `dark` theme with `highContrast` set to `true` */
    ColorTheme["HighContrastDark"] = "high-contrast-dark";
})(ColorTheme || (ColorTheme = {}));
/**
 * Map of ColorTheme to ThemeType
 */
const colorThemeToThemeTypeMap = {
    [ColorTheme.Light]: "light",
    [ColorTheme.HighContrastLight]: "light",
    [ColorTheme.Dark]: "dark",
    [ColorTheme.HighContrastDark]: "dark",
    [ColorTheme.System]: "os",
};
/**
 * List of high contrast color themes
 */
const highContrastColorThemes = [
    ColorTheme.HighContrastDark,
    ColorTheme.HighContrastLight,
];
/** The default widget opacity.
 * @public
 */
export const WIDGET_OPACITY_DEFAULT = 0.9;
/** The default widget opacity.
 * @public
 */
export const TOOLBAR_OPACITY_DEFAULT = 0.5;
function mapStateToProps(state) {
    const frameworkState = state[UiFramework.frameworkStateKey]; // since app sets up key, don't hard-code name
    // istanbul ignore if
    if (!frameworkState)
        return undefined;
    return {
        theme: frameworkState.configurableUiState.theme,
        widgetOpacity: frameworkState.configurableUiState.widgetOpacity,
        toolbarOpacity: frameworkState.configurableUiState.toolbarOpacity,
    };
}
/** ThemeManagerComponent handles setting themes.
 */
class ThemeManagerComponent extends React.Component {
    constructor() {
        super(...arguments);
        this._setTheme = (theme) => {
            document.documentElement.classList.add("theme-transition");
            document.documentElement.setAttribute("data-theme", theme);
            window.setTimeout(() => document.documentElement.classList.remove("theme-transition"), 1000);
        };
        this._setWidgetOpacity = (opacity) => {
            const currentWidgetOpacity = document.documentElement.style.getPropertyValue("--buic-widget-opacity");
            if (currentWidgetOpacity !== opacity.toString()) {
                setTimeout(() => document.documentElement.style.setProperty("--buic-widget-opacity", opacity.toString()));
            }
        };
        this._setToolbarOpacity = (opacity) => {
            const currentToolbarOpacity = document.documentElement.style.getPropertyValue("--buic-toolbar-opacity");
            if (currentToolbarOpacity !== opacity.toString()) {
                setTimeout(() => {
                    document.documentElement.style.setProperty("--buic-toolbar-opacity", opacity.toString());
                });
            }
        };
    }
    componentDidMount() {
        this._setTheme(this.props.theme);
        this._setWidgetOpacity(this.props.widgetOpacity);
        this._setToolbarOpacity(this.props.toolbarOpacity);
    }
    componentDidUpdate(prevProps) {
        if (this.props.theme !== prevProps.theme)
            this._setTheme(this.props.theme);
        if (this.props.widgetOpacity !== prevProps.widgetOpacity)
            this._setWidgetOpacity(this.props.widgetOpacity);
        if (this.props.toolbarOpacity !== prevProps.toolbarOpacity)
            this._setToolbarOpacity(this.props.toolbarOpacity);
    }
    render() {
        const theme = colorThemeToThemeTypeMap[this.props.theme];
        const highContrast = highContrastColorThemes.includes(this.props.theme);
        return (React.createElement(ThemeProvider, { style: { height: "100%" }, theme: theme !== null && theme !== void 0 ? theme : "inherit", themeOptions: { highContrast }, "data-root-container": "iui-root-id" }, this.props.children));
    }
}
/** ThemeManager handles setting color themes and element opacity management. Note that this component will
 * affect the entire application by setting the data-theme attribute to the html element.
 * It also sets an iTwinUI `ThemeProvider` element locally, so all elements
 * within the AppUI tree will have the same theme, and should be using iTwinUI 2.x or later.
 * A `ColorTheme` enum values will configure iTwinUI `ThemeProvider` accordingly.
 * Any other string will only apply the `data-theme` attribute to the `html` element
 * and `ThemeProvider` theme will be set to `inherit`, in this case the application is
 * responsible for setting the theme by overriding iTwinUI css variables.
 *
 * This React component is Redux connected and should wrap [[ConfigurableUiContent]].
 *
 * ```tsx
 * <Provider store={UiFramework.store}>
 *   <ThemeManager>
 *     <ConfigurableUiContent />
 *   </ThemeManager>
 * </Provider>
 * ```
 * @public
 */
export const ThemeManager = connect(mapStateToProps)(ThemeManagerComponent);
//# sourceMappingURL=ThemeManager.js.map