<template>
	<a-card size="small">
		<template #title>
			<a-tabs centered size="small">
				<a-tab-pane key="form" tab="预览区" />
			</a-tabs>
		</template>
		<template #extra>
			<a-space v-if="notEmpty">
				<a-button size="small" type="primary" @click="generate">
					<template #icon>
						<icon-font type="icon-code" />
					</template>
					生成
				</a-button>
				<a-button size="small" type="primary" @click="preview">
					<template #icon>
						<icon-font type="icon-preview" />
					</template>
					预览
				</a-button>
				<a-popconfirm title="确定清空设计？" ok-text="确定" cancel-text="取消" @confirm="reset">
					<a-button size="small" type="primary" danger>
						<template #icon>
							<icon-font type="icon-reset" />
						</template>
						清空
					</a-button>
				</a-popconfirm>
			</a-space>
		</template>
		<div :style="{ minHeight: 'calc(100vh - 190px)', maxHeight: 'calc(100vh - 190px)', overflowY: 'auto' }">
			<a-watermark :content="waterMark" :rotate="22" :font="{ color: 'rgba(0,0,0,.3)', fontSize: 20 }">
				<a-form
					v-bind="formConfig"
					ref="formRef"
					:style="{ '--ant-primary-color': token.colorPrimaryBorder }"
					@click="selectedChange()"
				>
					<component-item
						v-for="(c, index) in components"
						:key="c.uuid"
						:data-id="c.uuid"
						:item="c"
						:components="components"
						:disabled-fields="disabledFields"
						:selected="selected"
						@selected="selectedChange"
						@copy="copyItem(index)"
						@delete="deleteItem(index, $event)"
					/>
				</a-form>
			</a-watermark>
		</div>
		<code-generator-drawer
			ref="codeGeneratorDrawer"
			:components="components"
			:config="formConfig"
		></code-generator-drawer>
		<form-preview-drawer ref="formPreviewModal" :components="components" :config="formConfig"></form-preview-drawer>
	</a-card>
</template>
<script lang="ts" setup>
	import { FormDesignerItem } from '../form-designer-types'
	import Sortable from 'sortablejs'
	import allComponents from '../component-panel/components'
	import { FormConfig, FormItem } from '@/components/form-render/form-render-types'
	import XEUtils from 'xe-utils'
	import { notification, theme } from 'ant-design-vue'
	import FormPreviewDrawer from './form-preview-drawer.vue'
	import CodeGeneratorDrawer from './code-generator-drawer.vue'
	const { useToken } = theme
	const { token } = useToken()
	const props = defineProps({
		formConfig: {
			type: Object as PropType<FormConfig>,
			required: true,
		},
		// 选中的组件
		selected: {
			type: Object as PropType<FormDesignerItem>,
			required: false,
			default: () => {
				return undefined
			},
		},
		// 禁用的表单项
		disabledFields: {
			type: Array as PropType<Array<string>>,
			required: false,
			default: () => {
				return []
			},
		},
		isGenerate: {
			type: Boolean,
			default: () => true,
		},
	})
	const { selected } = toRefs(props)

	const selectedKey = computed(() => {
		return selected?.value?.uuid
	})

	const emit = defineEmits<{
		selectedChange: [config?: FormDesignerItem]
		'update:form-items': [formItems: Array<FormItem>]
	}>()

	const selectedChange = (config?: FormDesignerItem) => {
		emit('selectedChange', config)
	}

	// 复制表单项
	const copyItem = (index: number) => {
		const item = XEUtils.assign(XEUtils.clone(components.value[index], true), { uuid: XEUtils.uniqueId() })
		if (item.formItem.config?.name)
			item.formItem.config.name = item.formItem.config.name.split('_')[0] + '_' + XEUtils.uniqueId()
		// 必须深拷贝，否则对象类型的字段会拷贝引用
		components.value.splice(index + 1, 0, item)
	}

	// 删除表单项
	const deleteItem = (index: number, item: FormDesignerItem) => {
		components.value.splice(index, 1)
		if (item.uuid == selectedKey.value) {
			// 如果删除的是当前选中的组件，则要清理选中组件
			selectedChange()
		}
	}

	const components = ref<Array<FormDesignerItem>>([])
	const notEmpty = computed<boolean>(() => {
		return components.value.length > 0
	})

	const waterMark = computed<string>(() => {
		return notEmpty.value ? ' ' : '拖动组件到这里'
	})
	const codeGeneratorDrawer = ref<typeof CodeGeneratorDrawer>()
	// 生成
	const generate = () => {
		codeGeneratorDrawer.value?.show()
	}
	const formPreviewModal = ref<typeof FormPreviewDrawer>()
	// 预览
	const preview = () => {
		formPreviewModal.value?.show()
	}
	// 清空
	const reset = () => {
		// 清空容器中的组件
		components.value = []
		selectedChange()
	}
	const sort = ref<Sortable>()
	nextTick(() => {
		const form = document.querySelector('.ant-form')
		// 整体的组件
		if (form) {
			sort.value = Sortable.create(form as HTMLElement, {
				animation: 150,
				sort: true,
				group: { name: 'components', pull: true, put: true },
				onEnd: (evt) => {
					components.value = [...evt.from.children]
						.filter((item) => (item as HTMLElement).style.display !== 'none')
						.map((item) => {
							const id = (item as HTMLElement).dataset.id
							return components.value.find((item) => item.uuid === id)
						}) as FormDesignerItem[]
				},
				onAdd: (evt) => {
					;[...evt.to.children]
						.filter((item) => item.classList.contains('ant-card-grid'))
						.forEach((item) => {
							;(item as HTMLElement).style.display = 'none'
						})
					const uuid = evt.clone.dataset.id
					const type = evt.clone.dataset.type
					if (type === 'col') {
						notification.warning({
							message: '提示',
							description: '列组件需要放入行组件',
							duration: 3,
						})
						return
					}
					const item = type
						? allComponents.find((item) => item.type === type)
						: XEUtils.findTree(components.value, (item) => item.uuid === uuid).item
					if (item) {
						components.value.push(XEUtils.assign(XEUtils.clone(item, true), { uuid: XEUtils.uniqueId() }))
					}
					nextTick(() => {
						rowDrag()
					})
				},
			})
		}
	})
	const rowDrag = () => {
		;[...document.querySelectorAll('.list-group-item .drag-row')].forEach((item) => {
			Sortable.create(item as HTMLElement, {
				animation: 150,
				sort: true,
				group: { name: 'components', pull: true, put: true },
				onEnd: (evt) => {
					const item = components.value.find((a) => a.uuid === evt.to.dataset.id)
					if (item) {
						item.children = [...evt.from.children]
							.filter((c) => (c as HTMLElement).style.display !== 'none')
							.map((c) => {
								const id = (c as HTMLElement).dataset.id
								return (item.children ?? []).find((c) => c.uuid === id)
							}) as FormDesignerItem[]
					}
				},
				onAdd: (evt) => {
					;[...evt.to.children]
						.filter((item) => item.classList.contains('ant-card-grid'))
						.forEach((item) => {
							;(item as HTMLElement).style.display = 'none'
						}) //原始元素都别给我显示出来了

					//获取拖到了哪个行,添加拖入的列
					const item = components.value.find((a) => a.uuid === evt.to.dataset.id)
					const type = evt.clone.dataset.type
					if (!type) {
						notification.warning({
							message: '提示',
							description: '已设置组件放入布局将无法恢复!',
							duration: 3,
						})
						return
					}
					if (type !== 'col') {
						notification.warning({
							message: '提示',
							description: '行组件只接受放入列组件',
							duration: 3,
						})
						return
					}
					const newItem = allComponents.find((item) => item.type === type) //仅仅找到原始组件
					if (newItem) {
						item?.children?.push(XEUtils.assign(XEUtils.clone(newItem, true), { uuid: XEUtils.uniqueId() }))
					}
				},
			})
		})
	}
</script>
<style scoped>
	.ant-form {
		height: calc(100vh - 190px);
		padding: 15px;
		overflow-x: hidden;
		background-color: #fff;
		border: 1px dashed var(--ant-primary-color);
	}

	.ant-pro-pro-layout-watermark-wrapper {
		min-height: calc(100vh - 190px) !important;
	}
</style>
