<script lang="ts">
	import { MessageToolUpdateType, type MessageToolUpdate } from "$lib/types/MessageUpdate";
	import {
		isMessageToolCallUpdate,
		isMessageToolErrorUpdate,
		isMessageToolResultUpdate,
	} from "$lib/utils/messageUpdates";

	import CarbonTools from "~icons/carbon/tools";
	import { toolHasName } from "$lib/utils/tools";
	import type { ToolFront } from "$lib/types/Tool";
	import { page } from "$app/stores";
	import { onMount } from "svelte";
	import { browser } from "$app/environment";

	export let tool: MessageToolUpdate[];
	export let loading: boolean = false;

	const toolName = tool.find(isMessageToolCallUpdate)?.call.name;
	$: toolError = tool.some(isMessageToolErrorUpdate);
	$: toolDone = tool.some(isMessageToolResultUpdate);

	const availableTools: ToolFront[] = $page.data.tools;

	let loadingBarEl: HTMLDivElement;
	let animation: Animation | undefined = undefined;

	let isShowingLoadingBar = false;
	onMount(() => {
		if (!toolError && !toolDone && loading && loadingBarEl) {
			loadingBarEl.classList.remove("hidden");
			isShowingLoadingBar = true;
			animation = loadingBarEl.animate([{ width: "0%" }, { width: "calc(100%+1rem)" }], {
				duration: availableTools.find((tool) => tool.name === toolName)?.timeToUseMS,
				fill: "forwards",
			});
		}
		return () => animation?.cancel();
	});

	// go to 100% quickly if loading is done
	$: (!loading || toolDone || toolError) &&
		browser &&
		loadingBarEl &&
		isShowingLoadingBar &&
		(() => {
			isShowingLoadingBar = false;

			loadingBarEl.classList.remove("hidden");

			animation?.cancel();
			animation = loadingBarEl.animate(
				[{ width: loadingBarEl.style.width }, { width: "calc(100%+1rem)" }],
				{
					duration: 300,
					fill: "forwards",
				}
			);

			setTimeout(() => {
				loadingBarEl.classList.add("hidden");
			}, 300);
		})();
</script>

{#if toolName && toolName !== "websearch"}
	<details
		class="group/tool my-2.5 w-fit cursor-pointer rounded-lg border border-gray-200 bg-white pl-1 pr-2.5 text-sm shadow-sm transition-all open:mb-3
        open:border-purple-500/10 open:bg-purple-600/5 open:shadow-sm dark:border-gray-800 dark:bg-gray-900 open:dark:border-purple-800/40 open:dark:bg-purple-800/10"
	>
		<summary
			class="relative flex select-none list-none items-center gap-1.5 py-1 group-open/tool:text-purple-700 group-open/tool:dark:text-purple-300"
		>
			<div
				bind:this={loadingBarEl}
				class="absolute -m-1 hidden h-full w-[calc(100%+1rem)] rounded-lg bg-purple-500/5 transition-all dark:bg-purple-500/10"
			/>

			<div
				class="relative grid size-[22px] place-items-center rounded bg-purple-600/10 dark:bg-purple-600/20"
			>
				<svg
					class="absolute inset-0 text-purple-500/40 transition-opacity"
					class:invisible={toolDone || toolError}
					width="22"
					height="22"
					viewBox="0 0 38 38"
					fill="none"
					xmlns="http://www.w3.org/2000/svg"
				>
					<path
						class="loading-path"
						d="M8 2.5H30C30 2.5 35.5 2.5 35.5 8V30C35.5 30 35.5 35.5 30 35.5H8C8 35.5 2.5 35.5 2.5 30V8C2.5 8 2.5 2.5 8 2.5Z"
						stroke="currentColor"
						stroke-width="1"
						stroke-linecap="round"
						id="shape"
					/>
				</svg>
				<CarbonTools class="text-xs text-purple-700 dark:text-purple-500" />
			</div>

			<span>
				{toolError ? "Error calling" : toolDone ? "Called" : "Calling"} tool
				<span class="font-semibold"
					>{availableTools.find((el) => toolHasName(toolName, el))?.displayName}</span
				>
			</span>
		</summary>
		{#each tool as toolUpdate}
			{#if toolUpdate.subtype === MessageToolUpdateType.Call}
				<div class="mt-1 flex items-center gap-2 opacity-80">
					<h3 class="text-sm">Parameters</h3>
					<div class="h-px flex-1 bg-gradient-to-r from-gray-500/20" />
				</div>
				<ul class="py-1 text-sm">
					{#each Object.entries(toolUpdate.call.parameters ?? {}) as [k, v]}
						<li>
							<span class="font-semibold">{k}</span>:
							<span>{v}</span>
						</li>
					{/each}
				</ul>
			{:else if toolUpdate.subtype === MessageToolUpdateType.Error}
				<div class="mt-1 flex items-center gap-2 opacity-80">
					<h3 class="text-sm">Error</h3>
					<div class="h-px flex-1 bg-gradient-to-r from-gray-500/20" />
				</div>
				<p class="text-sm">{toolUpdate.message}</p>
			{/if}
		{/each}
	</details>
{/if}

<style>
	details summary::-webkit-details-marker {
		display: none;
	}

	.loading-path {
		stroke-dasharray: 61.45;
		animation: loading 2s linear infinite;
	}
</style>
