<script
	module
	lang="ts"
>
	let index = 0
</script>

<script lang="ts">
	import type { Entity } from 'koota'

	import { TransformControls } from '@threlte/extras'
	import { PressedKeys } from 'runed'
	import { SvelteSet } from 'svelte/reactivity'
	import { Quaternion, Vector3 } from 'three'

	import { traits, useWorld } from '../ecs'
	import { useTransformControls } from '../hooks/useControls.svelte'
	import { useSelectedEntity } from '../hooks/useSelection.svelte'
	import { useSettings } from '../hooks/useSettings.svelte'
	import { quaternionToPose, vector3ToPose } from '../transform'

	import Frame from './Entities/Frame.svelte'

	const world = useWorld()
	const settings = useSettings()
	const transformControls = useTransformControls()
	const selectedEntity = useSelectedEntity()

	const entities = new SvelteSet<Entity>()
	const selectedCustomGeometry = $derived(
		[...entities].find((entity) => entity === selectedEntity.current)
	)

	const mode = $derived(settings.current.transformMode)

	const quaternion = new Quaternion()
	const vector3 = new Vector3()

	const keys = new PressedKeys()

	keys.onKeys('=', () => {
		const entity = world.spawn(
			traits.Name(`custom geometry ${++index}`),
			traits.Pose,
			traits.Box({ x: 100, y: 100, z: 100 }),
			traits.Removable
		)

		entities.add(entity)
	})

	keys.onKeys('-', () => {
		if (selectedCustomGeometry) {
			const entity = selectedCustomGeometry
			entity.destroy()
			entities.delete(entity)
			selectedEntity.set()
		}
	})

	$effect(() => {
		settings.current.transforming = selectedCustomGeometry !== undefined
	})
</script>

{#each entities as entity (entity)}
	<Frame {entity}>
		{#snippet children({ ref })}
			{#if selectedEntity.current === entity}
				{#key mode}
					<TransformControls
						object={ref}
						{mode}
						translationSnap={settings.current.snapping ? 0.1 : undefined}
						rotationSnap={settings.current.snapping ? Math.PI / 24 : undefined}
						scaleSnap={settings.current.snapping ? 0.1 : undefined}
						onmouseDown={() => {
							transformControls.setActive(true)
						}}
						onmouseUp={() => {
							transformControls.setActive(false)

							const pose = entity.get(traits.Pose)
							const box = entity.get(traits.Box)

							if (pose && mode === 'translate') {
								vector3ToPose(ref.getWorldPosition(vector3), pose)
								entity.set(traits.Pose, pose)
							} else if (pose && mode === 'rotate') {
								quaternionToPose(ref.getWorldQuaternion(quaternion), pose)
								ref.quaternion.copy(quaternion)
								entity.set(traits.Pose, pose)
							} else if (box && mode === 'scale') {
								box.x *= ref.scale.x
								box.y *= ref.scale.y
								box.z *= ref.scale.z
								entity.set(traits.Box, box)
								ref.scale.setScalar(1)
							}
						}}
					/>
				{/key}
			{/if}
		{/snippet}
	</Frame>
{/each}
