<script lang="ts">
	import { T, useTask } from '@threlte/core';
	import { onMount } from 'svelte';
	import * as THREE from 'three';
	import { themeColors, mode } from '$lib/stores/theme';

	interface Props {
		particleCount?: number;
	}

	let { particleCount = 500 }: Props = $props();

	let particlesGeometry: THREE.BufferGeometry;
	let particlesMaterial: THREE.PointsMaterial;
	let particles = $state<THREE.Points | null>(null);
	let positions: Float32Array;
	let velocities: Float32Array;
	let time = 0;

	// Reactive theme values - use accent or a darker color for light mode visibility
	const currentMode = $derived($mode);
	const particleColor = $derived(
		currentMode === 'dark' 
			? $themeColors.primary 
			: $themeColors.accent || $themeColors.primary
	);

	// Create particles
	function createParticles() {
		positions = new Float32Array(particleCount * 3);
		velocities = new Float32Array(particleCount * 3);

		for (let i = 0; i < particleCount; i++) {
			const i3 = i * 3;
			// Spread particles in a larger area
			positions[i3] = (Math.random() - 0.5) * 20;
			positions[i3 + 1] = (Math.random() - 0.5) * 20;
			positions[i3 + 2] = (Math.random() - 0.5) * 20;

			// Random velocities
			velocities[i3] = (Math.random() - 0.5) * 0.01;
			velocities[i3 + 1] = (Math.random() - 0.5) * 0.01;
			velocities[i3 + 2] = (Math.random() - 0.5) * 0.01;
		}

		particlesGeometry = new THREE.BufferGeometry();
		particlesGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));

		particlesMaterial = new THREE.PointsMaterial({
			size: 0.05,
			color: new THREE.Color(particleColor),
			sizeAttenuation: true,
			transparent: true,
			opacity: currentMode === 'dark' ? 0.6 : 0.8,
			blending: currentMode === 'dark' ? THREE.AdditiveBlending : THREE.NormalBlending,
			depthWrite: false
		});

		particles = new THREE.Points(particlesGeometry, particlesMaterial);
	}

	onMount(() => {
		createParticles();
	});

	// Update particle color and opacity based on theme
	$effect(() => {
		if (particlesMaterial) {
			particlesMaterial.color.set(particleColor);
			particlesMaterial.opacity = currentMode === 'dark' ? 0.6 : 0.8;
			particlesMaterial.blending = currentMode === 'dark' ? THREE.AdditiveBlending : THREE.NormalBlending;
			particlesMaterial.needsUpdate = true;
		}
	});

	// Animation loop
	useTask((delta) => {
		if (!particles || !particlesGeometry) return;

		time += delta;
		const positionAttribute = particlesGeometry.getAttribute('position') as THREE.BufferAttribute;
		const positionArray = positionAttribute.array as Float32Array;

		for (let i = 0; i < particleCount; i++) {
			const i3 = i * 3;
			
			// Add some wave motion
			positionArray[i3] += velocities[i3] + Math.sin(time + i * 0.1) * 0.001;
			positionArray[i3 + 1] += velocities[i3 + 1] + Math.cos(time + i * 0.1) * 0.001;
			positionArray[i3 + 2] += velocities[i3 + 2];

			// Wrap around boundaries
			if (positionArray[i3] > 10) positionArray[i3] = -10;
			if (positionArray[i3] < -10) positionArray[i3] = 10;
			if (positionArray[i3 + 1] > 10) positionArray[i3 + 1] = -10;
			if (positionArray[i3 + 1] < -10) positionArray[i3 + 1] = 10;
			if (positionArray[i3 + 2] > 10) positionArray[i3 + 2] = -10;
			if (positionArray[i3 + 2] < -10) positionArray[i3 + 2] = 10;
		}

		positionAttribute.needsUpdate = true;
		
		// Rotate the entire particle system slowly
		particles.rotation.y += delta * 0.05;
		particles.rotation.x += delta * 0.02;
	});
</script>

{#if particles}
	<T is={particles} />
{/if}
