<script lang="ts">
	import { getSegmentsUpToChar } from "./utils";
	import { user } from "$lib/config";
	import TuiLine from "./TuiLine.svelte";
	import type { DisplayedLine, TerminalLine } from "./types";
	import "$lib/assets/css/tui-body.css";

	interface Props {
		displayedLines: DisplayedLine[];
		currentLineIndex?: number;
		isTyping?: boolean;
		selectedIndex?: number;
		ref?: HTMLDivElement | undefined;
		onButtonClick: (idx: number, line?: TerminalLine) => void;
		onHoverButton: (idx: number) => void;
		onLinkClick: (idx: number) => void;
		terminalSettings: { showCursor: boolean };
	}

	let {
		displayedLines = [],
		currentLineIndex = 0,
		isTyping = false,
		selectedIndex = -1,
		ref = $bindable(undefined),
		onButtonClick,
		onHoverButton,
		onLinkClick,
		terminalSettings,
	}: Props = $props();

	// Group consecutive inline items together
	type ProcessedGroup =
		| { kind: "single"; index: number; displayed: DisplayedLine }
		| {
				kind: "inline";
				items: Array<{ index: number; displayed: DisplayedLine }>;
		  };

	const processedGroups = $derived.by(() => {
		const groups: ProcessedGroup[] = [];
		let i = 0;

		while (i < displayedLines.length) {
			const displayed = displayedLines[i];
			const isInline =
				displayed.parsed.line.inline ||
				displayed.parsed.line.display === "inline";

			if (isInline) {
				const inlineItems: Array<{
					index: number;
					displayed: DisplayedLine;
				}> = [];
				// Collect consecutive inline items
				while (i < displayedLines.length) {
					const nextLine = displayedLines[i].parsed.line;
					const nextIsInline =
						nextLine.inline || nextLine.display === "inline";

					if (!nextIsInline) break;

					inlineItems.push({
						index: i,
						displayed: displayedLines[i],
					});
					i++;
				}
				groups.push({ kind: "inline", items: inlineItems });
			} else {
				groups.push({ kind: "single", index: i, displayed });
				i++;
			}
		}
		return groups;
	});
</script>

<div class="tui-body" bind:this={ref}>
	{#each processedGroups as group, gi (gi)}
		{#if group.kind === "inline"}
			<div class="tui-inline-group">
				{#each group.items as item (item.index)}
					<TuiLine
						line={item.displayed.parsed.line}
						index={item.index}
						segments={getSegmentsUpToChar(
							item.displayed.parsed.segments,
							item.displayed.charIndex,
						)}
						complete={item.displayed.complete}
						showImage={item.displayed.showImage}
						{selectedIndex}
						inline={true}
						showCursor={terminalSettings.showCursor &&
							item.index === currentLineIndex &&
							!item.displayed.complete &&
							isTyping &&
							item.displayed.parsed.line.type !== "image"}
						{onButtonClick}
						{onHoverButton}
						{onLinkClick}
					/>
				{/each}
			</div>
		{:else}
			<TuiLine
				line={group.displayed.parsed.line}
				index={group.index}
				segments={getSegmentsUpToChar(
					group.displayed.parsed.segments,
					group.displayed.charIndex,
				)}
				complete={group.displayed.complete}
				showImage={group.displayed.showImage}
				{selectedIndex}
				inline={false}
				showCursor={terminalSettings.showCursor &&
					group.index === currentLineIndex &&
					!group.displayed.complete &&
					isTyping &&
					group.displayed.parsed.line.type !== "image"}
				{onButtonClick}
				{onHoverButton}
				{onLinkClick}
			/>
		{/if}
	{/each}

	{#if terminalSettings.showCursor && !isTyping && displayedLines.length > 0}
		<div class="tui-line prompt">
			<span class="prompt">
				<span class="user">{user.username}</span><span class="at"
					>@</span
				><span class="host">{user.hostname}</span>
				<span class="separator">:</span><span class="path">~</span><span
					class="symbol">$</span
				>
			</span>
			<span class="cursor blink"></span>
		</div>
	{/if}
</div>
