#!/usr/bin/env python3
import urllib.request
import re

COLLISION_URL = "https://raw.githubusercontent.com/n64decomp/sm64/06ec56df7f951f88da05f468cdcacecba496145a/levels/bob/areas/1/collision.inc.c"
SCRIPT_URL = "https://raw.githubusercontent.com/n64decomp/sm64/06ec56df7f951f88da05f468cdcacecba496145a/levels/bob/script.c"


LEVEL_H = """#pragma once

#include "../src/libsm64.h"

extern const struct SM64Surface surfaces[];
extern const size_t surfaces_count;
"""


def extract_surface(token):
    token = token.strip()
    if "SURFACE_" in token:
        token = token[token.find("SURFACE_"):]
    if "," in token:
        token = token.split(",")[0].strip()
    return token


def parse_collision(raw):
    verts = []
    tris = []
    current_surface = "SURFACE_DEFAULT"

    for line in raw:
        line = line.strip()

        if "COL_VERTEX(" in line:
            inside = line[line.find("(") + 1:line.rfind(")")]
            t = [x.strip() for x in inside.split(",")]
            verts.append((int(t[0]), int(t[1]), int(t[2])))

        elif "COL_TRI_INIT(" in line:
            inside = line[line.find("(") + 1:line.rfind(")")]
            t = [x.strip() for x in inside.split(",")]
            current_surface = extract_surface(t[0])

        elif "COL_TRI(" in line:
            inside = line[line.find("(") + 1:line.rfind(")")]
            t = [x.strip() for x in inside.split(",")]
            tris.append((int(t[0]), int(t[1]), int(t[2]), current_surface))

    return verts, tris


def parse_script(raw):
    current_area = None
    area_terrain = {}

    for line in raw:
        line = line.strip()

        m_area = re.search(r"AREA\s*\(\s*(\d+)", line)
        if m_area:
            current_area = int(m_area.group(1))

        m_terrain = re.search(r"TERRAIN_TYPE\s*\(\s*([A-Z_0-9]+)\s*\)", line)
        if m_terrain and current_area is not None:
            area_terrain[current_area] = m_terrain.group(1)

    return area_terrain


def main():
    print("Downloading collision...")
    collision_raw = urllib.request.urlopen(COLLISION_URL).read().decode("utf8").splitlines()

    print("Downloading script...")
    script_raw = urllib.request.urlopen(SCRIPT_URL).read().decode("utf8").splitlines()

    verts, tris = parse_collision(collision_raw)
    area_terrain = parse_script(script_raw)

    current_terrain = area_terrain.get(1, "TERRAIN_GRASS")

    out_lines = []

    for tri in tris:
        v1 = verts[tri[0]]
        v2 = verts[tri[1]]
        v3 = verts[tri[2]]
        surf = tri[3]

        out_lines.append(
            "{%s,0,%s,0,{{%d,%d,%d},{%d,%d,%d},{%d,%d,%d}}}" % (
                surf,
                current_terrain,
                v1[0], v1[1], v1[2],
                v2[0], v2[1], v2[2],
                v3[0], v3[1], v3[2],
            )
        )

    out_str = ",\n".join(out_lines)

    out_str = "const struct SM64Surface surfaces[] = {\n" + out_str + "\n};\n\n"
    out_str += "const size_t surfaces_count = sizeof(surfaces) / sizeof(surfaces[0]);\n"
    out_str = '#include "../src/decomp/include/surface_terrains.h"\n' + out_str
    out_str = '#include "level.h"\n' + out_str

    with open("test/level.c", "w") as f:
        f.write(out_str)

    with open("test/level.h", "w") as f:
        f.write(LEVEL_H)


if __name__ == "__main__":
    main()
