<script lang="ts">
	import { resolve } from "$app/paths";
	import File from "$icon/file";
	import FileSymlink from "$icon/file-symlink";
	import Folder from "$icon/folder";
	import FolderInput from "$icon/folder-input";
	import { splitMessage } from "$lib/api/repo";
	import TimeAgo from "$lib/components/ui/TimeAgo.svelte";
	import type { TreeEntrySummary } from "./types";
	import { encodePathSegments } from "./urls";

	interface Props {
		ownerHandle: string;
		repoName: string;
		ref: string;
		entries: TreeEntrySummary[];
		path?: string;
		withMessage?: boolean;
	}

	let { ownerHandle, repoName, ref, entries, path = "", withMessage = false }: Props = $props();

	const base = $derived(`/${ownerHandle}/${repoName}`);
	const encodedRef = $derived(encodeURIComponent(ref));

	const linkFor = (entry: TreeEntrySummary) => {
		const target = path ? `${path}/${entry.name}` : entry.name;
		const kind = entry.kind === "directory" ? "tree" : "blob";
		return `${base}/${kind}/${encodedRef}/${encodePathSegments(target)}`;
	};

	// lucide puts fill="none" on the path itself, which beats anything inherited
	// from the svg, so the class has to reach the path
	const iconClassFor = (entry: TreeEntrySummary) =>
		entry.kind === "directory" ? "size-4 shrink-0 [&_path]:fill-current" : "size-4 shrink-0";

	const iconFor = (entry: TreeEntrySummary) => {
		switch (entry.kind) {
			case "directory":
				return Folder;
			case "submodule":
				return FolderInput;
			case "symlink":
				return FileSymlink;
			default:
				return File;
		}
	};
</script>

<!-- the divider belongs to whatever column the tree is sat in -->
<div class="min-w-0">
	{#each entries as entry (entry.name)}
		{@const Glyph = iconFor(entry)}
		<div class={`grid items-center gap-4 py-1 ${withMessage ? "grid-cols-12" : "grid-cols-3"}`}>
			<a
				href={resolve(linkFor(entry) as "/")}
				class={`flex min-w-0 items-center gap-2 text-foreground-default no-underline hover:underline ${
					withMessage ? "col-span-8 md:col-span-4" : "col-span-2"
				}`}
			>
				<span class="text-foreground-muted">
					<Glyph class={iconClassFor(entry)} aria-hidden="true" />
				</span>
				<span class="truncate">{entry.name}</span>
			</a>

			{#if withMessage}
				<div class="hidden min-w-0 md:col-span-6 md:block">
					{#if entry.lastCommitHash && entry.lastCommitMessage}
						<a
							href={resolve(`${base}/commit/${entry.lastCommitHash}` as "/")}
							class="block truncate text-foreground-subtle no-underline hover:underline"
						>
							{splitMessage(entry.lastCommitMessage)[0]}
						</a>
					{/if}
				</div>
			{/if}

			<div
				class={`text-right text-sm text-foreground-subtle ${
					withMessage ? "col-span-4 md:col-span-2" : "col-span-1"
				}`}
			>
				{#if entry.lastCommitHash && entry.lastCommitWhen}
					<a
						href={resolve(`${base}/commit/${entry.lastCommitHash}` as "/")}
						class="text-foreground-subtle no-underline hover:underline"
						title={entry.lastCommitMessage}
					>
						<TimeAgo value={entry.lastCommitWhen} />
					</a>
				{/if}
			</div>
		</div>
	{/each}
</div>
