import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import _extends from "@babel/runtime/helpers/esm/extends";
import _objectWithoutProperties from "@babel/runtime/helpers/esm/objectWithoutProperties";
import _typeof from "@babel/runtime/helpers/esm/typeof";
import _formatMuiErrorMessage from "@mui/utils/formatMuiErrorMessage";
import * as React from 'react';
import PropTypes from 'prop-types';
import { deepmerge } from '@mui/utils';
import { GlobalStyles } from '@mui/styled-engine';
import { useTheme as muiUseTheme } from '@mui/private-theming';
import ThemeProvider from '../ThemeProvider';
import systemGetInitColorSchemeScript, { DEFAULT_ATTRIBUTE, DEFAULT_COLOR_SCHEME_STORAGE_KEY, DEFAULT_MODE_STORAGE_KEY } from './getInitColorSchemeScript';
import useCurrentColorScheme from './useCurrentColorScheme';
import { jsx as _jsx } from "react/jsx-runtime";
import { jsxs as _jsxs } from "react/jsx-runtime";
export var DISABLE_CSS_TRANSITION = '*{-webkit-transition:none!important;-moz-transition:none!important;-o-transition:none!important;-ms-transition:none!important;transition:none!important}';
export default function createCssVarsProvider(options) {
  var themeId = options.themeId,
    _options$theme = options.theme,
    defaultTheme = _options$theme === void 0 ? {} : _options$theme,
    _options$attribute = options.attribute,
    defaultAttribute = _options$attribute === void 0 ? DEFAULT_ATTRIBUTE : _options$attribute,
    _options$modeStorageK = options.modeStorageKey,
    defaultModeStorageKey = _options$modeStorageK === void 0 ? DEFAULT_MODE_STORAGE_KEY : _options$modeStorageK,
    _options$colorSchemeS = options.colorSchemeStorageKey,
    defaultColorSchemeStorageKey = _options$colorSchemeS === void 0 ? DEFAULT_COLOR_SCHEME_STORAGE_KEY : _options$colorSchemeS,
    _options$defaultMode = options.defaultMode,
    designSystemMode = _options$defaultMode === void 0 ? 'light' : _options$defaultMode,
    designSystemColorScheme = options.defaultColorScheme,
    _options$disableTrans = options.disableTransitionOnChange,
    designSystemTransitionOnChange = _options$disableTrans === void 0 ? false : _options$disableTrans,
    resolveTheme = options.resolveTheme,
    excludeVariablesFromRoot = options.excludeVariablesFromRoot;
  if (!defaultTheme.colorSchemes || typeof designSystemColorScheme === 'string' && !defaultTheme.colorSchemes[designSystemColorScheme] || _typeof(designSystemColorScheme) === 'object' && !defaultTheme.colorSchemes[designSystemColorScheme == null ? void 0 : designSystemColorScheme.light] || _typeof(designSystemColorScheme) === 'object' && !defaultTheme.colorSchemes[designSystemColorScheme == null ? void 0 : designSystemColorScheme.dark]) {
    console.error("MUI: `".concat(designSystemColorScheme, "` does not exist in `theme.colorSchemes`."));
  }
  var ColorSchemeContext = /*#__PURE__*/React.createContext(undefined);
  var useColorScheme = function useColorScheme() {
    var value = React.useContext(ColorSchemeContext);
    if (!value) {
      throw new Error(process.env.NODE_ENV !== "production" ? "MUI: `useColorScheme` must be called under <CssVarsProvider />" : _formatMuiErrorMessage(19));
    }
    return value;
  };
  function CssVarsProvider(_ref) {
    var children = _ref.children,
      _ref$theme = _ref.theme,
      themeProp = _ref$theme === void 0 ? defaultTheme : _ref$theme,
      _ref$modeStorageKey = _ref.modeStorageKey,
      modeStorageKey = _ref$modeStorageKey === void 0 ? defaultModeStorageKey : _ref$modeStorageKey,
      _ref$colorSchemeStora = _ref.colorSchemeStorageKey,
      colorSchemeStorageKey = _ref$colorSchemeStora === void 0 ? defaultColorSchemeStorageKey : _ref$colorSchemeStora,
      _ref$attribute = _ref.attribute,
      attribute = _ref$attribute === void 0 ? defaultAttribute : _ref$attribute,
      _ref$defaultMode = _ref.defaultMode,
      defaultMode = _ref$defaultMode === void 0 ? designSystemMode : _ref$defaultMode,
      _ref$defaultColorSche = _ref.defaultColorScheme,
      defaultColorScheme = _ref$defaultColorSche === void 0 ? designSystemColorScheme : _ref$defaultColorSche,
      _ref$disableTransitio = _ref.disableTransitionOnChange,
      disableTransitionOnChange = _ref$disableTransitio === void 0 ? designSystemTransitionOnChange : _ref$disableTransitio,
      _ref$storageWindow = _ref.storageWindow,
      storageWindow = _ref$storageWindow === void 0 ? typeof window === 'undefined' ? undefined : window : _ref$storageWindow,
      _ref$documentNode = _ref.documentNode,
      documentNode = _ref$documentNode === void 0 ? typeof document === 'undefined' ? undefined : document : _ref$documentNode,
      _ref$colorSchemeNode = _ref.colorSchemeNode,
      colorSchemeNode = _ref$colorSchemeNode === void 0 ? typeof document === 'undefined' ? undefined : document.documentElement : _ref$colorSchemeNode,
      _ref$colorSchemeSelec = _ref.colorSchemeSelector,
      colorSchemeSelector = _ref$colorSchemeSelec === void 0 ? ':root' : _ref$colorSchemeSelec,
      _ref$disableNestedCon = _ref.disableNestedContext,
      disableNestedContext = _ref$disableNestedCon === void 0 ? false : _ref$disableNestedCon,
      _ref$disableStyleShee = _ref.disableStyleSheetGeneration,
      disableStyleSheetGeneration = _ref$disableStyleShee === void 0 ? false : _ref$disableStyleShee;
    var hasMounted = React.useRef(false);
    var upperTheme = muiUseTheme();
    var ctx = React.useContext(ColorSchemeContext);
    var nested = !!ctx && !disableNestedContext;
    var scopedTheme = themeProp[themeId];
    var _ref2 = scopedTheme || themeProp,
      _ref2$colorSchemes = _ref2.colorSchemes,
      colorSchemes = _ref2$colorSchemes === void 0 ? {} : _ref2$colorSchemes,
      _ref2$components = _ref2.components,
      components = _ref2$components === void 0 ? {} : _ref2$components,
      _ref2$generateCssVars = _ref2.generateCssVars,
      generateCssVars = _ref2$generateCssVars === void 0 ? function () {
        return {
          vars: {},
          css: {}
        };
      } : _ref2$generateCssVars,
      cssVarPrefix = _ref2.cssVarPrefix,
      restThemeProp = _objectWithoutProperties(_ref2, ["colorSchemes", "components", "generateCssVars", "cssVarPrefix"]);
    var allColorSchemes = Object.keys(colorSchemes);
    var defaultLightColorScheme = typeof defaultColorScheme === 'string' ? defaultColorScheme : defaultColorScheme.light;
    var defaultDarkColorScheme = typeof defaultColorScheme === 'string' ? defaultColorScheme : defaultColorScheme.dark;

    // 1. Get the data about the `mode`, `colorScheme`, and setter functions.
    var _useCurrentColorSchem = useCurrentColorScheme({
        supportedColorSchemes: allColorSchemes,
        defaultLightColorScheme: defaultLightColorScheme,
        defaultDarkColorScheme: defaultDarkColorScheme,
        modeStorageKey: modeStorageKey,
        colorSchemeStorageKey: colorSchemeStorageKey,
        defaultMode: defaultMode,
        storageWindow: storageWindow
      }),
      stateMode = _useCurrentColorSchem.mode,
      setMode = _useCurrentColorSchem.setMode,
      systemMode = _useCurrentColorSchem.systemMode,
      lightColorScheme = _useCurrentColorSchem.lightColorScheme,
      darkColorScheme = _useCurrentColorSchem.darkColorScheme,
      stateColorScheme = _useCurrentColorSchem.colorScheme,
      setColorScheme = _useCurrentColorSchem.setColorScheme;
    var mode = stateMode;
    var colorScheme = stateColorScheme;
    if (nested) {
      mode = ctx.mode;
      colorScheme = ctx.colorScheme;
    }
    var calculatedMode = function () {
      if (mode) {
        return mode;
      }
      // This scope occurs on the server
      if (defaultMode === 'system') {
        return designSystemMode;
      }
      return defaultMode;
    }();
    var calculatedColorScheme = function () {
      if (!colorScheme) {
        // This scope occurs on the server
        if (calculatedMode === 'dark') {
          return defaultDarkColorScheme;
        }
        // use light color scheme, if default mode is 'light' | 'system'
        return defaultLightColorScheme;
      }
      return colorScheme;
    }();

    // 2. Create CSS variables and store them in objects (to be generated in stylesheets in the final step)
    var _generateCssVars = generateCssVars(),
      rootCss = _generateCssVars.css,
      rootVars = _generateCssVars.vars; // 3. Start composing the theme object
    var theme = _extends({}, restThemeProp, {
      components: components,
      colorSchemes: colorSchemes,
      cssVarPrefix: cssVarPrefix,
      vars: rootVars,
      getColorSchemeSelector: function getColorSchemeSelector(targetColorScheme) {
        return "[".concat(attribute, "=\"").concat(targetColorScheme, "\"] &");
      }
    });

    // 4. Create color CSS variables and store them in objects (to be generated in stylesheets in the final step)
    //    The default color scheme stylesheet is constructed to have the least CSS specificity.
    //    The other color schemes uses selector, default as data attribute, to increase the CSS specificity so that they can override the default color scheme stylesheet.
    var defaultColorSchemeStyleSheet = {};
    var otherColorSchemesStyleSheet = {};
    Object.entries(colorSchemes).forEach(function (_ref3) {
      var _ref4 = _slicedToArray(_ref3, 2),
        key = _ref4[0],
        scheme = _ref4[1];
      var _generateCssVars2 = generateCssVars(key),
        css = _generateCssVars2.css,
        vars = _generateCssVars2.vars;
      theme.vars = deepmerge(theme.vars, vars);
      if (key === calculatedColorScheme) {
        // 4.1 Merge the selected color scheme to the theme
        Object.keys(scheme).forEach(function (schemeKey) {
          if (scheme[schemeKey] && _typeof(scheme[schemeKey]) === 'object') {
            // shallow merge the 1st level structure of the theme.
            theme[schemeKey] = _extends({}, theme[schemeKey], scheme[schemeKey]);
          } else {
            theme[schemeKey] = scheme[schemeKey];
          }
        });
        if (theme.palette) {
          theme.palette.colorScheme = key;
        }
      }
      var resolvedDefaultColorScheme = function () {
        if (typeof defaultColorScheme === 'string') {
          return defaultColorScheme;
        }
        if (defaultMode === 'dark') {
          return defaultColorScheme.dark;
        }
        return defaultColorScheme.light;
      }();
      if (key === resolvedDefaultColorScheme) {
        if (excludeVariablesFromRoot) {
          var excludedVariables = {};
          excludeVariablesFromRoot(cssVarPrefix).forEach(function (cssVar) {
            excludedVariables[cssVar] = css[cssVar];
            delete css[cssVar];
          });
          defaultColorSchemeStyleSheet["[".concat(attribute, "=\"").concat(key, "\"]")] = excludedVariables;
        }
        defaultColorSchemeStyleSheet["".concat(colorSchemeSelector, ", [").concat(attribute, "=\"").concat(key, "\"]")] = css;
      } else {
        otherColorSchemesStyleSheet["".concat(colorSchemeSelector === ':root' ? '' : colorSchemeSelector, "[").concat(attribute, "=\"").concat(key, "\"]")] = css;
      }
    });
    theme.vars = deepmerge(theme.vars, rootVars);

    // 5. Declaring effects
    // 5.1 Updates the selector value to use the current color scheme which tells CSS to use the proper stylesheet.
    React.useEffect(function () {
      if (colorScheme && colorSchemeNode) {
        // attaches attribute to <html> because the css variables are attached to :root (html)
        colorSchemeNode.setAttribute(attribute, colorScheme);
      }
    }, [colorScheme, attribute, colorSchemeNode]);

    // 5.2 Remove the CSS transition when color scheme changes to create instant experience.
    // credit: https://github.com/pacocoursey/next-themes/blob/b5c2bad50de2d61ad7b52a9c5cdc801a78507d7a/index.tsx#L313
    React.useEffect(function () {
      var timer;
      if (disableTransitionOnChange && hasMounted.current && documentNode) {
        var css = documentNode.createElement('style');
        css.appendChild(documentNode.createTextNode(DISABLE_CSS_TRANSITION));
        documentNode.head.appendChild(css);

        // Force browser repaint
        (function () {
          return window.getComputedStyle(documentNode.body);
        })();
        timer = setTimeout(function () {
          documentNode.head.removeChild(css);
        }, 1);
      }
      return function () {
        clearTimeout(timer);
      };
    }, [colorScheme, disableTransitionOnChange, documentNode]);
    React.useEffect(function () {
      hasMounted.current = true;
      return function () {
        hasMounted.current = false;
      };
    }, []);
    var contextValue = React.useMemo(function () {
      return {
        mode: mode,
        systemMode: systemMode,
        setMode: setMode,
        lightColorScheme: lightColorScheme,
        darkColorScheme: darkColorScheme,
        colorScheme: colorScheme,
        setColorScheme: setColorScheme,
        allColorSchemes: allColorSchemes
      };
    }, [allColorSchemes, colorScheme, darkColorScheme, lightColorScheme, mode, setColorScheme, setMode, systemMode]);
    var shouldGenerateStyleSheet = true;
    if (disableStyleSheetGeneration || nested && (upperTheme == null ? void 0 : upperTheme.cssVarPrefix) === cssVarPrefix) {
      shouldGenerateStyleSheet = false;
    }
    var element = /*#__PURE__*/_jsxs(React.Fragment, {
      children: [shouldGenerateStyleSheet && /*#__PURE__*/_jsxs(React.Fragment, {
        children: [/*#__PURE__*/_jsx(GlobalStyles, {
          styles: _defineProperty({}, colorSchemeSelector, rootCss)
        }), /*#__PURE__*/_jsx(GlobalStyles, {
          styles: defaultColorSchemeStyleSheet
        }), /*#__PURE__*/_jsx(GlobalStyles, {
          styles: otherColorSchemesStyleSheet
        })]
      }), /*#__PURE__*/_jsx(ThemeProvider, {
        themeId: scopedTheme ? themeId : undefined,
        theme: resolveTheme ? resolveTheme(theme) : theme,
        children: children
      })]
    });
    if (nested) {
      return element;
    }
    return /*#__PURE__*/_jsx(ColorSchemeContext.Provider, {
      value: contextValue,
      children: element
    });
  }
  process.env.NODE_ENV !== "production" ? CssVarsProvider.propTypes = {
    /**
     * The body attribute name to attach colorScheme.
     */
    attribute: PropTypes.string,
    /**
     * The component tree.
     */
    children: PropTypes.node,
    /**
     * The node used to attach the color-scheme attribute
     */
    colorSchemeNode: PropTypes.any,
    /**
     * The CSS selector for attaching the generated custom properties
     */
    colorSchemeSelector: PropTypes.string,
    /**
     * localStorage key used to store `colorScheme`
     */
    colorSchemeStorageKey: PropTypes.string,
    /**
     * The initial color scheme used.
     */
    defaultColorScheme: PropTypes.oneOfType([PropTypes.string, PropTypes.object]),
    /**
     * The initial mode used.
     */
    defaultMode: PropTypes.string,
    /**
     * If `true`, the provider creates its own context and generate stylesheet as if it is a root `CssVarsProvider`.
     */
    disableNestedContext: PropTypes.bool,
    /**
     * If `true`, the style sheet won't be generated.
     *
     * This is useful for controlling nested CssVarsProvider behavior.
     */
    disableStyleSheetGeneration: PropTypes.bool,
    /**
     * Disable CSS transitions when switching between modes or color schemes.
     */
    disableTransitionOnChange: PropTypes.bool,
    /**
     * The document to attach the attribute to.
     */
    documentNode: PropTypes.any,
    /**
     * The key in the local storage used to store current color scheme.
     */
    modeStorageKey: PropTypes.string,
    /**
     * The window that attaches the 'storage' event listener.
     * @default window
     */
    storageWindow: PropTypes.any,
    /**
     * The calculated theme object that will be passed through context.
     */
    theme: PropTypes.object
  } : void 0;
  var defaultLightColorScheme = typeof designSystemColorScheme === 'string' ? designSystemColorScheme : designSystemColorScheme.light;
  var defaultDarkColorScheme = typeof designSystemColorScheme === 'string' ? designSystemColorScheme : designSystemColorScheme.dark;
  var getInitColorSchemeScript = function getInitColorSchemeScript(params) {
    return systemGetInitColorSchemeScript(_extends({
      attribute: defaultAttribute,
      colorSchemeStorageKey: defaultColorSchemeStorageKey,
      defaultMode: designSystemMode,
      defaultLightColorScheme: defaultLightColorScheme,
      defaultDarkColorScheme: defaultDarkColorScheme,
      modeStorageKey: defaultModeStorageKey
    }, params));
  };
  return {
    CssVarsProvider: CssVarsProvider,
    useColorScheme: useColorScheme,
    getInitColorSchemeScript: getInitColorSchemeScript
  };
}