const SWC_NOT_FOUND = Symbol("SWC_NOT_FOUND");
class SwcUtils {
  static getValueByPath(obj, path, rootName) {
    if (!obj || !path) return SWC_NOT_FOUND;
    const parts = path.split(".");
    if (parts[0] === rootName && parts.length > 1) {
      const subParts = parts.slice(1);
      let subResult = obj;
      for (const part of subParts) {
        if (subResult === null || subResult === void 0 || !(part in subResult)) return SWC_NOT_FOUND;
        subResult = subResult[part];
      }
      return subResult;
    }
    let result = obj;
    for (const part of parts) {
      if (result === null || result === void 0 || !(part in result)) {
        return SWC_NOT_FOUND;
      }
      result = result[part];
    }
    if (result !== obj && !(result instanceof HTMLElement)) {
      return result;
    }
    return SWC_NOT_FOUND;
  }
  static evalExpression(expr, context) {
    try {
      const keys = Object.keys(context);
      const values = Object.values(context);
      return new Function(...keys, `return (${expr})`).apply(null, values);
    } catch {
      return SWC_NOT_FOUND;
    }
  }
  static applyData(node, data, options) {
    const { asKey, asIndexKey, index, hostContext } = options;
    const context = {};
    if (index !== void 0) {
      context[asIndexKey] = index;
    }
    if (data !== null && data !== void 0) {
      context[asKey] = data;
    }
    const fullContext = { ...hostContext || {}, ...context };
    const resolveExpr = (expr, match) => {
      expr = expr.trim();
      const simpleVal = SwcUtils.getValueByPath(data, expr, asKey);
      if (simpleVal !== SWC_NOT_FOUND && typeof simpleVal !== "symbol") {
        return simpleVal === null || simpleVal === void 0 ? "" : String(simpleVal);
      }
      const exprVal = SwcUtils.evalExpression(expr, fullContext);
      if (exprVal !== SWC_NOT_FOUND && typeof exprVal !== "symbol") {
        return exprVal === null || exprVal === void 0 ? "" : String(exprVal);
      }
      return match;
    };
    const walk = (n) => {
      if (n.nodeType === Node.TEXT_NODE) {
        if (!n._original) n._original = n.textContent;
        let text = n._original;
        text = text.replace(/{{(.*?)}}/g, (match, path) => {
          return resolveExpr(path, match);
        });
        if (n.textContent !== text) n.textContent = text;
      } else if (n.nodeType === Node.ELEMENT_NODE) {
        const el = n;
        Array.from(el.attributes).forEach((a) => {
          if (!a._original) a._original = a.value;
          let val = a._original;
          val = val.replace(/{{(.*?)}}/g, (match, path) => {
            return resolveExpr(path, match);
          });
          if (a.value !== val) a.value = val;
        });
        el.childNodes.forEach(walk);
      }
    };
    walk(node);
  }
  static createReactiveProxy(target, onChange, onIndexChange) {
    const makeRecursiveProxy = (obj) => {
      if (typeof obj !== "object" || obj === null || obj instanceof Node) return obj;
      if (obj.__swc_is_proxy) return obj;
      const IS_PROXY_KEY = "__swc_is_proxy";
      const proxy = new Proxy(obj, {
        get: (t, prop) => {
          if (prop === IS_PROXY_KEY) return true;
          if (typeof prop === "symbol") return t[prop];
          return t[prop];
        },
        set: (t, prop, val) => {
          if (prop === IS_PROXY_KEY) return true;
          if (typeof prop === "symbol") {
            t[prop] = val;
            return true;
          }
          const oldVal = t[prop];
          if (oldVal === val) return true;
          t[prop] = makeRecursiveProxy(val);
          const isIndex = !isNaN(Number(prop)) && Array.isArray(t);
          if (isIndex && onIndexChange) {
            onIndexChange(Number(prop), val);
          } else {
            onChange();
          }
          return true;
        },
        deleteProperty: (t, prop) => {
          delete t[prop];
          onChange();
          return true;
        }
      });
      return proxy;
    };
    return makeRecursiveProxy(target);
  }
  static findNearestSwcHost(el) {
    const hosts = this.findAllSwcHosts(el);
    return hosts.length > 0 ? hosts[0] : null;
  }
  static findAllSwcHosts(el) {
    const hosts = [];
    let curr = el instanceof Node && !(el instanceof HTMLElement) ? el.host : el;
    curr = curr?.parentElement || curr?.getRootNode()?.host;
    while (curr) {
      if (curr._swcId) hosts.push(curr);
      curr = curr.parentElement || curr.getRootNode().host;
    }
    return hosts.reverse();
  }
}
export {
  SWC_NOT_FOUND,
  SwcUtils
};
//# sourceMappingURL=Utils.js.map
