<script lang="ts">
	import { fileOrder, files, getFileIndex, selectedFiles, selectFiles } from '$lib/stores';

	import { Button } from '$lib/components/ui/button';
	import { ScrollArea } from '$lib/components/ui/scroll-area/index';
	import Sortable from 'sortablejs/Sortable';

	import type { GPXFile } from 'gpx';

	import { afterUpdate, onMount } from 'svelte';
	import { get } from 'svelte/store';

	let container: HTMLDivElement;
	let buttons: HTMLDivElement[] = [];
	let sortable: Sortable;

	function selectFile(file: GPXFile) {
		selectedFiles.update((selectedFiles) => {
			selectedFiles.clear();
			selectedFiles.add(file);
			return selectedFiles;
		});
	}

	function addSelectFile(file: GPXFile) {
		selectedFiles.update((selectedFiles) => {
			selectedFiles.add(file);
			return selectedFiles;
		});
	}

	function selectAllFiles() {
		selectedFiles.update((selectedFiles) => {
			get(files).forEach((file) => {
				selectedFiles.add(get(file));
			});
			return selectedFiles;
		});
	}

	function deselectFile(file: GPXFile) {
		selectedFiles.update((selectedFiles) => {
			selectedFiles.delete(file);
			return selectedFiles;
		});
	}

	function updateFileOrder() {
		let newFileOrder = sortable.toArray().map((index: string) => get(get(files)[parseInt(index)]));
		if (newFileOrder.length !== get(fileOrder).length) {
			fileOrder.set(newFileOrder);
			return;
		}

		for (let i = 0; i < newFileOrder.length; i++) {
			if (newFileOrder[i] !== get(fileOrder)[i]) {
				fileOrder.set(newFileOrder);
				return;
			}
		}
	}

	onMount(() => {
		sortable = Sortable.create(container, {
			forceAutoScrollFallback: true,
			multiDrag: true,
			multiDragKey: 'shift',
			selectedClass: 'sortable-selected',
			avoidImplicitDeselect: true,
			onSelect: (e) => {
				const index = parseInt(e.item.getAttribute('data-id'));
				addSelectFile(get($files[index]));
				if (!e.originalEvent.shiftKey && $selectedFiles.size > 1) {
					$selectedFiles.forEach((file) => {
						if (file !== get($files[index])) {
							deselectFile(file);
							const index = getFileIndex(file);
							Sortable.utils.deselect(buttons[index]);
						}
					});
				}
			},
			onDeselect: (e) => {
				const index = parseInt(e.item.getAttribute('data-id'));
				deselectFile(get($files[index]));
			},
			onSort: () => {
				updateFileOrder();
			}
		});
	});

	selectFiles.update(() => {
		return {
			select: (file: GPXFile) => {
				buttons.forEach((button) => {
					if (button) {
						Sortable.utils.deselect(button);
					}
				});
				const index = getFileIndex(file);
				Sortable.utils.select(buttons[index]);
				selectFile(file);
			},
			addSelect: (file: GPXFile) => {
				const index = getFileIndex(file);
				Sortable.utils.select(buttons[index]);
				addSelectFile(file);
			},
			selectAllFiles: () => {
				$files.forEach((file, index) => {
					Sortable.utils.select(buttons[index]);
				});
				selectAllFiles();
			},
			removeSelect: (file: GPXFile) => {
				const index = getFileIndex(file);
				Sortable.utils.deselect(buttons[index]);
				deselectFile(file);
			}
		};
	});

	afterUpdate(updateFileOrder);
</script>

<div class="h-10 -translate-y-10 w-full pointer-events-none">
	<ScrollArea orientation="horizontal" class="w-full h-full" scrollbarXClasses="h-2">
		<div bind:this={container} class="flex flex-row gap-1">
			{#each $files as file, index}
				<div
					bind:this={buttons[index]}
					data-id={index}
					class="pointer-events-auto first:ml-1 last:mr-1 mb-1 bg-transparent"
				>
					<Button variant="outline" class="h-9 px-1.5 py-1 border-none shadow-md">
						{get(file).metadata.name}
					</Button>
				</div>
			{/each}
		</div>
	</ScrollArea>
</div>

<style lang="postcss">
	div :global(button) {
		@apply bg-accent;
		@apply hover:bg-background;
	}

	div :global(.sortable-selected > button) {
		@apply bg-background;
	}
</style>
