import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
import _typeof from "@babel/runtime/helpers/typeof";
/* eslint-disable @atlaskit/design-system/ensure-design-token-usage */
import { css as cssEmotion } from '@emotion/react';
import { media } from '../responsive/media-helper';
import { backgroundColorMap, borderColorMap, borderRadiusMap, borderWidthMap, dimensionMap, layerMap, shadowMap, spaceMap, textColorMap } from './style-maps.partial';
var tokensMap = {
  backgroundColor: backgroundColorMap,
  blockSize: dimensionMap,
  borderColor: borderColorMap,
  borderRadius: borderRadiusMap,
  borderWidth: borderWidthMap,
  bottom: spaceMap,
  boxShadow: shadowMap,
  color: textColorMap,
  columnGap: spaceMap,
  gap: spaceMap,
  height: dimensionMap,
  inlineSize: dimensionMap,
  inset: spaceMap,
  insetBlock: spaceMap,
  insetBlockEnd: spaceMap,
  insetBlockStart: spaceMap,
  insetInline: spaceMap,
  insetInlineEnd: spaceMap,
  insetInlineStart: spaceMap,
  margin: spaceMap,
  marginBlock: spaceMap,
  marginBlockEnd: spaceMap,
  marginBlockStart: spaceMap,
  marginInline: spaceMap,
  marginInlineEnd: spaceMap,
  marginInlineStart: spaceMap,
  left: spaceMap,
  maxBlockSize: dimensionMap,
  maxHeight: dimensionMap,
  maxInlineSize: dimensionMap,
  maxWidth: dimensionMap,
  minBlockSize: dimensionMap,
  minHeight: dimensionMap,
  minInlineSize: dimensionMap,
  minWidth: dimensionMap,
  outlineOffset: spaceMap,
  outlineWidth: borderWidthMap,
  outlineColor: borderColorMap,
  padding: spaceMap,
  paddingBlock: spaceMap,
  paddingBlockEnd: spaceMap,
  paddingBlockStart: spaceMap,
  paddingBottom: spaceMap,
  paddingInline: spaceMap,
  paddingInlineEnd: spaceMap,
  paddingInlineStart: spaceMap,
  paddingLeft: spaceMap,
  paddingRight: spaceMap,
  paddingTop: spaceMap,
  right: spaceMap,
  rowGap: spaceMap,
  top: spaceMap,
  width: dimensionMap,
  zIndex: layerMap
};
var uniqueSymbol = Symbol('UNSAFE_INTERNAL_styles');
var isSafeEnvToThrow = function isSafeEnvToThrow() {
  return (typeof process === "undefined" ? "undefined" : _typeof(process)) === 'object' && _typeof(process.env) === 'object' && process.env.NODE_ENV !== 'production';
};
var reNestedSelectors = /(\.|\s|&+|\*\>|#|\[.*\])/;
var rePseudos = /^::?.*$/;
var reMediaQuery = /^@media .*$/;

/**
 * Reduce our media queries into a safe string for regex comparison.
 */
var reValidMediaQuery = new RegExp("^(".concat(Object.values(media.above).map(function (mediaQuery) {
  return mediaQuery.replace(/[.()]/g, '\\$&');
} // Escape the ".", "(", and ")" in the media query syntax.
).join('|'), ")$"));
var transformStyles = function transformStyles(styleObj) {
  if (!styleObj || _typeof(styleObj) !== 'object') {
    return styleObj;
  }

  // If styles are defined as a CSSObject[], recursively call on each element until we reach CSSObject
  if (Array.isArray(styleObj)) {
    return styleObj.map(transformStyles);
  }

  // Modifies styleObj in place. Be careful.
  Object.entries(styleObj).forEach(function (_ref) {
    var _ref2 = _slicedToArray(_ref, 2),
      key = _ref2[0],
      value = _ref2[1];
    if (isSafeEnvToThrow()) {
      // We don't support `.class`, `[data-testid]`, `> *`, `#some-id`
      if (reNestedSelectors.test(key) && !reValidMediaQuery.test(key)) {
        throw new Error("Styles not supported for key '".concat(key, "'."));
      }
    }

    // If key is a pseudo class or a pseudo element, then value should be an object.
    // So, call transformStyles on the value
    if (rePseudos.test(key)) {
      styleObj[key] = transformStyles(value);
      return;
    }
    if (reMediaQuery.test(key)) {
      // @ts-expect-error
      styleObj[key] = transformStyles(value);
      return;
    }

    // We have now dealt with all the special cases, so,
    // check whether what remains is a style property
    // that can be transformed.
    if (!(key in tokensMap)) {
      return;
    }
    var tokenValue = tokensMap[key][value];
    styleObj[key] = tokenValue !== null && tokenValue !== void 0 ? tokenValue : value;
  });
  return styleObj;
};
var baseXcss = function baseXcss(style) {
  var transformedStyles = transformStyles(style);
  return _defineProperty({}, uniqueSymbol, cssEmotion(transformedStyles));
};

/**
 * @internal used in primitives
 * @returns a collection of styles that can be applied to the respective primitive
 */

export var parseXcss = function parseXcss(args) {
  if (Array.isArray(args)) {
    return args.map(function (x) {
      return x && parseXcss(x);
    }).filter(Boolean);
  }
  var styles = args[uniqueSymbol];
  if ((typeof process === "undefined" ? "undefined" : _typeof(process)) && process.env.NODE_ENV === 'development' && typeof styles === 'undefined') {
    throw new Error('Styles generated from unsafe source, use the `xcss` export from `@atlaskit/primitives`.');
  }
  return styles;
};

// Media queries should not contain nested media queries

// Pseudos should not contain nested pseudos, or media queries

// unused private functions only so we can extract the return type from a generic function
var boxWrapper = function boxWrapper(style) {
  return xcss(style);
};
var spaceWrapper = function spaceWrapper(style) {
  return xcss(style);
};
/**
 * ### xcss
 *
 * `xcss` is a safer, tokens-first approach to CSS-in-JS. It allows token-backed values for
 * CSS application.
 *
 * ```tsx
 * const styles = xcss({
 *   padding: 'space.100'
 * })
 * ```
 */
export function xcss(style) {
  return baseXcss(style);
}