<script lang="ts">
	import { PUBLIC_BACKEND_WS_URL } from '$env/static/public';
	import { onMount } from 'svelte';
	import { nanoid } from 'nanoid';
	import { chatsStore, selectedChatId, loadingState } from '$lib/store';
	import type { Message, Chat } from '$lib/types';
	import { MessageType, Sender } from '$lib/types';
	import ChatInput from '$lib/ChatInput.svelte';
	import ChatMessage from '$lib/ChatMessage.svelte';
	import ChatNewBtn from '$lib/ChatNewBtn.svelte';

	$: isLoading = false;

	function clearStateMsg(t = 5000) {
		setTimeout(() => {
			$loadingState = '';
		}, t);
	}
	onMount(() => {
		// generateImage();
	});

	$: chatData = $chatsStore.find((chat) => chat.id === $selectedChatId);
	$: messages = chatData?.messages || [];

	$: console.log($chatsStore);

	function newChat() {
		const chatId = nanoid();
		const chat: Chat = {
			id: chatId,
			blurb: `New Chat - ${chatId}`,
			messages: [],
			timestamp: new Date().getTime()
		};
		$chatsStore = [chat].concat($chatsStore);
		$selectedChatId = chat.id;
	}

	function submitMessage(event: CustomEvent) {
		const value = event.detail;
		const message: Message = {
			sender: Sender.USER,
			id: nanoid(),
			type: MessageType.TEXT,
			content: value,
			timestamp: new Date().getTime()
		};
		$chatsStore = $chatsStore.map((chat) => {
			if (chat.id === $selectedChatId) {
				chat.messages.push(message);
			}
			return chat;
		});
	}
	const timeFormater = new Intl.DateTimeFormat('en-US', {
		day: 'numeric',
		month: 'short',
		hour: 'numeric',
		minute: 'numeric'
	}).format;
	async function generateImage() {
		if (isLoading) return;

		$loadingState = 'Pending';

		const sessionHash = crypto.randomUUID();
		const hashpayload = {
			fn_index: 1,
			session_hash: sessionHash
		};
		const image = '';
		const datapayload = {
			data: [
				'make him wear shirts', // prompt
				10.5, // text guidance
				1.5, // image guidance
				image,
				15, // steps
				'', // negative promtp,
				512, // width
				512, // height
				0 // seed
			]
		};

		const websocket = new WebSocket(PUBLIC_BACKEND_WS_URL);
		// websocket.onopen = async function (event) {
		// 	websocket.send(JSON.stringify({ hash: sessionHash }));
		// };
		websocket.onclose = (evt) => {
			if (!evt.wasClean) {
				$loadingState = 'Error';
			}
		};
		websocket.onmessage = async function (event) {
			try {
				const data = JSON.parse(event.data);
				$loadingState = '';
				switch (data.msg) {
					case 'send_hash':
						websocket.send(JSON.stringify(hashpayload));
						break;
					case 'send_data':
						$loadingState = 'Sending Data';
						websocket.send(JSON.stringify({ ...hashpayload, ...datapayload }));
						break;
					case 'queue_full':
						$loadingState = 'Queue full';
						websocket.close();

						return;
					case 'estimation':
						const { rank, queue_size } = data;
						$loadingState = `On queue ${rank}/${queue_size}`;
						break;
					case 'process_generating':
						$loadingState = data.success ? 'Generating' : 'Error';
						break;
					case 'process_completed':
						try {
							console.log(data);
							// const params = data.output.data[0] as {
							// 	is_nsfw: boolean;
							// 	image: {
							// 		url: string;
							// 		filename: string;
							// 	};
							// };
							// const isNSWF = params.is_nsfw;
							// if (isNSWF) {
							// 	throw new Error('NFSW');
							// }
							// // const imgBlob = await base64ToBlob(imgBase64);
							// const promptImgParams = {
							// 	imgURL: params.image.filename
							// };
							// // const imgURL = await uploadImage(imgBlob, promptImgParams);
							// // $promptImgStorage.set(imageKey, promptImgParams);
							// console.log(params.image.url);
							$loadingState = data.success ? 'Complete' : 'Error';
							clearStateMsg();
						} catch (err) {
							const tError = err as Error;
							$loadingState = tError?.message;

							clearStateMsg(10000);
						}
						websocket.close();
						return;
					case 'process_starts':
						$loadingState = 'Processing';
						break;
				}
			} catch (e) {
				console.error(e);
				$loadingState = 'Error';
			}
		};
	}
</script>

<div>
	<h1 class="text-2xl">CHATS</h1>
	<div class="grid min-h-[40rem] grid-cols-4">
		<div class="col-span-1 flex flex-col border-r p-4">
			<ChatNewBtn on:click={newChat} />
			<div class="max-h-[40rem] flex flex-col gap-2 overflow-y-scroll">
				{#if $chatsStore.length}
					{#each $chatsStore as chat}
						<button on:click={() => ($selectedChatId = chat.id)}>
							<div
								class="flex h-16 flex-col items-start justify-center rounded-xl bg-gray-100 px-4 text-gray-900 
						{chat.id === $selectedChatId ? 'bg-gray-400' : ''}"
							>
								<h3 class="w-full truncate font-semibold">{chat.blurb}</h3>
								<p class="w-full truncate text-sm text-gray-500">
									{timeFormater(new Date(chat.timestamp))}
								</p>
							</div>
						</button>
					{/each}
				{:else}
					<div
						class="flex h-16 flex-col items-start justify-center rounded-xl bg-gray-100 px-4 text-gray-900"
					>
						<h3 class="w-full truncate font-semibold">No chats</h3>
						<p class="w-full truncate text-sm text-gray-500">Start a new Chat!</p>
					</div>
				{/if}
			</div>
		</div>
		<div class="col-span-3 flex flex-col">
			{#each messages as message}
				<ChatMessage {message} />
			{/each}
			<ChatInput on:submitMessage={submitMessage} />
		</div>
	</div>
</div>

<style lang="postcss" scoped>
</style>
