<template>
	<div
		class="app-html"
		ref="appHtmlRef"
		:style="
			[
				`--app-html-color: #eee;`,
				`--app-html-placeholder: '${props.placeholder}';`,
			].join('')
		"
	>
		<!-- Actions -->
		<v-defaults-provider
			:defaults="{
				VBtn: {
					rounded: 0,
					variant: 'text',
					size: 40,
				},
			}"
		>
			<div class="app-html__actions pa-1">
				<div v-for="g in actionGroups">
					<template v-for="btn in g.buttons">
						<v-btn v-bind="btn" />
					</template>
				</div>
			</div>
		</v-defaults-provider>

		<!-- Content editor -->
		<div class="d-flex">
			<slot name="prepend"></slot>

			<div class="flex-grow-1">
				<Contenteditable
					ref="editorRef"
					class="app-html__editor-ref pa-3"
					:class="{
						'app-html__editor-ref-placeholder': !props.modelValue,
					}"
					tag="div"
					:contenteditable="true"
					:model-value="props.modelValue"
					:no-nl="!props.multiline"
					:no-html="false"
					@update:modelValue="emitHandler($event)"
					@keyup="selection.update()"
					@click="selection.update()"
					@focus="selection.update()"
					@blur="selection.update()"
				/>
			</div>

			<slot name="append"></slot>
		</div>
	</div>
</template>

<script setup>
const Contenteditable = Vue.defineAsyncComponent(() =>
	loadModule(`${SAS_URL}/src/components/Contenteditable.vue`, options),
);

const { ref, reactive } = Vue;

const props = defineProps({
	modelValue: {
		type: String,
		default: null,
	},
	placeholder: {
		type: String,
		default: "",
	},
	multiline: {
		type: Boolean,
		default: true,
	},
});

const emit = defineEmits(["update:modelValue"]);

const appHtmlRef = ref(null);
const editorRef = ref(null);

const selection = reactive({
	active: false,
	text: "",
	start: 0,
	final: 0,
	update() {
		const el = editorRef.value.$el;
		const s = window.getSelection();
		selection.start = Math.min(s.anchorOffset, s.focusOffset);
		selection.final = Math.max(s.anchorOffset, s.focusOffset);
		selection.text = el.innerHTML.substring(
			selection.start,
			selection.final,
		);
		selection.active = appHtmlRef.value.contains(document.activeElement);
	},
	textReplace(callback) {
		if (typeof callback != "function") return;
		if (!selection.text) return;
		const replaceText = callback();
		if (replaceText) {
			const el = editorRef.value.$el;
			const sel = window.getSelection();
			if (sel.rangeCount > 0) {
				const range = sel.getRangeAt(0);
				const selectedText = range.toString();
				const newNode = document.createTextNode(replaceText);
				range.deleteContents();
				range.insertNode(newNode);
				range.setStartAfter(newNode);
				range.setEndAfter(newNode);
				selection.removeAllRanges();
				selection.addRange(range);

				// text = props.modelValue.replace(selection.text, text);
				// emit('update:modelValue', text);
			}
		}
	},
});

const emitHandler = (value) => {
	emit("update:modelValue", value);
};

const actionGroups = [
	{
		title: "Group 1",
		buttons: [
			{
				icon: "uil:bold",
				onClick: (ev) => {
					document.execCommand("bold", false, null);
				},
			},
			{
				icon: "uil:italic",
				onClick: (ev) => {
					document.execCommand("italic", false, null);
				},
			},
			{
				icon: "uil:underline",
				onClick: (ev) => {
					document.execCommand("underline", false, null);
				},
			},
		],
	},
];
</script>

<style>
.app-html {
	border: solid 1px #eee;

	&__actions {
		display: flex;
		flex-wrap: wrap;
		gap: 25px;
		background-color: #eee;

		& > div {
			display: flex;
			gap: 5px;
		}
	}

	&__editor-ref {
		outline: 0 !important;

		&-placeholder:before {
			content: attr(--app-html-placeholder);
			color: #aaa;
		}
	}
}
</style>
