'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var hash = require('@emotion/hash');
var unitless = require('@emotion/unitless');
var stylis = require('stylis');
var vue = require('vue');
require('../../../../utils/index.cjs');
require('../../linters/index.cjs');
var StyleContext = require('../../StyleContext.cjs');
var util = require('../../util.cjs');
var useGlobalCache = require('../useGlobalCache.cjs');
var cacheMapUtil = require('./cacheMapUtil.cjs');
var canUseDom = require('../../../../utils/dom/canUseDom.cjs');
var contentQuotesLinter = require('../../linters/contentQuotesLinter.cjs');
var hashedAnimationLinter = require('../../linters/hashedAnimationLinter.cjs');
var dynamicCSS = require('../../../../utils/dom/dynamicCSS.cjs');

const isClientSide = canUseDom.canUseDom();
const SKIP_CHECK = "_skip_check_";
const MULTI_VALUE = "_multi_value_";
function normalizeStyle(styleStr) {
  const serialized = stylis.serialize(stylis.compile(styleStr), stylis.stringify);
  return serialized.replace(/\{%%%\:[^;];}/g, ";");
}
function isCompoundCSSProperty(value) {
  return typeof value === "object" && value && (SKIP_CHECK in value || MULTI_VALUE in value);
}
function injectSelectorHash(key, hashId, hashPriority) {
  if (!hashId)
    return key;
  const hashClassName = `.${hashId}`;
  const hashSelector = hashPriority === "low" ? `:where(${hashClassName})` : hashClassName;
  const keys = key.split(",").map((k) => {
    var _a;
    const fullPath = k.trim().split(/\s+/);
    let firstPath = fullPath[0] || "";
    const htmlElement = ((_a = firstPath.match(/^\w+/)) == null ? void 0 : _a[0]) || "";
    firstPath = `${htmlElement}${hashSelector}${firstPath.slice(htmlElement.length)}`;
    return [firstPath, ...fullPath.slice(1)].join(" ");
  });
  return keys.join(",");
}
const globalEffectStyleKeys = /* @__PURE__ */ new Set();
const _cf = process.env.NODE_ENV !== "production" ? () => globalEffectStyleKeys.clear() : void 0;
function parseStyle(interpolation, config = {}, {
  root,
  injectHash,
  parentSelectors
} = {
  root: true,
  parentSelectors: []
}) {
  const {
    hashId,
    layer,
    path,
    hashPriority,
    transformers = [],
    linters = []
  } = config;
  let styleStr = "";
  let effectStyle = {};
  function parseKeyframes(keyframes) {
    const animationName = keyframes.getName(hashId);
    if (!effectStyle[animationName]) {
      const [parsedStr] = parseStyle(keyframes.style, config, {
        root: false,
        parentSelectors
      });
      effectStyle[animationName] = `@keyframes ${keyframes.getName(hashId)}${parsedStr}`;
    }
  }
  function flattenList(list, fullList = []) {
    list.forEach((item) => {
      if (Array.isArray(item))
        flattenList(item, fullList);
      else if (item)
        fullList.push(item);
    });
    return fullList;
  }
  const flattenStyleList = flattenList(Array.isArray(interpolation) ? interpolation : [interpolation]);
  flattenStyleList.forEach((originStyle) => {
    const style = typeof originStyle === "string" && !root ? {} : originStyle;
    if (typeof style === "string") {
      styleStr += `${style}
`;
    } else if (style._keyframe) {
      parseKeyframes(style);
    } else {
      const mergedStyle = transformers.reduce((prev, trans) => {
        var _a;
        return ((_a = trans == null ? void 0 : trans.visit) == null ? void 0 : _a.call(trans, prev)) || prev;
      }, style);
      Object.keys(mergedStyle).forEach((key) => {
        var _a;
        const value = mergedStyle[key];
        if (typeof value === "object" && value && (key !== "animationName" || !value._keyframe) && !isCompoundCSSProperty(value)) {
          let subInjectHash = false;
          let mergedKey = key.trim();
          let nextRoot = false;
          if ((root || injectHash) && hashId) {
            if (mergedKey.startsWith("@")) {
              subInjectHash = true;
            } else {
              mergedKey = injectSelectorHash(key, hashId, hashPriority);
            }
          } else if (root && !hashId && (mergedKey === "&" || mergedKey === "")) {
            mergedKey = "";
            nextRoot = true;
          }
          const [parsedStr, childEffectStyle] = parseStyle(value, config, {
            root: nextRoot,
            injectHash: subInjectHash,
            parentSelectors: [...parentSelectors, mergedKey]
          });
          effectStyle = {
            ...effectStyle,
            ...childEffectStyle
          };
          styleStr += `${mergedKey}${parsedStr}`;
        } else {
          let appendStyle = function(cssKey, cssValue) {
            if (process.env.NODE_ENV !== "production" && (typeof value !== "object" || !(value == null ? void 0 : value[SKIP_CHECK]))) {
              [contentQuotesLinter.default, hashedAnimationLinter.default, ...linters].forEach((linter) => linter(cssKey, cssValue, {
                path,
                hashId,
                parentSelectors
              }));
            }
            const styleName = cssKey.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`);
            let formatValue = cssValue;
            if (!unitless[cssKey] && typeof formatValue === "number" && formatValue !== 0)
              formatValue = `${formatValue}px`;
            if (cssKey === "animationName" && (cssValue == null ? void 0 : cssValue._keyframe)) {
              parseKeyframes(cssValue);
              formatValue = cssValue.getName(hashId);
            }
            styleStr += `${styleName}:${formatValue};`;
          };
          const actualValue = (_a = value == null ? void 0 : value.value) != null ? _a : value;
          if (typeof value === "object" && (value == null ? void 0 : value[MULTI_VALUE]) && Array.isArray(actualValue)) {
            actualValue.forEach((item) => {
              appendStyle(key, item);
            });
          } else {
            appendStyle(key, actualValue);
          }
        }
      });
    }
  });
  if (!root) {
    styleStr = `{${styleStr}}`;
  } else if (layer && util.supportLayer()) {
    const layerCells = layer.split(",");
    const layerName = layerCells[layerCells.length - 1].trim();
    styleStr = `@layer ${layerName} {${styleStr}}`;
    if (layerCells.length > 1) {
      styleStr = `@layer ${layer}{%%%:%}${styleStr}`;
    }
  }
  return [styleStr, effectStyle];
}
function uniqueHash(path, styleStr) {
  return hash(`${path.join("%")}${styleStr}`);
}
function useStyleRegister(info, styleFn) {
  const styleContext = StyleContext.useStyleInject();
  const tokenKey = vue.computed(() => info.value.token._tokenKey);
  const fullPath = vue.computed(() => [tokenKey.value, ...info.value.path]);
  let isMergedClientSide = isClientSide;
  if (process.env.NODE_ENV !== "production" && styleContext.value.mock !== void 0)
    isMergedClientSide = styleContext.value.mock === "client";
  useGlobalCache.default(
    "style",
    fullPath,
    // Create cache if needed
    () => {
      const {
        path,
        hashId,
        layer,
        nonce,
        clientOnly,
        order = 0
      } = info.value;
      const cachePath = fullPath.value.join("|");
      if (cacheMapUtil.existPath(cachePath)) {
        const [inlineCacheStyleStr, styleHash] = cacheMapUtil.getStyleAndHash(cachePath);
        if (inlineCacheStyleStr)
          return [inlineCacheStyleStr, tokenKey.value, styleHash, {}, clientOnly, order];
      }
      const styleObj = styleFn();
      const {
        hashPriority,
        container,
        transformers,
        linters,
        cache
      } = styleContext.value;
      const [parsedStyle, effectStyle] = parseStyle(styleObj, {
        hashId,
        hashPriority,
        layer,
        path: path.join("-"),
        transformers,
        linters
      });
      const styleStr = normalizeStyle(parsedStyle);
      const styleId = uniqueHash(fullPath.value, styleStr);
      if (isMergedClientSide) {
        const mergedCSSConfig = {
          mark: StyleContext.ATTR_MARK,
          prepend: "queue",
          attachTo: container,
          priority: order
        };
        const nonceStr = typeof nonce === "function" ? nonce() : nonce;
        if (nonceStr)
          mergedCSSConfig.csp = {
            nonce: nonceStr
          };
        const style = dynamicCSS.updateCSS(styleStr, styleId, mergedCSSConfig);
        style[StyleContext.CSS_IN_JS_INSTANCE] = cache.instanceId;
        style.setAttribute(StyleContext.ATTR_TOKEN, tokenKey.value);
        if (process.env.NODE_ENV !== "production")
          style.setAttribute(StyleContext.ATTR_CACHE_PATH, fullPath.value.join("|"));
        Object.keys(effectStyle).forEach((effectKey) => {
          if (!globalEffectStyleKeys.has(effectKey)) {
            globalEffectStyleKeys.add(effectKey);
            dynamicCSS.updateCSS(normalizeStyle(effectStyle[effectKey]), `_effect-${effectKey}`, {
              mark: StyleContext.ATTR_MARK,
              prepend: "queue",
              attachTo: container
            });
          }
        });
      }
      return [styleStr, tokenKey.value, styleId, effectStyle, clientOnly, order];
    },
    // Remove cache if no need
    ([, , styleId], fromHMR) => {
      if ((fromHMR || styleContext.value.autoClear) && isClientSide)
        dynamicCSS.removeCSS(styleId, {
          mark: StyleContext.ATTR_MARK
        });
    }
  );
  return (node) => {
    return node;
  };
}
function extractStyle(cache, plain = false) {
  const matchPrefix = "style%";
  const styleKeys = Array.from(cache.cache.keys()).filter((key) => key.startsWith(matchPrefix));
  const effectStyles = {};
  const cachePathMap = {};
  let styleText = "";
  function toStyleStr(style, tokenKey, styleId, customizeAttrs = {}) {
    const attrs = {
      ...customizeAttrs,
      [StyleContext.ATTR_TOKEN]: tokenKey,
      [StyleContext.ATTR_MARK]: styleId
    };
    const attrStr = Object.keys(attrs).map((attr) => {
      const val = attrs[attr];
      return val ? `${attr}="${val}"` : null;
    }).filter((v) => v).join(" ");
    return plain ? style : `<style ${attrStr}>${style}</style>`;
  }
  const orderStyles = styleKeys.map((key) => {
    const cachePath = key.slice(matchPrefix.length).replace(/%/g, "|");
    const [styleStr, tokenKey, styleId, effectStyle, clientOnly, order] = cache.cache.get(key)[1];
    if (clientOnly)
      return null;
    const sharedAttrs = {
      "data-vc-order": "prependQueue",
      "data-vc-priority": `${order}`
    };
    let keyStyleText = toStyleStr(styleStr, tokenKey, styleId, sharedAttrs);
    cachePathMap[cachePath] = styleId;
    if (effectStyle) {
      Object.keys(effectStyle).forEach((effectKey) => {
        if (!effectStyles[effectKey]) {
          effectStyles[effectKey] = true;
          keyStyleText += toStyleStr(normalizeStyle(effectStyle[effectKey]), tokenKey, `_effect-${effectKey}`, sharedAttrs);
        }
      });
    }
    const ret = [order, keyStyleText];
    return ret;
  }).filter((o) => o);
  orderStyles.sort((o1, o2) => o1[0] - o2[0]).forEach(([, style]) => {
    styleText += style;
  });
  styleText += toStyleStr(`.${cacheMapUtil.ATTR_CACHE_MAP}{content:"${cacheMapUtil.serialize(cachePathMap)}";}`, void 0, void 0, {
    [cacheMapUtil.ATTR_CACHE_MAP]: cacheMapUtil.ATTR_CACHE_MAP
  });
  return styleText;
}

exports._cf = _cf;
exports.default = useStyleRegister;
exports.extractStyle = extractStyle;
exports.normalizeStyle = normalizeStyle;
exports.parseStyle = parseStyle;
//# sourceMappingURL=index.cjs.map
