import style_default from "./style/index.js";
import { XBubble } from "./Bubble.js";
import { XBubbleDivider } from "./Divider.js";
import { useCompatibleScroll } from "./hooks/useCompatibleScroll.js";
import { XBubbleSystem } from "./System.js";
import { computed, createVNode, defineComponent, mergeProps, ref } from "vue";
//#region components/bubble/BubbleList.tsx
function roleCfgIsFunction(roleCfg) {
	return typeof roleCfg === "function";
}
function pickBubbleRef(instance) {
	if (!instance) return null;
	if ("nativeElement" in instance) return instance.nativeElement ?? null;
	return instance;
}
var bubbleSlotNames = [
	"contentRender",
	"loadingRender",
	"avatar",
	"header",
	"footer",
	"extra"
];
var XBubbleList = /* @__PURE__ */ defineComponent({
	name: "AxBubbleList",
	inheritAttrs: false,
	props: {
		prefixCls: {
			type: String,
			default: "antd-bubble"
		},
		styles: {
			type: Object,
			default: () => ({})
		},
		classes: {
			type: Object,
			default: () => ({})
		},
		rootClass: {
			type: String,
			default: ""
		},
		style: {
			type: [
				String,
				Object,
				Array
			],
			default: void 0
		},
		class: {
			type: [
				String,
				Array,
				Object
			],
			default: void 0
		},
		items: {
			type: Array,
			required: true
		},
		autoScroll: {
			type: Boolean,
			default: true
		},
		role: {
			type: Object,
			default: void 0
		},
		onScroll: {
			type: Function,
			default: void 0
		}
	},
	setup(props, { expose, attrs, slots }) {
		const rootRef = ref();
		const scrollBoxRef = ref();
		const scrollContentRef = ref();
		const bubbleRefs = /* @__PURE__ */ new Map();
		const [hashId, cssVarCls] = style_default(computed(() => props.prefixCls));
		const { scrollTo: compatibleScrollTo } = useCompatibleScroll(scrollBoxRef, scrollContentRef);
		const listPrefixCls = computed(() => `${props.prefixCls}-list`);
		const handleScroll = (event) => {
			props.onScroll?.(event);
		};
		const mergedItems = computed(() => {
			return props.items.map((item) => {
				if (item.role && props.role) {
					const cfg = props.role[item.role];
					if (cfg) return {
						...roleCfgIsFunction(cfg) ? cfg(item) : cfg,
						...item
					};
				}
				return item;
			});
		});
		const bubbleClassNames = computed(() => {
			const { root: _root, scroll: _scroll, bubble, system, divider, ...rest } = props.classes || {};
			return {
				bubble,
				system,
				divider,
				rest
			};
		});
		const bubbleStyles = computed(() => {
			const { root: _root, scroll: _scroll, bubble, system, divider, ...rest } = props.styles || {};
			return {
				bubble,
				system,
				divider,
				rest
			};
		});
		const setBubbleRef = (key) => (instance) => {
			const element = pickBubbleRef(instance);
			if (element) bubbleRefs.set(key, element);
			else bubbleRefs.delete(key);
		};
		const scrollTo = ({ key, top, behavior = "smooth", block }) => {
			const scrollBox = scrollBoxRef.value;
			if (!scrollBox) return;
			const { scrollHeight, clientHeight } = scrollBox;
			if (typeof top === "number") {
				compatibleScrollTo({
					top: props.autoScroll ? -scrollHeight + clientHeight + top : top,
					behavior
				});
				return;
			}
			if (top === "bottom") {
				compatibleScrollTo({
					top: props.autoScroll ? 0 : scrollHeight,
					behavior
				});
				return;
			}
			if (top === "top") {
				compatibleScrollTo({
					top: props.autoScroll ? -scrollHeight : 0,
					behavior
				});
				return;
			}
			if (key !== void 0) {
				const target = bubbleRefs.get(key);
				if (!target) return;
				compatibleScrollTo({
					intoView: {
						behavior,
						block: block ?? "nearest"
					},
					intoViewDom: target
				});
			}
		};
		expose({
			get nativeElement() {
				return rootRef.value;
			},
			get scrollBoxNativeElement() {
				return scrollBoxRef.value;
			},
			scrollTo
		});
		return () => createVNode("div", mergeProps({ "ref": rootRef }, attrs, {
			"class": [
				listPrefixCls.value,
				props.rootClass,
				props.classes?.root,
				hashId.value,
				cssVarCls.value,
				props.class,
				attrs.class
			],
			"style": [
				props.styles?.root,
				props.style,
				attrs.style
			]
		}), [createVNode("div", {
			"ref": scrollBoxRef,
			"class": [
				`${listPrefixCls.value}-scroll-box`,
				props.classes?.scroll,
				{ [`${listPrefixCls.value}-autoscroll`]: props.autoScroll }
			],
			"style": props.styles?.scroll,
			"onScroll": handleScroll
		}, [createVNode("div", {
			"ref": scrollContentRef,
			"class": `${listPrefixCls.value}-scroll-content`
		}, [mergedItems.value.map((item, index) => {
			const { key, role, status, extraInfo, contentRender, loadingRender, styles, classes, rootClass, class: itemClass, style: itemStyle, ...rest } = item;
			const roleRootClassName = role === "divider" ? bubbleClassNames.value.divider : role === "system" ? bubbleClassNames.value.system : bubbleClassNames.value.bubble;
			const roleRootStyle = role === "divider" ? bubbleStyles.value.divider : role === "system" ? bubbleStyles.value.system : bubbleStyles.value.bubble;
			const mergedClassNames = {
				...bubbleClassNames.value.rest,
				...classes
			};
			const mergedStyles = {
				...bubbleStyles.value.rest,
				...styles
			};
			const info = {
				key,
				status,
				extraInfo
			};
			const hasListContentRenderSlot = Boolean(slots.contentRender);
			const hasListLoadingRenderSlot = Boolean(slots.loadingRender);
			const commonProps = {
				key,
				ref: setBubbleRef(key),
				prefixCls: props.prefixCls,
				content: item.content,
				rootClass: rootClass || roleRootClassName,
				style: itemStyle || roleRootStyle,
				class: itemClass,
				classes: mergedClassNames,
				styles: mergedStyles,
				...hasListContentRenderSlot && contentRender ? { contentRender } : {},
				...hasListLoadingRenderSlot && loadingRender ? { loadingRender } : {},
				...rest
			};
			if (role === "divider") return createVNode(XBubbleDivider, commonProps, null);
			if (role === "system") return createVNode(XBubbleSystem, commonProps, null);
			const bubbleSlots = {};
			const bindListSlot = (name) => {
				const slot = slots[name];
				if (!slot) return void 0;
				return ({ content, info: bubbleInfo }) => slot({
					content,
					info: bubbleInfo,
					item,
					index,
					role
				});
			};
			if (slots.contentRender) bubbleSlots.content = bindListSlot("contentRender");
			else if (contentRender) bubbleSlots.content = ({ content, info: bubbleInfo }) => contentRender(content, bubbleInfo);
			if (slots.loadingRender) bubbleSlots.loading = bindListSlot("loadingRender");
			else if (loadingRender) bubbleSlots.loading = ({ content, info: bubbleInfo }) => loadingRender(content, bubbleInfo);
			for (const name of bubbleSlotNames) {
				if (name === "contentRender" || name === "loadingRender") continue;
				const slot = bindListSlot(name);
				if (slot) bubbleSlots[name] = slot;
			}
			return createVNode(XBubble, mergeProps(commonProps, { "info": info }), bubbleSlots);
		})])])]);
	}
});
//#endregion
export { XBubbleList, XBubbleList as default };
