<template>
	<div class="es-checkbox-group">
		<es-checkbox
			v-for="item in source"
			:key="item[valueKey]"
			:model-value="isSelected(item[valueKey])"
			:label-text="item[labelKey]"
			:disabled="item[disabledKey]"
			@select="checkBoxChangeEvt($event, item)"
		/>
	</div>
</template>

<script lang="ts">
import { computed, defineComponent, toRefs, watch } from 'vue'
import type { PropType } from 'vue'
interface IKeyConfig {
	labelKey?: string
	valueKey?: string
	disabledKey?: string
}

export default defineComponent({
	name: 'EsCheckboxGroup',
	props: {
		source: {
			type: Array,
			default: () => [],
		},
		modelValue: {
			type: Array,
			default: () => [],
		},
		keyConfig: {
			type: Object as PropType<IKeyConfig>,
			default: () => ({
				labelKey: 'label',
				valueKey: 'value',
				disabledKey: 'disabled',
			}),
		},
	},
	emits: ['update:modelValue', 'select', 'change'],
	setup(props, ctx) {
		const { modelValue } = toRefs(props)
		const defaultKeyConfig: IKeyConfig = {
			labelKey: 'label',
			valueKey: 'value',
			disabledKey: 'disabled',
		}
		const isSelected = computed(() => {
			return itemValue => {
				return modelValue.value.includes(itemValue)
			}
		})
		const { labelKey, valueKey, disabledKey } = {
			...defaultKeyConfig,
			...props.keyConfig,
		}
		watch(modelValue, (newVal, preVal) => {
			const nVal = [...newVal],
				pVal = [...preVal]
			if (nVal.length !== pVal.length) {
				ctx.emit('change', nVal)
			} else {
				if (!nVal.every(v => pVal.includes(v))) {
					ctx.emit('change', nVal)
				}
			}
		})
		const checkBoxChangeEvt = (e, item: IKeyConfig) => {
			const itemValue = item[valueKey]
			const val = new Set([...modelValue.value])
			val.has(itemValue) ? val.delete(itemValue) : val.add(itemValue)
			ctx.emit('update:modelValue', Array.from(val))
			ctx.emit('select', {
				e: e?.e || {},
				item: { ...item },
				data: Array.from(val),
			})
		}
		return {
			labelKey,
			valueKey,
			disabledKey,
			isSelected,
			checkBoxChangeEvt,
		}
	},
})
</script>
