<script lang="ts">
	import { onMount } from "svelte"
	import { marked } from "marked"
	import { TITLE_MAX_LENGTH } from "$lib/const"
	import { apiClient, type FullNote } from "$lib/client"

	// Props
	export let note: FullNote
	export let isEditing = false
	export let saveNote: (title: string, content: string) => Promise<void>

	// Local copy for editing (to prevent uploading every single keypress as unique version)
	let editableTitle = note.title
	let editableContent = note.content

	// Update the local copy when the note changes
	$: if (note && note.id) {
		editableTitle = note.title
		editableContent = note.content
	}

	const handleContentChange = (
		event: Event & { currentTarget: EventTarget & HTMLTextAreaElement }
	) => {
		if (!event.target) {
			return
		}

		const { value } = event.target as HTMLTextAreaElement
		editableContent = value

		// Update title based on the first line if it starts with #
		const firstLine = editableContent.split("\n")[0]
		if (firstLine && firstLine.startsWith("# ")) {
			editableTitle = firstLine.substring(2).slice(0, TITLE_MAX_LENGTH)
		} else if (!editableTitle || editableTitle === "Untitled Note") {
			// Try to extract a title from the first non-empty line if there's no title yet
			const firstNonEmptyLine = editableContent.split("\n").find((line) => line.trim().length > 0)

			if (firstNonEmptyLine) {
				editableTitle =
					firstNonEmptyLine.length > TITLE_MAX_LENGTH
						? firstNonEmptyLine.substring(0, TITLE_MAX_LENGTH - 3) + "..."
						: firstNonEmptyLine
			}
		}
	}

	const exitEditMode = () => {
		isEditing = false
	}

	const handleKeyDown = (event: KeyboardEvent) => {
		// Ctrl+Enter or Command+Enter keyboard shortcut for saving the current note
		if ((event.ctrlKey || event.metaKey) && event.key === "Enter") {
			event.preventDefault()
			handleSave()
		}
		// Esc keyboard shortcut for quitting edit mode
		else if (event.key === "Escape") {
			event.preventDefault()
			exitEditMode()
		}
	}

	const handleSave = () => {
		saveNote(editableTitle, editableContent)
	}

	const handleTitleChange = (event: Event & { currentTarget: EventTarget & HTMLInputElement }) => {
		if (!event.target) {
			return
		}

		const { value } = event.target as HTMLInputElement
		editableTitle = value.slice(0, TITLE_MAX_LENGTH)
	}

	const parseMarkdown = async (markdown: string) => {
		if (!markdown) {
			return ""
		}

		// Enable Github flavored markdown rendering
		marked.setOptions({
			gfm: true,
			breaks: true
		})

		let html = await marked(markdown)

		// Add spans to regular list items
		html = html.replaceAll(/\<li\>([^\<].*)\<\/li\>/g, '<li><span class="list-text">$1</span></li>')

		// Add spans to nested ordered/unordered lists
		html = html.replaceAll(
			/<li>([^<]+)(?=.*?<(?:ul|ol)[^>]*>)/g,
			'<li><span class="list-text">$1</span></li>'
		)

		return html
	}

	let textarea: HTMLTextAreaElement | null
	const autoResize = () => {
		if (textarea) {
			textarea.style.height = "auto"
			textarea.style.height = textarea.scrollHeight + "px"
		}
	}

	onMount(() => {
		if (isEditing && textarea) {
			// Scrollbar is hidden in global CSS so flickering during resizing of the
			// textarea shouldn't be an issue anymore
			autoResize()
		}
	})

	$: if (isEditing && textarea) {
		setTimeout(autoResize, 0)
	}
</script>

<div class="note-editor-content">
	<!-- Note title -->
	<div class="note-title-container">
		{#if isEditing}
			<input
				type="text"
				bind:value={editableTitle}
				on:input={handleTitleChange}
				on:keydown={handleKeyDown}
				placeholder="Title"
				class="note-title-input"
			/>
			<div class="note-char-count ml-3">
				{editableTitle.length}/{TITLE_MAX_LENGTH} characters
			</div>
			<div class="note-char-count ml-3">
				Last updated: {new Date(note.versionCreatedAt).toLocaleString()}
				{#if !isEditing}
					<!-- Minus 1 due to versioning beginning at 2 in the DB -->
					• Version: {note.versionNumber - 1}
				{/if}
			</div>
		{:else}
			<h1 class="border-[var(--light-text)]/20 border-b pb-2 text-2xl font-bold">
				{note.title || "Untitled Note"}
			</h1>
			<div class="note-char-count">
				Last updated: {new Date(note.versionCreatedAt).toLocaleString()}
				{#if !isEditing}
					<!-- Minus 1 due to versioning beginning at 2 in the DB -->
					• Version: {note.versionNumber - 1}
				{/if}
			</div>
		{/if}
	</div>

	<!-- Note content (takes up remaining vertical space) -->
	<div class="note-editor-container">
		{#if isEditing}
			<div class="note-editor-wrapper">
				<textarea
					bind:this={textarea}
					bind:value={editableContent}
					on:input={handleContentChange}
					on:keydown={handleKeyDown}
					placeholder="Markdown contents"
					class="note-textarea"
				></textarea>
			</div>
		{:else}
			<!-- Rendered markdown preview -->
			<div class="prose markdown-preview max-w-none p-4">
				{#await parseMarkdown(note.content) then html}
					{@html html}
				{/await}
			</div>
		{/if}
	</div>

	{#if isEditing}
		<div class="note-save-button">
			<button on:click={handleSave} class="btn-primary rounded-full"> Save </button>
		</div>
	{/if}
</div>
