import json
import sys

if len(sys.argv) < 3:
    print("please provide the json generated by https://github.com/Kakoen/valheim-save-tools and the output filename as command line arguments")
    sys.exit(1)

print("# opening input file")
with open(sys.argv[1]) as f:
    print("# parsing input file")
    data = json.load(f)

print("# determinining generated sectors")

def vec2(d):
    """converts an object-style vector (as output by valheim-save-tools) into a pair"""
    return d["x"], d["y"]

generated_sectors = set(map(vec2, data["zones"]["generatedZones"]))

print("found {} generated sectors".format(len(generated_sectors)))

print("# determining inhabited sector(s)")

inhabited_sectors = set()
for zdo in data["zdoList"]:
    # TODO: support hash codes (for now I'm leaving the lookup to the valheim-save-tools)
    if "creator" in (zdo.get("longsByName") or {}):
        inhabited_sectors.add(vec2(zdo["sector"]))
    # TODO: check zdo["prefab"] in {hash("digg"), hash("BossStone_TheElder"), hash("BossStone_Bonemass"), hash("BossStone_Eikthyr"), hash("BossStone_Yagluth"), hash("BossStone_DragonQueen")}

print("found {} inhabited sector(s)".format(len(inhabited_sectors)))

print("TODO: also find boss sectors, probably?")

all_sectors = generated_sectors | inhabited_sectors
min_x = min(map(lambda p: p[0], all_sectors))
min_y = min(map(lambda p: p[1], all_sectors))
max_x = max(map(lambda p: p[0], all_sectors))
max_y = max(map(lambda p: p[1], all_sectors))

print("generated sectors are within (({}, {}), ({}, {}))".format(min_x, min_y, max_x, max_y))

MAX_COORD_CUTOFF = 10000

if max_x > MAX_COORD_CUTOFF or max_y > MAX_COORD_CUTOFF:
    # TODO: I probably should not just ignore these. Maybe they're dungeons? What happens if I delete the overworld for a dungeon? :ThisIsFine:
    print("Those are some mysteriously high coordinates. I'll just ignore anything exceeding {}".format(MAX_COORD_CUTOFF))
    all_sectors = {p for p in all_sectors if p[0] < MAX_COORD_CUTOFF and p[1] < MAX_COORD_CUTOFF}
    min_x = min(map(lambda p: p[0], all_sectors))
    min_y = min(map(lambda p: p[1], all_sectors))
    max_x = max(map(lambda p: p[0], all_sectors))
    max_y = max(map(lambda p: p[1], all_sectors))
    print("generated sectors are now within (({}, {}), ({}, {}))".format(min_x, min_y, max_x, max_y))


print("# opening output file")

MAX_COLOR = 2

def color(x, y):
    inhabited = (x, y) in inhabited_sectors
    generated = (x, y) in generated_sectors
    if inhabited:
        return 2
    if generated:
        return 1
    return 0

with open(sys.argv[2], "w") as f:
    print("# writing output file")
    f.write("P2\n")  # PGM header
    f.write("{} {}\n".format(max_x - min_x + 1, max_y - min_y + 1))  # dimensions
    f.write("{}\n".format(MAX_COLOR))  # maximum brightness.
    for y in range(max_y, min_y - 1, -1):  # mirror Y
        for x in range(min_x, max_x + 1):
            f.write("{} ".format(color(x, y)))
        f.write("\n")

print("# done")
