import pygame
import json
import os
import numpy as np
import random

POOL_FILE = "qrng_pool.json"

# Load entropy pool
def load_entropy_pool():
    if not os.path.exists(POOL_FILE):
        print("\u26a0\ufe0f No entropy pool found!")
        return []
    with open(POOL_FILE, 'r') as f:
        data = json.load(f)
        return data.get('pool', [])

class Particle:
    def __init__(self, x, y, vx, vy, color, lifespan, radius):
        self.x = x
        self.y = y
        self.vx = vx
        self.vy = vy
        self.color = color  # RGB
        self.lifespan = lifespan
        self.age = 0
        self.radius = radius

    def update(self):
        self.x += self.vx
        self.y += self.vy
        self.age += 1

        self.vy += 0.02  # Gravity pull
        self.vx *= 0.99  # Horizontal damping


    def is_alive(self):
        return self.age < self.lifespan

    def draw(self, screen):
        alpha = max(0, 255 * (1 - self.age / self.lifespan))
        color = (*self.color, int(alpha))  # RGBA
        surface = pygame.Surface((self.radius * 2, self.radius * 2), pygame.SRCALPHA)
        pygame.draw.circle(surface, color, (self.radius, self.radius), self.radius)
        screen.blit(surface, (self.x, self.y))


def run():
    pool = load_entropy_pool()
    if not pool:
        return

    pygame.init()
    WIDTH, HEIGHT = 800, 600
    screen = pygame.display.set_mode((WIDTH, HEIGHT), pygame.RESIZABLE)
    pygame.display.set_caption("Quantum Particles")

    clock = pygame.time.Clock()
    particles = []
    pool_index = 0

    running = True
    while running:
        screen.fill((0, 0, 0))
        WIDTH, HEIGHT = screen.get_size()  # Dynamically track window size

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            elif event.type == pygame.VIDEORESIZE:
                WIDTH, HEIGHT = event.size
                screen = pygame.display.set_mode((WIDTH, HEIGHT), pygame.RESIZABLE)

        pixel_size = 128  # Grid size

        for grid_y in range(0, HEIGHT, pixel_size):
            for grid_x in range(0, WIDTH, pixel_size):
                # Always spawn at grid positions
                x = grid_x
                y = grid_y

                jitter_x = random.uniform(-pixel_size / 2, pixel_size / 2)
                jitter_y = random.uniform(-pixel_size / 2, pixel_size / 2)
                x = grid_x + jitter_x
                y = grid_y + jitter_y

                
                # Pull particle attributes from entropy pool (cycling)
                vx = (pool[pool_index % len(pool)] - 128) / 64.0
                pool_index += 1
                vy = (pool[pool_index % len(pool)] - 128) / 64.0
                pool_index += 1
                hue = (pool[pool_index % len(pool)] / 255.0)
                pool_index += 1
                lifespan = 60 + (pool[pool_index % len(pool)] % 120)
                pool_index += 1
                radius = 2 + (pool[pool_index % len(pool)] % 4)
                pool_index += 1

                # Convert hue to RGB
                color_obj = pygame.Color(0)
                color_obj.hsva = (hue * 360, 100, 100, 100)
                color = color_obj.r, color_obj.g, color_obj.b

                particles.append(Particle(x, y, vx, vy, color, lifespan, radius))


        # Update and draw particles
        for p in particles[:]:
            p.update()
            if not p.is_alive():
                particles.remove(p)
            else:
                p.draw(screen)

        pygame.display.flip()
        clock.tick(60)

    pygame.quit()
