
import sys
import struct
import os
import re

def parse_map(file_path):
    with open(file_path, 'r') as f:
        lines = f.readlines()

    entities = []
    stack = []
    current_entity = None
    current_brush = None
    face_pattern = re.compile(r"""
    (?:\(\s*(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s*\)\s*)
    (?:\(\s*(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s*\)\s*)
    (?:\(\s*(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s*\)\s*)
    (?:\(\s*(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s*\)\s*)
    (?:\(\s*(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s*\)\s*)
    (?:\(\s*(-?\d+(?:\.\d+)?)\s+(-?\d+(?:\.\d+)?)\s*\)\s*)
    (\S+)
""", re.VERBOSE)

    for line in lines:
        line = line.strip()
        if not line or line.startswith('//'):
            continue

        if line == '{':
            stack.append('{')
            if current_entity is None:
                current_entity = {'classname': None, 'keyvalues': {}, 'brushes': []}
            elif current_brush is None:
                current_brush = []
            continue

        if line == '}':
            if current_brush is not None:
                current_entity['brushes'] = current_brush
                current_brush = None
            else:
                entities.append(current_entity)
                current_entity = None
            stack.pop()
            continue

        if current_brush is not None:
            m = face_pattern.match(line)
            if m:
                points = [
                    (float(m.group(1)), float(m.group(2)), float(m.group(3))),
                    (float(m.group(4)), float(m.group(5)), float(m.group(6))),
                    (float(m.group(7)), float(m.group(8)), float(m.group(9))),
                ]
                uvs = [
                    (float(m.group(10)), float(m.group(11))),
                    (float(m.group(12)), float(m.group(13))),
                    (float(m.group(14)), float(m.group(15))),
                ]
                texture = m.group(16)

                face = {
                    'points': points,
                    'uvs': uvs,
                    'texture': texture,
                }
                current_brush.append(face)
            else:
                print(f"Warning: Could not parse face line: {line}")
            continue

        if current_entity is not None:
            if line.startswith('"'):
                parts = re.findall(r'"([^"]*)"', line)
                if len(parts) == 2:
                    key, value = parts
                    if key == "classname":
                        current_entity['classname'] = value
                    else:
                        current_entity['keyvalues'][key] = value
            else:
                print(f"Warning: Unexpected line in entity: {line}")

    return entities


if (len(sys.argv)==1):
	print("mapcc.py is a rtt's .map to .fmap converter");
	print("key changes:");
	print("- uses triangles instead of brushes");
	print("- uses uv coordinates instead of brushes");
	print("use better map editor instead of this");
	exit(0)
entities = parse_map(sys.argv[1])
pakfilename = sys.argv[2] 
pakfile = open(pakfilename,"wb")
pakfile.write(struct.Struct("<8sI").pack(b"rttfmapc",len(entities)))
for i, e in enumerate(entities):
	pakfile.write(struct.Struct(f"<{len(e['classname'])+1}s").pack(str(e['classname']).encode("ascii")))
	pakfile.write(struct.Struct("<I").pack(len(e['brushes'])))
	pakfile.write(struct.Struct("<I").pack(len(e['keyvalues'])))
	for k, v in e['keyvalues'].items():
		pakfile.write(struct.Struct(f"<{len(k)+1}s").pack(k.encode("ascii")))
		pakfile.write(struct.Struct(f"<{len(v)+1}s").pack(v.encode("ascii")))
	for k, face in enumerate(e['brushes']):
		# the fuck
		for i in range(9):
			pakfile.write(struct.Struct(f"<f").pack(float(face['points'][int(i/3)][i%3])))
		for i in range(6):
			pakfile.write(struct.Struct(f"<f").pack(float(face['uvs'][int(i//2)][i%2])))
		pakfile.write(struct.Struct(f"<{len(face['texture'])+1}s").pack(face['texture'].encode("ascii")))
