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

const props = withDefaults(
	defineProps<{
		description?: string
		meta: { [key: string]: any } /* EntityMeta */
		fieldname: string
		bagelApp?: any
		modelValue: any
	} & BagelInputShellProps>(),
	{
		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)
}
const { shellClass, shellStyle } = useBagelInputShell(props)

onMounted(() => {
	bagel = props.bagelApp || api
})
</script>

<template>
	<div
		class="table-field-wrap"
		:title="description"
	>
		<div class="bagel-input" :class="shellClass" :style="shellStyle">
			<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(--bgl-border-color);
border-bottom: 1px solid var(--bgl-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(--bgl-input-height) * 3);
font-size: 13px;
color: var(--bgl-input-color);
padding: 10px 0;
border-bottom: 1px solid var(--bgl-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(--bgl-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(--bgl-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>
