#!/usr/bin/env python3
"""Map each world island/location to the production-line conveyors placed on it.

The recipe-bearing conveyors (game_conveyor_<product>_epb) are placed as named child
GameObjects inside the island_* prefabs in islands_assets_all.bundle (NOT via energy_grid,
which is only the power grid, and NOT in any config/designed-environment asset). This walks
every island prefab's Transform hierarchy, collects the conveyor instances (with local
position), and cross-references each recipe conveyor against extracted/production_lines.json.

Writes extracted/conveyor_placements.json.
"""
import os, sys, json, UnityPy

BUNDLES = "/home/downloadpizza/sand_tools/bundles"
PL = "/home/downloadpizza/sand_tools/extracted/production_lines.json"
OUT = "/home/downloadpizza/sand_tools/extracted/conveyor_placements.json"


def walk(go, seen, out):
    """Yield (name, localPosition) for every descendant GameObject."""
    for c in go.m_Components:
        try:
            co = c.read()
        except Exception:
            continue
        if co.object_reader.type.name != "Transform":
            continue
        for ch in co.m_Children:
            try:
                tr = ch.read()
                cgo = tr.m_GameObject.read()
            except Exception:
                continue
            pid = cgo.object_reader.path_id
            if pid in seen:
                continue
            seen.add(pid)
            pos = getattr(tr, "m_LocalPosition", None)
            xyz = [round(pos.x, 2), round(pos.y, 2), round(pos.z, 2)] if pos else None
            out.append((getattr(cgo, "m_Name", "?"), xyz))
            walk(cgo, seen, out)


def main():
    pl = json.load(open(PL))["production_lines"]
    env = UnityPy.load(os.path.join(BUNDLES, "islands_assets_all.bundle"))
    islands = {p.split("/")[-1].replace(".prefab", ""): obj
               for p, obj in env.container.items()
               if obj.type.name == "GameObject" and p.split("/")[-1].startswith("island_")}

    result = {}
    placed_recipes = set()
    for iname in sorted(islands):
        acc = []
        walk(islands[iname].read(), set(), acc)
        recipe_conv = []
        unmatched = []
        infra = []
        for name, pos in acc:
            base = name.replace("_epb", "")
            # product conveyors are game_conveyor_<product> (underscore); the slot/switch/
            # out/in pieces are game_conveyorXxx (no underscore) = generic infrastructure.
            if base.startswith("game_conveyor_"):
                if base in pl:
                    recipe_conv.append({"conveyor": base, "pos": pos, "recipe": pl[base]})
                    placed_recipes.add(base)
                else:
                    unmatched.append({"conveyor": base, "pos": pos})  # placed, no recipe key (name mismatch?)
            elif name.startswith("game_conveyor"):
                infra.append(name)
        if recipe_conv or unmatched:
            result[iname] = {"recipes": recipe_conv,
                             "product_conveyors_without_matching_recipe": unmatched,
                             "infrastructure": sorted(set(infra))}

    unplaced = sorted(set(pl) - placed_recipes)
    out = {
        "_source": "islands_assets_all.bundle island_* prefab hierarchy "
                   "(game_conveyor_<product>_epb child GameObjects); recipes from production_lines.json",
        "_unplaced_recipes": unplaced,
        "islands": result,
    }
    json.dump(out, open(OUT, "w"), indent=1)

    def fmt(r):
        i = " + ".join("%sx %s" % (x["amount"], x["itemId"]) for x in r["inputs"])
        o = " + ".join("%sx %s" % (x["amount"], x["itemId"]) for x in r["outputs"])
        return "%s -> %s (%ss)" % (i, o, r["craftTimeSeconds"])

    print("wrote %s\n" % OUT)
    for iname, d in result.items():
        print("### %s" % iname.replace("island_", ""))
        for rc in d["recipes"]:
            print("   %-34s %s" % (rc["conveyor"].replace("game_conveyor_", ""), fmt(rc["recipe"])))
        for u in d["product_conveyors_without_matching_recipe"]:
            print("   %-34s (placed, no recipe blueprint of this exact name)" % u["conveyor"].replace("game_conveyor_", ""))
    print("\nrecipe blueprints NOT placed on any island:", unplaced)


if __name__ == "__main__":
    main()
