<template>
	<div class="saswp-property-stepper">
		<v-slide-group
			show-arrows
			center-active
			:model-value="props.modelValue"
			class="saswp-property-stepper__header"
			v-if="!props.hideNavigation"
		>
			<template v-for="(s, i) in meta.items">
				<v-slide-group-item :value="s.id">
					<!-- <v-divider v-if="i>0" class="mx-3" /> -->
					<v-btn
						block
						stacked
						variant="text"
						rounded="0"
						@click="stepGoto(s, i)"
						:disabled="!s.valid"
						:class="{
							'flex-grow-1': true,
							'bg-primary': props.modelValue == (s.id || i),
						}"
					>
						<slot
							:name="`header:${s.id || i}`"
							v-bind="slotBind({ id: s.id, index: i, item: s })"
						>
							{{ s.title || `Step ${i + 1}` }}
						</slot>
					</v-btn>
				</v-slide-group-item>
			</template>
		</v-slide-group>

		<v-window :model-value="props.modelValue" :touch="false">
			<template v-for="(s, i) in meta.items">
				<v-window-item
					:value="s.id"
					:class="props.contentClass"
				>
					<slot
						name="step-header"
						v-bind="slotBind({ id: s.id, index: i, item: s })"
					></slot>
					<slot
						:name="`step:${s.id}`"
						v-bind="slotBind({ id: s.id, index: i, item: s })"
					>
						<!-- <pre class="bg-blue-grey-darken-3 pa-3" style="max-height:500px; overflow:auto;">{{ [
						  `<template #header:${s.id}="bind">`,
						  ` &#123;&#123; bind.title &#125;&#125;`,
						  `</template>`,
						  ``,
						  `<template #step:${s.id}="bind">`,
						  ` <pre>&#123;&#123; bind &#125;&#125;</pre>`,
						  `</template>`,
						  ``,
						  'bind: '+JSON.stringify(slotBind({ id: s.id, index: i, item: s }), null, 2),
						].join("\n") }}</pre> -->
						<slot
							:name="`step-footer:${s.id}`"
							v-bind="slotBind({ id: s.id, index: i, item: s })"
						></slot>
					</slot>
					<slot
						name="step-footer"
						v-bind="slotBind({ id: s.id, index: i, item: s })"
					></slot>
				</v-window-item>
			</template>
		</v-window>
	</div>
</template>

<script setup>
const emit = defineEmits(["update:modelValue"]);

const props = defineProps({
	modelValue: {
		type: [Number, String],
		default: 0,
	},
	items: {
		type: [Array],
		default: () => [],
	},
	hideNavigation: {
		type: [Array],
		default: false,
	},
	contentClass: {
		type: String,
		default: "",
	},
});

const meta = Vue.reactive({
	lastIndex: 0,
	lastItem: props.items[0] || false,
	prev: false,
	next: false,
	items: [],
});

const slotBind = (merge = {}) => {
	return {
		...merge,
		...meta,
	};
};

const itemDefault = (item, index) => {
	item = {
		id: item.id || index,
		validate:
			typeof item.validate == "function" ? item.validate : () => true,
		valid: null,
		current: null,
		...item,
	};

	if (item.valid === null) {
		item.valid = item.validate(slotBind({id: item.id, index, item}));
	}

	item.current = props.modelValue === item.id;

	return item;
};

const updateItems = () => {
	let hasInvalidItem = false;
	meta.items = props.items.map((item, index) => {
		item = itemDefault(item, index);

		if (!item.valid) {
			hasInvalidItem = true;
		}
		if (hasInvalidItem) {
			item.valid = false;
		}

		if (item.current) {
			meta.prev = props.items[index - 1] || false;
			if (meta.prev) {
				meta.prev = itemDefault(meta.prev, index - 1);
			}
			meta.next = props.items[index + 1] || false;
			if (meta.next) {
				meta.next = itemDefault(meta.next, index + 1);
			}
		}
		return item;
	});
};

Vue.watch(() => [props.items, props.modelValue], updateItems, {
	immediate: true,
	deep: true,
});

const stepGoto = (step, index) => {
	emit("update:modelValue", step.id || index);
	meta.lastIndex = index;
	meta.lastItem = step;
};
</script>

<style>
.saswp-property-stepper {
	&__header {
		.v-slide-group__content {
			align-items: center;
		}

		.v-slide-group__content > * {
			flex-grow: 1 !important;
		}

		.v-slide-group__content > hr.v-divider {
			max-width: 200px;
		}
	}
}
</style>
