<script lang="ts">
	import { onMount } from 'svelte';

	let canvas: HTMLCanvasElement;
	let ctx: CanvasRenderingContext2D;
	let animationId: number;

	interface Snake {
		x: number;
		y: number;
		angle: number;
		color: string;
		trail: { x: number; y: number }[];
		alive: boolean;
		turnBias: number; // Unique personality trait
		aggressiveness: number; // How much they turn randomly
	}

	let snakes: Snake[] = [];
	const SPEED = 2;
	const TURN_SPEED = 0.05;
	const LINE_WIDTH = 4;
	const CANVAS_WIDTH = 300;
	const CANVAS_HEIGHT = 300;

	function initSnakes() {
		snakes = [
			{
				x: CANVAS_WIDTH * 0.3,
				y: CANVAS_HEIGHT * 0.4,
				angle: Math.random() * Math.PI * 2,
				color: '#00ff00',
				trail: [],
				alive: true,
				turnBias: (Math.random() - 0.5) * 0.02,
				aggressiveness: 0.8 + Math.random() * 0.4
			},
			{
				x: CANVAS_WIDTH * 0.7,
				y: CANVAS_HEIGHT * 0.6,
				angle: Math.random() * Math.PI * 2,
				color: '#0000ff',
				trail: [],
				alive: true,
				turnBias: (Math.random() - 0.5) * 0.02,
				aggressiveness: 0.8 + Math.random() * 0.4
			}
		];
	}

	function checkCollision(snake: Snake): boolean {
		// Check wall collision
		if (snake.x < 0 || snake.x > CANVAS_WIDTH || snake.y < 0 || snake.y > CANVAS_HEIGHT) {
			return true;
		}

		// Check collision with own trail (after some length)
		if (snake.trail.length > 100) {
			for (let i = 0; i < snake.trail.length - 50; i++) {
				const dist = Math.hypot(snake.x - snake.trail[i].x, snake.y - snake.trail[i].y);
				if (dist < LINE_WIDTH) {
					return true;
				}
			}
		}

		// Check collision with other snakes' trails
		for (const otherSnake of snakes) {
			if (otherSnake === snake) continue;
			if (otherSnake.trail.length < 30) continue; // Give other snake time to get away
			for (const point of otherSnake.trail) {
				const dist = Math.hypot(snake.x - point.x, snake.y - point.y);
				if (dist < LINE_WIDTH) {
					return true;
				}
			}
		}

		return false;
	}

	function checkDangerAhead(snake: Snake, distance: number = 80): number {
		// Check in five directions for more awareness
		const directions = [-0.6, -0.3, 0, 0.3, 0.6]; // left 34°, left 17°, straight, right 17°, right 34°
		const scores = [0, 0, 0, 0, 0];

		for (let d = 0; d < directions.length; d++) {
			const checkAngle = snake.angle + directions[d];
			
			// Check multiple points ahead for better space detection
			for (let dist = 20; dist <= distance; dist += 20) {
				const checkX = snake.x + Math.cos(checkAngle) * dist;
				const checkY = snake.y + Math.sin(checkAngle) * dist;

				// Check wall danger
				if (checkX < 30 || checkX > CANVAS_WIDTH - 30 || checkY < 30 || checkY > CANVAS_HEIGHT - 30) {
					scores[d] += 100;
				}

				// Check collision with trails
				for (const otherSnake of snakes) {
					const trailToCheck = otherSnake === snake ? snake.trail.slice(0, -60) : otherSnake.trail;
					for (const point of trailToCheck) {
						const distToPoint = Math.hypot(checkX - point.x, checkY - point.y);
						if (distToPoint < LINE_WIDTH * 8) {
							scores[d] += (1 - distToPoint / (LINE_WIDTH * 8)) * 30;
						}
					}
				}
			}
		}

		// Find the direction with the most open space (lowest score)
		let bestDirection = 2; // default to straight
		let lowestScore = scores[2];
		
		for (let i = 0; i < scores.length; i++) {
			if (scores[i] < lowestScore) {
				lowestScore = scores[i];
				bestDirection = i;
			}
		}

		// Return turn direction based on best option
		if (bestDirection === 2) return 0; // straight
		if (bestDirection < 2) return -1; // turn left
		return 1; // turn right
	}

	function updateSnake(snake: Snake) {
		if (!snake.alive) return;

		// Check for danger ahead and find open space
		const bestDirection = checkDangerAhead(snake);
		
		// Steer towards open space
		snake.angle += bestDirection * TURN_SPEED * 4;
		
		// Apply turn bias (personality) - reduced influence
		snake.angle += snake.turnBias * 0.5;
		
		// Less random turning since we're seeking open space
		if (Math.random() < 0.01 * snake.aggressiveness) {
			snake.angle += (Math.random() - 0.5) * TURN_SPEED * 4;
		}

		// Move forward
		snake.x += Math.cos(snake.angle) * SPEED;
		snake.y += Math.sin(snake.angle) * SPEED;

		// Add to trail
		snake.trail.push({ x: snake.x, y: snake.y });

		// Check collision
		if (checkCollision(snake)) {
			snake.alive = false;
		}
	}

	function draw() {
		if (!ctx) return;

		// Clear canvas
		ctx.fillStyle = '#000000';
		ctx.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);

		// Draw snakes
		for (const snake of snakes) {
			if (snake.trail.length < 2) continue;

			ctx.strokeStyle = snake.color;
			ctx.lineWidth = LINE_WIDTH;
			ctx.lineCap = 'round';
			ctx.lineJoin = 'round';

			ctx.beginPath();
			ctx.moveTo(snake.trail[0].x, snake.trail[0].y);
			for (let i = 1; i < snake.trail.length; i++) {
				ctx.lineTo(snake.trail[i].x, snake.trail[i].y);
			}
			ctx.stroke();
		}
	}

	function animate() {
		// Update all snakes
		for (const snake of snakes) {
			updateSnake(snake);
		}

		draw();

		// Check if any snake died
		const anyDead = snakes.some((s) => !s.alive);
		if (anyDead) {
			// Restart after a short delay
			setTimeout(() => {
				initSnakes();
				animate(); // Restart animation loop
			}, 1000);
		} else {
			animationId = requestAnimationFrame(animate);
		}
	}

	onMount(() => {
		ctx = canvas.getContext('2d')!;
		initSnakes();
		animate();

		return () => {
			if (animationId) {
				cancelAnimationFrame(animationId);
			}
		};
	});
</script>

<div class="w-full flex justify-center items-center">
	<canvas
		bind:this={canvas}
		width={CANVAS_WIDTH}
		height={CANVAS_HEIGHT}
		class="border border-gray-700 rounded-lg shadow-xl max-w-full h-auto"
	></canvas>
</div>
