#!/usr/bin/env python3
import sys
import xml.etree.ElementTree as ET
import os
import re

def remove_namespaces(xml_string):
    # Entferne Namespace-Deklarationen, um "unbound prefix"-Fehler zu vermeiden
    xml_string = re.sub(r'\sxmlns(:\w+)?="[^"]+"', "", xml_string)
    xml_string = re.sub(r'<(/?)(\w+):', r'<\1', xml_string)
    return xml_string

def bmk_prefix(bmk):
    """Gibt den Teil vor dem Doppelpunkt zurück."""
    if ":" in bmk:
        return bmk.split(":", 1)[0]
    return bmk

def safe_int(value):
    try:
        return int(float(value))
    except:
        return 0

def assign_new_numbers(sorted_klemmen):
    """
    Erwartet eine Liste von Tupeln
      (element, original_bmk, seite, x_position, y_position)
    und gibt zwei Listen zurück (in derselben Reihenfolge):
      - new_bmk_list: neue BMK-Labels (z.B. "X2:1" oder "X2:N")
      - new_numbers: der Teil nach dem Doppelpunkt, entweder als fortlaufende Nummer (für numerische Werte) oder der originale Text.
    """
    new_bmk_list = []
    new_numbers = []
    prefix_counts = {}
    for item in sorted_klemmen:
        original_bmk = item[1]
        if ":" in original_bmk:
            prefix, rest = original_bmk.split(":", 1)
            prefix = prefix.strip()
            rest = rest.strip()
            try:
                int(rest)
                if prefix not in prefix_counts:
                    prefix_counts[prefix] = 0
                prefix_counts[prefix] += 1
                new_num = prefix_counts[prefix]
                new_bmk = f"{prefix}:{new_num}"
                new_bmk_list.append(new_bmk)
                new_numbers.append(str(new_num))
            except ValueError:
                new_bmk_list.append(original_bmk)
                new_numbers.append(rest)
        else:
            new_bmk_list.append(original_bmk)
            new_numbers.append("")
    return new_bmk_list, new_numbers

def update_qet_file(input_file, output_file):
    try:
        with open(input_file, "r", encoding="utf-8") as f:
            xml_data = f.read()
        xml_data = remove_namespaces(xml_data)  # Hier wird der XML-Text bereinigt
        root = ET.fromstring(xml_data)
    except Exception as e:
        print(f"Fehler beim Parsen der Datei '{input_file}': {e}")
        sys.exit(1)
    
    # Liste der Klemmen sammeln:
    # Wir speichern Tupel: (element_obj, original_bmk, seite, x_position, y_position)
    klemmen_items = []
    for diagram in root.findall(".//diagram"):
        seite = diagram.get("order", "").strip()  # Seitenzahl
        for elem in diagram.findall(".//element"):
            element_type = elem.get("type", "")
            if "klemme" not in element_type.lower():
                continue
            bmk = ""
            infos = elem.find("elementInformations")
            if infos is not None:
                for info in infos.findall("elementInformation"):
                    if info.get("name", "").lower() == "label":
                        if info.text:
                            bmk = info.text.strip()
                        break
            if not bmk:
                continue  # überspringe Elemente ohne BMK
            x_position = elem.get("x", "").strip()
            y_position = elem.get("y", "").strip()
            klemmen_items.append((elem, bmk, seite, x_position, y_position))
    
    sorted_items = sorted(klemmen_items, key=lambda item: (
        bmk_prefix(item[1]).lower(),
        safe_int(item[2]),  # Seitenzahl
        safe_int(item[3]),  # X-Position (vorrangig)
        safe_int(item[4])   # Y-Position (nur bei gleichen X-Werten relevant)
    ))

    new_bmk_list, new_numbers = assign_new_numbers(sorted_items)
    
    for idx, item in enumerate(sorted_items):
        elem_obj, original_bmk, seite, x_pos, y_pos = item
        new_bmk = new_bmk_list[idx]
        if ":" in new_bmk:
            new_machine_ref = new_bmk.split(":", 1)[1].strip()
        else:
            new_machine_ref = ""
        infos = elem_obj.find("elementInformations")
        if infos is not None:
            for info in infos.findall("elementInformation"):
                name = info.get("name", "").lower()
                if name == "label":
                    info.text = new_bmk
                elif name == "machine_manufacturer_reference":
                    info.text = new_machine_ref
    
    try:
        tree = ET.ElementTree(root)
        tree.write(output_file, encoding="utf-8", xml_declaration=True)
        print(f"Datei erfolgreich aktualisiert und gespeichert in '{output_file}'")
    except Exception as e:
        print(f"Fehler beim Schreiben der aktualisierten Datei: {e}")

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Verwendung: python3 Update_Klemmen.py <Input-QET-Datei> <Output-QET-Datei>")
        sys.exit(1)
    
    input_file = sys.argv[1]
    output_file = sys.argv[2]
    update_qet_file(input_file, output_file)

