import tkinter as tk
import random
import math

WIDTH, HEIGHT = 800, 600
FPS = 16

COLORS = [
    ["#ff4444", "#ff6666", "#ff8888"],
    ["#44ff44", "#66ff66", "#88ff88"],
    ["#4444ff", "#6666ff", "#8888ff"],
    ["#ffff44", "#ffff66", "#ffff88"],
    ["#ff44ff", "#ff66ff", "#ff88ff"],
    ["#44ffff", "#66ffff", "#88ffff"],
    ["#ffa500", "#ffb733", "#ffc966"],
]

STIPPLES = ["gray25", "gray50", "gray75"]


class Particle:
    def __init__(self, x, y, vx, vy, color, size, life):
        self.x = x
        self.y = y
        self.vx = vx
        self.vy = vy
        self.color = color
        self.size = size
        self.life = life
        self.max_life = life
        self.id = None

    def update(self):
        self.vx *= 0.97
        self.vy *= 0.97
        self.vy += 0.12
        self.x += self.vx
        self.y += self.vy
        self.life -= 1

    def draw(self, canvas):
        if self.life <= 0:
            return
        ratio = max(0.2, self.life / self.max_life)
        size = max(1, self.size * ratio)

        stipple = STIPPLES[min(2, int((1 - ratio) * 3))]

        self.id = canvas.create_oval(
            self.x - size, self.y - size,
            self.x + size, self.y + size,
            fill=self.color,
            outline="",
            stipple=stipple
        )

    def destroy(self, canvas):
        if self.id:
            canvas.delete(self.id)


class Rocket:
    def __init__(self, canvas, x, ty, colors):
        self.canvas = canvas
        self.x = x
        self.y = HEIGHT
        self.target_y = ty
        self.vy = -random.uniform(5, 7)
        self.vx = random.uniform(-0.5, 0.5)
        self.colors = colors
        self.particles = []
        self.alive = True

        self.id = canvas.create_oval(
            x - 2, HEIGHT - 4,
            x + 2, HEIGHT,
            fill="#ffa500",
            outline=""
        )

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

        if self.vy >= 0 or self.y < self.target_y:
            self.explode()
            return

        self.canvas.coords(
            self.id,
            self.x - 2, self.y - 2,
            self.x + 2, self.y + 2
        )

    def explode(self):
        self.alive = False
        self.canvas.delete(self.id)

        for _ in range(random.randint(35, 55)):
            angle = random.uniform(0, math.pi * 2)
            speed = random.uniform(1.5, 5)
            self.particles.append(Particle(
                self.x, self.y,
                math.cos(angle) * speed,
                math.sin(angle) * speed,
                random.choice(self.colors),
                random.uniform(2, 4),
                random.randint(40, 80)
            ))

    def run(self, canvas):
        for p in self.particles[:]:
            p.update()
            p.draw(canvas)
            if p.life <= 0:
                p.destroy(canvas)
                self.particles.remove(p)

    def is_dead(self):
        return not self.alive and not self.particles


class FireworkApp:
    def __init__(self, root):
        self.root = root
        self.root.title("021. 动态烟花")
        self.root.geometry(f"{WIDTH}x{HEIGHT}")
        self.root.resizable(False, False)

        self.canvas = tk.Canvas(root, width=WIDTH, height=HEIGHT, bg="black")
        self.canvas.pack()

        self.rockets = []

        self.canvas.bind("<Button-1>", self.launch)
        self.root.bind("<a>", self.toggle_auto)
        self.root.bind("<c>", lambda e: self.clear())
        self.auto = True

        self.status = self.canvas.create_text(
            10, 10, anchor="nw",
            text="自动模式: 开启",
            fill="#aaaaaa", font=("Consolas", 10)
        )

        self.run()

    def launch(self, e):
        self.rockets.append(Rocket(
            self.canvas,
            e.x,
            random.randint(80, HEIGHT // 2),
            random.choice(COLORS)
        ))

    def toggle_auto(self, e):
        self.auto = not self.auto
        self.canvas.itemconfig(
            self.status,
            text=f"自动模式: {'开启' if self.auto else '关闭'}"
        )

    def clear(self):
        for r in self.rockets:
            r.alive = False
            r.particles.clear()
        self.rockets.clear()
        self.canvas.delete("all")
        self.status = self.canvas.create_text(
            10, 10, anchor="nw",
            text=f"自动模式: {'开启' if self.auto else '关闭'}",
            fill="#aaaaaa", font=("Consolas", 10)
        )

    def run(self):
        if self.auto and random.random() < 0.03:
            self.rockets.append(Rocket(
                self.canvas,
                random.randint(100, WIDTH - 100),
                random.randint(80, HEIGHT // 2),
                random.choice(COLORS)
            ))

        for r in self.rockets[:]:
            if r.alive:
                r.update()
            r.run(self.canvas)
            if r.is_dead():
                self.rockets.remove(r)

        self.root.after(FPS, self.run)


if __name__ == "__main__":
    root = tk.Tk()
    FireworkApp(root)
    root.mainloop()