from __future__ import annotations

import csv
import math
from pathlib import Path

from PIL import Image, ImageDraw

ROOT = Path(__file__).resolve().parents[3]
LAB = ROOT / "content" / "experiments" / "favicon-cross-device"
OUT = LAB / "outputs"
ASSETS = ROOT / "assets" / "favicon-cross-device"
S = 512


def draw_source() -> Image.Image:
    scale = 4
    im = Image.new("RGBA", (S * scale, S * scale), (0, 0, 0, 0))
    d = ImageDraw.Draw(im)
    def xy(v: int) -> int:
        return v * scale

    # A transparent, two-surface glyph with small corner marks outside the
    # PWA safe circle, making the crop measurable without using a real brand.
    mint = (185, 243, 109, 255)
    blue = (139, 211, 255, 255)
    pale = (243, 247, 250, 255)
    for x, y in ((12, 12), (452, 12), (12, 452), (452, 452)):
        d.rounded_rectangle((xy(x), xy(y), xy(x + 48), xy(y + 48)), radius=xy(9), fill=mint)
    d.rounded_rectangle((xy(100), xy(137), xy(349), xy(326)), radius=xy(27), outline=blue, width=xy(17))
    d.line((xy(123), xy(360), xy(326), xy(360)), fill=pale, width=xy(15))
    d.rounded_rectangle((xy(306), xy(194), xy(407), xy(357)), radius=xy(20), outline=mint, width=xy(15))
    d.line((xy(328), xy(326), xy(384), xy(326)), fill=blue, width=xy(9))
    d.line((xy(144), xy(216), xy(222), xy(216)), fill=pale, width=xy(13))
    d.line((xy(144), xy(255), xy(258), xy(255)), fill=blue, width=xy(13))
    return im.resize((S, S), Image.Resampling.LANCZOS)


def alpha_counts(im: Image.Image) -> tuple[int, int, int]:
    alpha = im.convert("RGBA").getchannel("A")
    hist = alpha.histogram()
    total = im.width * im.height
    transparent = hist[0]
    nonopaque = sum(hist[:255])
    return total, transparent, nonopaque


def main() -> None:
    OUT.mkdir(parents=True, exist_ok=True)
    ASSETS.mkdir(parents=True, exist_ok=True)
    source = draw_source()
    source.save(OUT / "same-source.png", optimize=True)
    ico = OUT / "desktop-favicon.ico"
    source.save(ico, format="ICO", sizes=[(256, 256), (48, 48), (32, 32), (16, 16)])
    ios = source.resize((180, 180), Image.Resampling.LANCZOS)
    ios.save(OUT / "apple-touch-icon-180.png", optimize=True)

    # Maskable web-app icons are full-bleed; this sample composites the same
    # foreground onto one flat background before applying a test circle.
    bg = Image.new("RGBA", (S, S), (11, 26, 41, 255))
    bg.alpha_composite(source)
    bg.convert("RGB").save(OUT / "pwa-maskable-512.png", optimize=True)

    # A circular 80%-diameter mask is the documented Chrome safe-zone guide.
    # It is a test mask, not a claim that every Android launcher uses a circle.
    mask = Image.new("L", (S, S), 0)
    md = ImageDraw.Draw(mask)
    radius = int(S * 0.4)
    md.ellipse((S // 2 - radius, S // 2 - radius, S // 2 + radius, S // 2 + radius), fill=255)
    masked = bg.copy()
    masked.putalpha(mask)
    masked.save(OUT / "pwa-circular-mask-preview.png", optimize=True)

    rows: list[dict[str, str]] = []
    total, transparent, nonopaque = alpha_counts(source)
    rows.append({"asset": "source PNG", "size": "512x512", "bytes": str((OUT / "same-source.png").stat().st_size), "transparent_pixels": str(transparent), "nonopaque_pixels": str(nonopaque), "mask": "none"})
    entry = Image.open(ico)
    sizes = sorted(entry.info.get("sizes", []), reverse=True)
    for w, h in sizes:
        layer = entry.ico.getimage((w, h)).convert("RGBA")
        pix, zero, partial = alpha_counts(layer)
        rows.append({"asset": "desktop ICO layer", "size": f"{w}x{h}", "bytes": str(ico.stat().st_size), "transparent_pixels": str(zero), "nonopaque_pixels": str(partial), "mask": "none"})
    pix, zero, partial = alpha_counts(ios)
    rows.append({"asset": "Apple touch PNG", "size": "180x180", "bytes": str((OUT / "apple-touch-icon-180.png").stat().st_size), "transparent_pixels": str(zero), "nonopaque_pixels": str(partial), "mask": "no OS mask applied to file"})
    pix, zero, partial = alpha_counts(bg)
    rows.append({"asset": "PWA maskable PNG", "size": "512x512", "bytes": str((OUT / "pwa-maskable-512.png").stat().st_size), "transparent_pixels": str(zero), "nonopaque_pixels": str(partial), "mask": "opaque full-bleed input"})

    source_alpha = source.getchannel("A")
    source_pixels = source_alpha.load()
    mask_pixels = mask.load()
    artwork_before = sum(1 for y in range(S) for x in range(S) if source_pixels[x, y] > 0)
    artwork_clipped = sum(1 for y in range(S) for x in range(S) if source_pixels[x, y] > 0 and mask_pixels[x, y] == 0)
    rows.append({"asset": "same source foreground under test circle", "size": "512x512", "bytes": "n/a", "transparent_pixels": "n/a", "nonopaque_pixels": "n/a", "mask": f"foreground pixels before={artwork_before}; clipped={artwork_clipped}; retained={artwork_before-artwork_clipped}; mask circle diameter=80% canvas"})

    with (LAB / "measurements.csv").open("w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=list(rows[0]))
        writer.writeheader()
        writer.writerows(rows)

    print(f"source={S}x{S} transparent={transparent} nonopaque={nonopaque}")
    for row in rows[1:]:
        print(" | ".join(f"{key}={value}" for key, value in row.items()))


if __name__ == "__main__":
    main()
