import { isPlainObject } from 'lodash-es';
import { Fragment, isVNode, h, Comment, Text } from 'vue';
import classNames from '../classNames.mjs';
import { isOn, camelize, hyphenate, resolvePropValue } from '../util.mjs';
import { isValid } from '../is.mjs';
export { default as initDefaultProps } from './initDefaultProps.mjs';

const splitAttrs = (attrs) => {
  const allAttrs = Object.keys(attrs);
  const eventAttrs = {};
  const onEvents = {};
  const extraAttrs = {};
  for (let i = 0, l = allAttrs.length; i < l; i++) {
    const key = allAttrs[i];
    if (isOn(key)) {
      eventAttrs[key[2].toLowerCase() + key.slice(3)] = attrs[key];
      onEvents[key] = attrs[key];
    } else {
      extraAttrs[key] = attrs[key];
    }
  }
  return { onEvents, events: eventAttrs, extraAttrs };
};
const parseStyleText = (cssText = "", camel) => {
  const res = {};
  const listDelimiter = /;(?![^(]*\))/g;
  const propertyDelimiter = /:(.+)/;
  if (typeof cssText === "object")
    return cssText;
  cssText.split(listDelimiter).forEach((item) => {
    if (item) {
      const tmp = item.split(propertyDelimiter);
      if (tmp.length > 1) {
        const k = camel ? camelize(tmp[0].trim()) : tmp[0].trim();
        res[k] = tmp[1].trim();
      }
    }
  });
  return res;
};
const hasProp = (instance, prop) => {
  return instance[prop] !== void 0;
};
const slotHasProp = (slot, prop) => {
  return hasProp(slot, prop);
};
const getScopedSlots = (ele) => {
  return ele.data && ele.data.scopedSlots || {};
};
const getSlots = (ele) => {
  let componentOptions = ele.componentOptions || {};
  if (ele.$vnode)
    componentOptions = ele.$vnode.componentOptions || {};
  const children = ele.children || componentOptions.children || [];
  const slots = {};
  children.forEach((child) => {
    if (!isEmptyElement(child)) {
      const name = child.data && child.data.slot || "default";
      slots[name] = slots[name] || [];
      slots[name].push(child);
    }
  });
  return { ...slots, ...getScopedSlots(ele) };
};
const skipFlattenKey = Symbol("skipFlatten");
const flattenChildren = (children = [], filterEmpty2 = true) => {
  const temp = Array.isArray(children) ? children : [children];
  const res = [];
  temp.forEach((child) => {
    if (Array.isArray(child)) {
      res.push(...flattenChildren(child, filterEmpty2));
    } else if (child && child.type === Fragment) {
      if (child.key === skipFlattenKey)
        res.push(child);
      else
        res.push(...flattenChildren(child.children, filterEmpty2));
    } else if (child && isVNode(child)) {
      if (filterEmpty2 && !isEmptyElement(child))
        res.push(child);
      else if (!filterEmpty2)
        res.push(child);
    } else if (isValid(child)) {
      res.push(child);
    }
  });
  return res;
};
const getSlot = (self, name = "default", options = {}) => {
  if (isVNode(self)) {
    if (self.type === Fragment)
      return name === "default" ? flattenChildren(self.children) : [];
    else if (self.children && self.children[name])
      return flattenChildren(self.children[name](options));
    else
      return [];
  } else {
    const res = self.$slots[name] && self.$slots[name](options);
    return flattenChildren(res);
  }
};
const getAllChildren = (ele) => {
  let componentOptions = ele.componentOptions || {};
  if (ele.$vnode)
    componentOptions = ele.$vnode.componentOptions || {};
  return ele.children || componentOptions.children || [];
};
const getSlotOptions = () => {
  throw new Error("\u4F7F\u7528 .type \u76F4\u63A5\u53D6\u503C");
};
const findDOMNode = (instance) => {
  var _a;
  let node = ((_a = instance == null ? void 0 : instance.vnode) == null ? void 0 : _a.el) || instance && (instance.$el || instance);
  while (node && !node.tagName)
    node = node.nextSibling;
  return node;
};
const getOptionProps = (instance) => {
  const res = {};
  if (instance.$ && instance.$.vnode) {
    const props = instance.$.vnode.props || {};
    Object.keys(instance.$props).forEach((k) => {
      const v = instance.$props[k];
      const hyphenateKey = hyphenate(k);
      if (v !== void 0 || hyphenateKey in props)
        res[k] = v;
    });
  } else if (isVNode(instance) && typeof instance.type === "object") {
    const originProps = instance.props || {};
    const props = {};
    Object.keys(originProps).forEach((key) => {
      props[camelize(key)] = originProps[key];
    });
    const options = instance.type.props || {};
    Object.keys(options).forEach((k) => {
      const v = resolvePropValue(options, props, k, props[k]);
      if (v !== void 0 || k in props)
        res[k] = v;
    });
  }
  return res;
};
const getComponent = (instance, prop = "default", options = instance, execute = true) => {
  let com;
  if (instance.$) {
    const temp = instance[prop];
    if (temp !== void 0) {
      return typeof temp === "function" && execute ? temp(options) : temp;
    } else {
      com = instance.$slots[prop];
      com = execute && com ? com(options) : com;
    }
  } else if (isVNode(instance)) {
    const temp = instance.props && instance.props[prop];
    if (temp !== void 0 && instance.props !== null) {
      return typeof temp === "function" && execute ? temp(options) : temp;
    } else if (instance.type === Fragment) {
      com = instance.children;
    } else if (instance.children && instance.children[prop]) {
      com = instance.children[prop];
      com = execute && com ? com(options) : com;
    }
  }
  if (Array.isArray(com)) {
    com = flattenChildren(com);
    com = com.length === 1 ? com[0] : com;
    com = com.length === 0 ? void 0 : com;
  }
  return com;
};
const getPropsData = (ins) => {
  const vnode = ins.$ ? ins.$ : ins;
  const res = {};
  const originProps = vnode.props || {};
  const props = {};
  Object.keys(originProps).forEach((key) => {
    props[camelize(key)] = originProps[key];
  });
  const options = isPlainObject(vnode.type) ? vnode.type.props : {};
  options && Object.keys(options).forEach((k) => {
    const v = resolvePropValue(options, props, k, props[k]);
    if (k in props) {
      res[k] = v;
    }
  });
  return { ...props, ...res };
};
const getComponentFromProp = (instance, prop, options = instance, execute = true) => {
  if (instance.$createElement) {
    const temp = instance[prop];
    if (temp !== void 0)
      return typeof temp === "function" && execute ? temp(h, options) : temp;
    return instance.$scopedSlots[prop] && execute && instance.$scopedSlots[prop](options) || instance.$scopedSlots[prop] || instance.$slots[prop] || void 0;
  } else {
    const temp = getPropsData(instance)[prop];
    if (temp !== void 0)
      return typeof temp === "function" && execute ? temp(h, options) : temp;
    const slotScope = getScopedSlots(instance)[prop];
    if (slotScope !== void 0)
      return typeof slotScope === "function" && execute ? slotScope(h, options) : slotScope;
    const slotsProp = [];
    const componentOptions = instance.componentOptions || {};
    (componentOptions.children || []).forEach((child) => {
      if (child.data && child.data.slot === prop) {
        if (child.data.attrs)
          delete child.data.attrs.slot;
        if (child.tag === "template")
          slotsProp.push(child.children);
        else
          slotsProp.push(child);
      }
    });
    return slotsProp.length ? slotsProp : void 0;
  }
};
const getAllProps = (ele) => {
  let props = getOptionProps(ele);
  if (ele.$)
    props = { ...props, ...(void 0).$attrs };
  else
    props = { ...ele.props, ...props };
  return props;
};
const getValueByProp = (ele, prop) => {
  return getPropsData(ele)[prop];
};
const getAttrs = (ele) => {
  let data = ele.data;
  if (ele.$vnode)
    data = ele.$vnode.data;
  return data ? data.attrs || {} : {};
};
const getKey = (ele) => {
  const key = ele.key;
  return key;
};
function getEvents(ele = {}, on = true) {
  let props = {};
  if (ele.$) {
    props = { ...props, ...ele.$attrs };
  } else {
    props = { ...props, ...ele.props };
  }
  return splitAttrs(props)[on ? "onEvents" : "events"];
}
function getEvent(child, event) {
  return child.props && child.props[event];
}
function getDataEvents(child) {
  let events = {};
  if (child.data && child.data.on)
    events = child.data.on;
  return { ...events };
}
function getListeners(context) {
  return (context.$vnode ? context.$vnode.componentOptions.listeners : context.$listeners) || {};
}
function getClass(ele) {
  const props = (isVNode(ele) ? ele.props : ele.$attrs) || {};
  const tempCls = props.class || {};
  let cls = {};
  if (typeof tempCls === "string") {
    tempCls.split(" ").forEach((c) => {
      cls[c.trim()] = true;
    });
  } else if (Array.isArray(tempCls)) {
    classNames(tempCls).split(" ").forEach((c) => {
      cls[c.trim()] = true;
    });
  } else {
    cls = { ...cls, ...tempCls };
  }
  return cls;
}
function getStyle(ele, camel = false) {
  const props = (isVNode(ele) ? ele.props : ele.$attrs) || {};
  let style = props.style || {};
  if (typeof style === "string") {
    style = parseStyleText(style, camel);
  } else if (camel && style) {
    const res = {};
    Object.keys(style).forEach((k) => res[camelize(k)] = style[k]);
    return res;
  }
  return style;
}
function getComponentName(opts) {
  return opts && (opts.Ctor.options.name || opts.tag);
}
function isFragment(c) {
  return c.length === 1 && c[0].type === Fragment;
}
function isEmptyContent(c) {
  return c === void 0 || c === null || c === "" || Array.isArray(c) && c.length === 0;
}
function isEmptyElement(c) {
  return c && (c.type === Comment || c.type === Fragment && c.children.length === 0 || c.type === Text && c.children.trim() === "");
}
function isEmptySlot(c) {
  return !c || c().every(isEmptyElement);
}
function isStringElement(c) {
  return c && c.type === Text;
}
function filterEmpty(children = []) {
  const res = [];
  children.forEach((child) => {
    if (Array.isArray(child))
      res.push(...child);
    else if ((child == null ? void 0 : child.type) === Fragment)
      res.push(...filterEmpty(child.children));
    else
      res.push(child);
  });
  return res.filter((c) => !isEmptyElement(c));
}
function filterEmptyWithUndefined(children) {
  if (children) {
    const coms = filterEmpty(children);
    return coms.length ? coms : void 0;
  } else {
    return children;
  }
}
function mergeProps() {
  const args = [].slice.call(arguments, 0);
  const props = {};
  args.forEach((p = {}) => {
    for (const [k, v] of Object.entries(p)) {
      props[k] = props[k] || {};
      if (isPlainObject(v))
        Object.assign(props[k], v);
      else
        props[k] = v;
    }
  });
  return props;
}
function isValidElement(element) {
  if (Array.isArray(element) && element.length === 1)
    element = element[0];
  return element && element.__v_isVNode && typeof element.type !== "symbol";
}
function getPropsSlot(slots, props, prop = "default") {
  var _a, _b;
  return (_b = props[prop]) != null ? _b : (_a = slots[prop]) == null ? void 0 : _a.call(slots);
}
const getTextFromElement = (ele) => {
  if (isValidElement(ele) && isStringElement(ele[0]))
    return ele[0].children;
  return ele;
};

export { camelize, hasProp as default, filterEmpty, filterEmptyWithUndefined, findDOMNode, flattenChildren, getAllChildren, getAllProps, getAttrs, getClass, getComponent, getComponentFromProp, getComponentName, getDataEvents, getEvent, getEvents, getKey, getListeners, getOptionProps, getPropsData, getPropsSlot, getSlot, getSlotOptions, getSlots, getStyle, getTextFromElement, getValueByProp, hasProp, isEmptyContent, isEmptyElement, isEmptySlot, isFragment, isStringElement, isValidElement, mergeProps, parseStyleText, skipFlattenKey, slotHasProp, splitAttrs };
//# sourceMappingURL=index.mjs.map
