#!/usr/bin/env python3
"""
Animate the original cell image with smooth PIL effects.
Source image: one consistent frame, transformed mathematically.
No AI inconsistency — just clean, programmatic animation.
"""
import math, io, subprocess
from pathlib import Path
from PIL import Image, ImageEnhance, ImageFilter, ImageChops

SRC   = "/tmp/cell_original.jpg"
OUT   = "/Users/bowang/.openclaw/workspace"
N     = 48       # frames in full loop
FPS   = 24       # output fps → 2-second seamless loop

def ease(t):
    """Smooth sine ease — maps 0→1 cyclically."""
    return (1 - math.cos(math.pi * 2 * t)) / 2   # 0 at t=0 & 1, peak at t=0.5

def zoom_center(img: Image.Image, factor: float) -> Image.Image:
    """Zoom into center by `factor` (1.0 = no zoom, 1.03 = 3% zoom in)."""
    w, h = img.size
    cx, cy = w // 2, h // 2
    nw, nh = int(w / factor), int(h / factor)
    left   = cx - nw // 2
    top    = cy - nh // 2
    right  = left + nw
    bottom = top + nh
    # clamp
    left, top     = max(0, left), max(0, top)
    right, bottom = min(w, right), min(h, bottom)
    return img.crop((left, top, right, bottom)).resize((w, h), Image.LANCZOS)

def add_glow(img: Image.Image, strength: float) -> Image.Image:
    """Subtle bloom / glow by blending a blurred brightened copy."""
    if strength < 0.01:
        return img
    blurred = img.filter(ImageFilter.GaussianBlur(radius=12))
    bright  = ImageEnhance.Brightness(blurred).enhance(1.0 + strength * 1.4)
    return Image.blend(img, bright, alpha=strength * 0.28)

def main():
    base = Image.open(SRC).convert("RGB")
    w, h = base.size
    frames: list[Image.Image] = []

    for i in range(N):
        t = i / N          # 0 → 1 (exclusive), smooth cycle

        # ── Phase offsets for overlapping effects ──────────────────────────
        t_breath  = ease(t)           # 0→1→0, one cycle
        t_glow    = ease((t + 0.25) % 1.0)   # quarter-phase offset
        t_color   = ease((t + 0.5) % 1.0)    # half-phase offset

        # ── 1. Nucleus breathing: subtle zoom 1.0x → 1.028x ──────────────
        zoom = 1.0 + 0.028 * t_breath
        frame = zoom_center(base, zoom)

        # ── 2. Brightness pulse (cell "breathing") ─────────────────────────
        brightness = 1.0 + 0.06 * t_glow
        frame = ImageEnhance.Brightness(frame).enhance(brightness)

        # ── 3. Saturation pulse (organelles pop at peak activity) ──────────
        sat = 1.0 + 0.12 * t_color
        frame = ImageEnhance.Color(frame).enhance(sat)

        # ── 4. Soft bloom glow on bright areas ────────────────────────────
        frame = add_glow(frame, t_glow * 0.18)

        # ── 5. Very subtle sharpness oscillation ──────────────────────────
        sharpness = 1.0 + 0.15 * (1 - t_breath)
        frame = ImageEnhance.Sharpness(frame).enhance(sharpness)

        frames.append(frame)
        if i % 8 == 0:
            print(f"  Frame {i+1}/{N} done", flush=True)

    print(f"\nSaving {N}-frame animated GIF...")
    gif_path = Path(OUT) / "cell-animation-v2.gif"
    frames[0].save(
        gif_path,
        save_all=True,
        append_images=frames[1:],
        duration=int(1000 / FPS),   # ms per frame
        loop=0,
        optimize=False,
    )
    print(f"  GIF: {gif_path.stat().st_size / 1e6:.1f} MB")

    print("Saving frames as PNG sequence for ffmpeg...")
    seq_dir = Path("/tmp/cell_seq")
    seq_dir.mkdir(exist_ok=True)
    for i, f in enumerate(frames):
        f.save(seq_dir / f"frame_{i:04d}.png")

    print("Encoding MP4...")
    mp4_path = Path(OUT) / "cell-animation-v2.mp4"
    subprocess.run([
        "/usr/local/bin/ffmpeg", "-y",
        "-framerate", str(FPS),
        "-i", str(seq_dir / "frame_%04d.png"),
        "-vf", "scale=1280:-2,format=yuv420p",
        "-c:v", "libx264", "-crf", "16", "-preset", "slow",
        "-movflags", "+faststart",
        str(mp4_path),
    ], capture_output=True)
    print(f"  MP4: {mp4_path.stat().st_size / 1e6:.1f} MB ✓")
    print(f"\nDone! {gif_path.name} + {mp4_path.name}")

if __name__ == "__main__":
    main()
