<script setup lang="ts">
import { Btn, Icon, formatString } from '@bagelink/vue'
import { onMounted, ref } from 'vue'
import { VueDraggableNext } from 'vue-draggable-next'

const props = withDefaults(
	defineProps<{
		description?: string
		meta: { [key: string]: any } /* EntityMeta */
		fieldname: string
		bagelApp?: any
		modelValue: any
	}>(),
	{
		description: '',
		bagelApp: undefined,
	},
)
const emits = defineEmits(['update:modelValue'])
let bagel: any
let api: any
const listRef = ref(props.modelValue)
const fieldMeta = props.meta.doc_meta.fields.find(
	(field: { [key: string]: any }) => field.fieldname === props.fieldname,
)
const entityMeta = props.meta.links.find(
	(link: { [key: string]: any }) => link.id === fieldMeta?.options,
)

function handleUpdateModelValue(value: any, index: number, fieldname: string) {
	const rows = [...props.modelValue]
	rows[index][fieldname] = value
	emits('update:modelValue', rows)
}

function addRow() {
	const rows = [...props.modelValue]
	const entry = {
		idx: rows.length,
	} as { [key: string]: any }
	entityMeta?.fields.forEach((field: any) => {
		if (field.default) {
			if (field.fieldtype === 'Check') {
				entry[field.fieldname] = Number.parseInt(field.default)
			} else {
				entry[field.fieldname] = field.default
			}
		}
	})
	rows.push(entry)
	emits('update:modelValue', rows)
}

function removeRow(idx: number) {
	const rows = [...props.modelValue]
	rows.splice(idx, 1)
	emits('update:modelValue', rows)
}

function ended() {
	listRef.value.forEach((item: { [key: string]: any }, index: number) => {
		item.idx = index + 1
	})
	emits('update:modelValue', listRef.value)
}
onMounted(() => {
	bagel = props.bagelApp || api
})
</script>

<template>
	<div
		class="table-field-wrap"
		:title="description"
	>
		<div class="bagel-input">
			<label>
				{{ fieldMeta?.label }}
			</label>
		</div>
		<div class="table-side-scroll">
			<div class="table-header">
				<div
					v-for="field in entityMeta?.fields"
					:key="`${field.fieldname}header`"
					class="header-col"
					:class="formatString(field.fieldtype, 'pascal')"
				>
					{{ field.label }}
				</div>
			</div>
			<VueDraggableNext
				v-model="listRef"
				animation="150"
				handle=".table-reorder"
				group="mainGroup"
				easing="cubic-bezier(1, 0, 0, 1)"
				ghost-class="ghost"
				@end="ended"
			>
				<TransitionGroup>
					<div
						v-for="(row, index) in modelValue"
						:key="row.id"
						class="flex table-row"
					>
						<div class="table-reorder">
							<Icon icon="more_vert" />
						</div>
						<div
							v-for="field in entityMeta?.fields"
							:key="`${field.fieldname}${row.id}`"
							class="table-cell"
							:class="formatString(field.fieldtype, 'pascal')"
						>
							<BagelInput
								no-label
								:field-meta="field"
								:bagel-app="bagel"
								:model-value="row[field.fieldname]"
								@update:modelValue="(value: any) => handleUpdateModelValue(value, index, field.fieldname)"
							/>
						</div>

						<div class="table-action">
							<Icon
								icon="delete"
								@click="removeRow(index)"
							/>
						</div>
					</div>
				</TransitionGroup>
			</VueDraggableNext>
		</div>
		<Btn
			thin
			flat
			icon="add"
			color="light"
			@click="addRow"
		>
			New
		</Btn>
	</div>
</template>

<style scoped>
.table-side-scroll {
	overflow: auto;
	margin-inline-start: -1rem;
	padding-inline-start: 1rem;
	padding-bottom: 1rem;
}

.table-field-wrap {
	margin-bottom: -1rem;
}

.table-cell {
	border-inline-end: 1px solid var(--border-color);
	border-bottom: 1px solid var(--border-color);
}

.table-row {
	transition: var(--bgl-transition);
	position: relative;
	width: max-content;
}

.table-row:hover {
	background: var(--bgl-gray-light);
}

.table-reorder {
	opacity: 0;
	width: 2rem;
	text-align: center;
	position: absolute;
	margin-inline-start: -2rem;
}

.table-row:hover .table-reorder {
	opacity: 1;
	cursor: grab;
}

.table-reorder:active {
	opacity: 1;
	cursor: grab;
}

.bgl_btn.thin.bgl_flatBtn {
	margin-inline-start: -1rem;
	margin-top: 1rem;
}

.table-header {
	display: flex;
	width: max-content;
}

.header-col {
	min-width: calc(var(--input-height) * 3);
	font-size: 13px;
	color: var(--input-color);
	padding: 10px 0;
	border-bottom: 1px solid var(--border-color);
}

.table-cell,
.header-col {
	width: 160px;
}

.table-cell.check,
.header-col.check {
	width: 100px;
}

.table-cell.date,
.header-col.date {
	width: 140px;
}

.header-col.small-text,
.header-col.text,
.header-col.long-text,
.header-col.json,
.table-cell.small-text,
.table-cell.text,
.table-cell.long-text,
.table-cell.json {
	width: 240px;
}

.table-cell.small-text .bagel-input,
.table-cell.text .bagel-input,
.table-cell.long-text .bagel-input,
.table-cell.json .bagel-input {
	height: 40px;
	overflow: auto;
}

.table-action {
	text-align: center;
	position: sticky;
	opacity: 0;
	transition: var(--bgl-transition);
	inset-inline-end: 0;
	height: 100%;
	margin-top: -1px;
	background: var(--border-color);
}

.table-action>.bgl_icon-font {
	padding: 11.4px;
	cursor: pointer;
	transition: var(--bgl-transition);
}

.table-action:hover>.bgl_icon-font {
	background: var(--bgl-red);
	color: var(--bgl-box-bg);
}

.table-action:active>.bgl_icon-font {
	filter: brightness(90%);
}

.table-row:hover .table-action {
	opacity: 1;
}
</style>

<style>
.table-row .bagel-input input,
.table-row .bagel-input textarea,
.table-row .bagel-input .input {
	border-radius: 0;
	background: transparent;
	color: var(--bgl-text-color);
}

.table-row .bagel-input textarea {
	resize: none;
	min-height: 40px;
	overflow: auto;
	margin: 0px;
	padding: 0.64rem 0.7rem 0;
}

.table-row .bagel-input {
	margin: 0;
}

.table-row .bagel-input input:focus-visible,
.table-row .bagel-input textarea:focus-visible,
.table-row .bagel-input .input:focus-visible {
	background: var(--border-color);
}

.ghost {
	opacity: 0;
	background: #c8ebfb;
}

.sortable-chosen {
	cursor: grabbing !important;
	border-color: transparent;
	background: var(--bgl-box-bg);
	border-radius: 10px;
	box-shadow: 0 0 10px 0 rgb(0 0 0 /20%);
}
</style>
