#!/usr/bin/env python3
"""Validate, package, and create a contact sheet for Starfall Haven PixelLab art."""
from pathlib import Path
import argparse
import json
import shutil
from PIL import Image, ImageDraw

REPRESENTATIVES = [
    "terrain/meadow_soil.png", "terrain/soil_rock.png",
    "objects/crystal_tree.png", "objects/ore_boulder.png",
    "objects/crashed_pod.png", "objects/campfire.png",
    "objects/shelter.png", "objects/workbench.png",
    "character/colonist/Idle/animations/idle/north/frame_000.png",
    "character/colonist/Idle/animations/idle/south/frame_002.png",
    "character/colonist/Idle/animations/walking/east/frame_003.png",
    "character/colonist/Idle/animations/walking/west/frame_007.png",
    "character/colonist/Idle/animations/using-tool/south/frame_004.png",
    "character/colonist/Idle/animations/melee/south/frame_005.png",
]


def validate(source: Path):
    records = []
    for path in sorted(source.rglob("*.png")):
        if path.name == "contact_sheet.png":
            continue
        with Image.open(path) as image:
            image.verify()
        with Image.open(path) as image:
            records.append({
                "path": str(path.relative_to(source)), "format": image.format,
                "width": image.width, "height": image.height, "mode": image.mode,
                "bytes": path.stat().st_size,
            })
    return records


def contact_sheet(source: Path, output: Path):
    cell_w, cell_h, columns = 260, 300, 4
    rows = (len(REPRESENTATIVES) + columns - 1) // columns
    sheet = Image.new("RGB", (cell_w * columns, cell_h * rows), (18, 24, 31))
    draw = ImageDraw.Draw(sheet)
    for index, relative in enumerate(REPRESENTATIVES):
        image = Image.open(source / relative).convert("RGBA")
        backdrop = Image.new("RGBA", (220, 220), (35, 45, 53, 255))
        checker = ImageDraw.Draw(backdrop)
        for y in range(0, 220, 16):
            for x in range(0, 220, 16):
                if (x // 16 + y // 16) % 2:
                    checker.rectangle((x, y, x + 15, y + 15), fill=(48, 59, 68, 255))
        scale = max(1, min(200 // image.width, 200 // image.height))
        display = image.resize((image.width * scale, image.height * scale), Image.Resampling.NEAREST)
        backdrop.alpha_composite(display, ((220 - display.width) // 2, (220 - display.height) // 2))
        left = index % columns * cell_w + 20
        top = index // columns * cell_h + 12
        sheet.paste(backdrop.convert("RGB"), (left, top))
        label = relative.replace("character/colonist/Idle/animations/", "anim/")
        for line_index in range(0, min(len(label), 102), 34):
            draw.text((left, top + 226 + (line_index // 34) * 16), label[line_index:line_index + 34], fill=(226, 235, 239))
    output.parent.mkdir(parents=True, exist_ok=True)
    sheet.save(output)


def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--source", type=Path, required=True)
    parser.add_argument("--destination", type=Path, required=True)
    parser.add_argument("--report", type=Path, required=True)
    parser.add_argument("--contact-sheet", type=Path, required=True)
    args = parser.parse_args()
    records = validate(args.source)
    if len(records) != 78:
        raise SystemExit(f"Expected 78 PNG assets, found {len(records)}")
    if args.destination.exists():
        shutil.rmtree(args.destination)
    for record in records:
        source = args.source / record["path"]
        destination = args.destination / record["path"]
        destination.parent.mkdir(parents=True, exist_ok=True)
        shutil.copy2(source, destination)
    args.report.parent.mkdir(parents=True, exist_ok=True)
    args.report.write_text(json.dumps({"images_checked": len(records), "images_valid": len(records), "files": records}, indent=2) + "\n")
    contact_sheet(args.source, args.contact_sheet)
    print(f"Validated and packaged {len(records)} PNG files")
    print(f"Destination: {args.destination}")
    print(f"Report: {args.report}")
    print(f"Contact sheet: {args.contact_sheet}")

if __name__ == "__main__":
    main()
