"""Generate the tileset palette `twu01palstd.itp` from tiles.py.

    python make_itp.py [out.itp]      # default: twu01palstd.itp

The toolset loads `<set>palstd.itp` when it registers a tileset; without it the
set fails to register (blank name in the New Area wizard, "could not create
area"). It's a GFF `ITP ` file: MAIN = a list of palette *category* folders, each
{ID byte, STRREF (dialog.tlk folder label), LIST of leaves}.

We emit TWO folders (the verified structure — AGENTS.md §2.3; wut01palstd.itp):
  * Features (STRREF 63261): one leaf per NON-paint tile, {NAME, RESREF=tile
    resref}. Each leaf is placeable ONLY because make_set.py backs it with a 1x1
    [GROUP#] whose Name == this NAME and Tile0 == that tile; the toolset finds the
    group by the RESREF (its first tile). Paint tiles (tiles.is_paint) are omitted
    here on purpose — they're brush-laid terrain, not click-placed features.
  * Terrain (STRREF 8282): the paintable vocabulary — `cobble` and `canal` (each
    RESREF = terrain name) plus the magic `eraser` leaf (RESREF `eraser`, STRREF
    63291, no NAME). `raised` is NOT here: it's a height on cobble (Raise/Lower),
    deferred to the next pass with HasHeightTransition=1 + a cobble-height matrix.
Multi-tile groups (folder 63262) would go in a third folder; we have none yet.
Built as JSON and converted to GFF with neverwinter.nim's nwn_gff (on PATH).
"""

import json
import os
import subprocess
import sys
import tempfile

import tiles

STRREF_FEATURES = 63261   # dialog.tlk label for the "Features" palette folder
STRREF_TERRAIN = 8282     # dialog.tlk label for the "Terrain" palette folder
STRREF_ERASER = 63291     # the magic eraser leaf (no NAME)


def leaf(name, resref):
    return {"__struct_id": 0,
            "NAME": {"type": "cexostring", "value": name},
            "RESREF": {"type": "resref", "value": resref}}


def eraser_leaf():
    return {"__struct_id": 0,
            "RESREF": {"type": "resref", "value": "eraser"},
            "STRREF": {"type": "dword", "value": STRREF_ERASER}}


def category(cid, strref, leaves):
    return {"__struct_id": 0,
            "ID": {"type": "byte", "value": cid},
            "STRREF": {"type": "dword", "value": strref},
            "LIST": {"type": "list", "value": leaves}}


def build():
    features = [leaf(tiles.group_name(s), tiles.resref(s))
                for s in tiles.TILES if not tiles.is_paint(s)]
    # Paintable terrains = every .set terrain EXCEPT 'raised' (which is a height on
    # cobble, not a terrain — the Raise/Lower tool, deferred to the next pass).
    paintable = [t for t in tiles.TERRAINS if t != "raised"]   # -> cobble, canal
    terrain = [leaf(t, t) for t in paintable] + [eraser_leaf()]
    return {
        "__data_type": "ITP ",
        "MAIN": {"type": "list", "value": [
            category(0, STRREF_FEATURES, features),   # ID/STRREF mirror wut01palstd.itp
            category(2, STRREF_TERRAIN, terrain),
        ]},
    }


def main():
    out = sys.argv[1] if len(sys.argv) > 1 else f"{tiles.PREFIX}palstd.itp"
    with tempfile.NamedTemporaryFile("w", suffix=".json", delete=False) as tf:
        json.dump(build(), tf)
        js = tf.name
    try:
        subprocess.run(["nwn_gff", "-i", js, "-l", "json", "-k", "gff", "-o", out],
                       check=True)
    finally:
        os.unlink(js)
    nfeat = sum(1 for s in tiles.TILES if not tiles.is_paint(s))
    print(f"wrote {out}  ({nfeat} features + paint:cobble,canal + eraser)")


if __name__ == "__main__":
    main()
