#!/usr/bin/env python3
"""Generate the Nexus launcher icon (adaptive icon layers + legacy/round fallbacks) with PIL.
Dark space background, cyan->violet ring around a geometric "N"."""
import math, os, random
from PIL import Image, ImageDraw, ImageFilter, ImageChops

RES = os.path.join(os.path.dirname(__file__), "..", "app_pojavlauncher", "src", "main", "res")
S = 1024  # master size (adaptive layer = 108dp)
CYAN = (34, 211, 238)
VIOLET = (139, 92, 246)

def lerp(a, b, t):
    return tuple(int(a[i] + (b[i] - a[i]) * t) for i in range(3))

def background():
    im = Image.new("RGB", (S, S))
    px = im.load()
    cx, cy = S * 0.62, S * 0.35
    for y in range(S):
        for x in range(S):
            d = math.hypot(x - cx, y - cy) / S
            t = min(1.0, d * 1.25)
            px[x, y] = lerp((38, 24, 78), (5, 7, 18), t)
    # nebula glow
    glow = Image.new("RGB", (S, S), (0, 0, 0))
    g = ImageDraw.Draw(glow)
    g.ellipse((S * 0.05, S * 0.55, S * 0.75, S * 1.1), fill=(10, 60, 90))
    g.ellipse((S * 0.45, S * 0.0, S * 1.05, S * 0.5), fill=(60, 20, 100))
    glow = glow.filter(ImageFilter.GaussianBlur(S * 0.12))
    im = ImageChops.add(im, glow)
    d = ImageDraw.Draw(im)
    rnd = random.Random(7)
    for _ in range(170):
        x, y = rnd.random() * S, rnd.random() * S
        r = rnd.choice([1, 1, 1, 2, 2, 3])
        b = rnd.randint(140, 255)
        d.ellipse((x - r, y - r, x + r, y + r), fill=(b, b, min(255, b + 20)))
    return im

def gradient_mask_fill(mask):
    """Fill a mask with a diagonal cyan->violet gradient."""
    grad = Image.new("RGB", (S, S))
    gp = grad.load()
    for y in range(S):
        for x in range(S):
            t = max(0.0, min(1.0, (x + y) / (2 * S) * 1.3 - 0.15))
            gp[x, y] = lerp(CYAN, VIOLET, t)
    out = Image.new("RGBA", (S, S), (0, 0, 0, 0))
    out.paste(grad, (0, 0), mask)
    return out

def foreground():
    mask = Image.new("L", (S, S), 0)
    d = ImageDraw.Draw(mask)
    c = S / 2
    # ring (kept inside the 66dp safe zone: radius <= 0.305*S)
    ro, ri = S * 0.300, S * 0.262
    d.ellipse((c - ro, c - ro, c + ro, c + ro), fill=255)
    d.ellipse((c - ri, c - ri, c + ri, c + ri), fill=0)
    # small orbit gap + satellite
    ang = math.radians(-40)
    sx, sy = c + math.cos(ang) * (ro + ri) / 2, c + math.sin(ang) * (ro + ri) / 2
    gap = S * 0.045
    d.ellipse((sx - gap, sy - gap, sx + gap, sy + gap), fill=0)
    sr = S * 0.026
    d.ellipse((sx - sr, sy - sr, sx + sr, sy + sr), fill=255)
    # geometric N
    w, h, t = S * 0.25, S * 0.30, S * 0.062
    x0, y0 = c - w / 2, c - h / 2
    d.rectangle((x0, y0, x0 + t, y0 + h), fill=255)
    d.rectangle((x0 + w - t, y0, x0 + w, y0 + h), fill=255)
    d.polygon([(x0, y0), (x0 + t * 1.15, y0), (x0 + w, y0 + h), (x0 + w - t * 1.15, y0 + h)], fill=255)
    mask = mask.filter(ImageFilter.GaussianBlur(1.2))
    fg = gradient_mask_fill(mask)
    # outer glow
    glow_mask = mask.filter(ImageFilter.GaussianBlur(S * 0.03))
    glow = gradient_mask_fill(glow_mask.point(lambda v: int(v * 0.55)))
    return Image.alpha_composite(glow, fg)

def main():
    bg = background()
    fg = foreground()
    full = Image.alpha_composite(bg.convert("RGBA"), fg)
    dens = {"mdpi": 1, "hdpi": 1.5, "xhdpi": 2, "xxhdpi": 3, "xxxhdpi": 4}
    for name, k in dens.items():
        d = os.path.join(RES, "mipmap-" + name)
        os.makedirs(d, exist_ok=True)
        layer = int(108 * k)
        legacy = int(48 * k)
        bg.resize((layer, layer), Image.LANCZOS).save(os.path.join(d, "ic_launcher_background.webp"), lossless=True)
        fg.resize((layer, layer), Image.LANCZOS).save(os.path.join(d, "ic_launcher_foreground.webp"), lossless=True)
        # legacy icons: crop the 72dp visible area of the adaptive icon
        crop = int(S * 18 / 108)
        vis = full.crop((crop, crop, S - crop, S - crop)).resize((legacy, legacy), Image.LANCZOS)
        sq = Image.new("L", (legacy, legacy), 0)
        ImageDraw.Draw(sq).rounded_rectangle((0, 0, legacy - 1, legacy - 1), radius=legacy * 0.18, fill=255)
        out = Image.new("RGBA", (legacy, legacy), (0, 0, 0, 0)); out.paste(vis, (0, 0), sq)
        out.save(os.path.join(d, "ic_launcher.webp"), lossless=True)
        rd = Image.new("L", (legacy, legacy), 0)
        ImageDraw.Draw(rd).ellipse((0, 0, legacy - 1, legacy - 1), fill=255)
        out = Image.new("RGBA", (legacy, legacy), (0, 0, 0, 0)); out.paste(vis, (0, 0), rd)
        out.save(os.path.join(d, "ic_launcher_round.webp"), lossless=True)
    full.resize((512, 512), Image.LANCZOS).save(os.path.join(os.path.dirname(__file__), "nexus_icon_512.png"))
    # monochrome notification icon (white glyph on transparent)
    notif = fg.split()[3].crop((int(S*0.18),)*2 + (int(S*0.82),)*2).resize((184, 184), Image.LANCZOS)
    n = Image.new("RGBA", (184, 184), (255, 255, 255, 0)); n.putalpha(notif)
    n.save(os.path.join(RES, "drawable", "notif_icon.png"))

if __name__ == "__main__":
    main()
