import os
import time
from jinja2 import Environment, FileSystemLoader
import json
import sys

import filechecksum as fcs

def build_dtcs():
    # Pfad zur Eingabedatei und Ausgabedatei
    input_file = "src/dtc_defs.txt"
    output_file = "include/dtc_defs.h"
    json_output_file = "data_src/static/dtc_table.json"
    
    # Überprüfen, ob das Verzeichnis existiert, andernfalls erstellen
    json_output_dir = os.path.dirname(json_output_file)
    if not os.path.exists(json_output_dir):
        os.makedirs(json_output_dir)
    
    # Mehrdimensionales Array zum Speichern der Zeilen aus der Eingabedatei
    dtc_lines = []
    
    # Lesen und analysieren der Eingabedatei
    with open(input_file, "r", encoding="utf-8") as f:
        for line in f:
            line = line.strip()
            if not line or line.startswith("#"):
                continue
    
            parts = line.split(";")
            if len(parts) == 5:
                num, dtc_name, dtc_severity, title, description = [part.strip() for part in parts]
                dtc_lines.append([int(num), dtc_name, dtc_severity, title, description])
    
    # Überprüfen auf Duplikate in den DTC-Nummern und DTC-Namen
    num_set = set()
    dtc_name_set = set()
    duplicates = []
    
    for line in dtc_lines:
        num, dtc_name, _, _, _ = line
        if num in num_set:
            duplicates.append(f"DTC-Nummer {num} ist ein Duplikat.")
        else:
            num_set.add(num)
    
        if dtc_name in dtc_name_set:
            duplicates.append(f"DTC-Name '{dtc_name}' ist ein Duplikat.")
        else:
            dtc_name_set.add(dtc_name)
    
    if duplicates:
        for duplicate in duplicates:
            print(f"Fehler: {duplicate}")
        raise ValueError("Duplicate DTC Data detected")
    
    # Suchen nach DTC_NO_DTC und DTC_LAST_DTC
    dtc_no_dtc_added = False
    dtc_last_dtc_line = None
    
    for line in dtc_lines:
        _, dtc_name, _, _, _ = line
        if dtc_name == "DTC_NO_DTC":
            dtc_no_dtc_added = True
        elif dtc_name == "DTC_LAST_DTC":
            dtc_last_dtc_line = line
    
    # Einen DTC für DTC_NO_DTC hinzufügen (wenn nicht vorhanden)
    if not dtc_no_dtc_added:
        dtc_lines.insert(0, [0, "DTC_NO_DTC", "DTC_NONE", "No Error", "No Error"])
    
    # Falls DTC_LAST_DTC existiert, lösche es
    if dtc_last_dtc_line:
        dtc_lines.remove(dtc_last_dtc_line)
    
    # Einen DTC für DTC_LAST_DTC hinzufügen (mit der höchsten Nummer)
    if dtc_lines:
        highest_num = max([line[0] for line in dtc_lines])
    else:
        highest_num = 0
    
    dtc_lines.append([highest_num + 1, "DTC_LAST_DTC", "DTC_NONE", "Last Error", "Last Error"])
    
    # Sortieren der Zeilen nach der Nummer aufsteigend
    dtc_lines.sort(key=lambda x: x[0])
    
    checksum = fcs.calculate_checksum(dtc_lines)
    timestamp = int(time.time())
    
    if fcs.read_and_compare_checksum(output_file, checksum):
        print("Keine Änderungen im DTC-Headerfile erforderlich.")
    else:
        # DTC_NAME_CONSTANT-Makros initialisieren
        dtc_macros = []
        dtc_structs = []
    
        # Verarbeiten der sortierten Zeilen
        for i, line in enumerate(dtc_lines):
            num, dtc_name, dtc_severity, title, description = line
            dtc_macros.append(f"#define {dtc_name:<30} {num}")
            comma = "," if i < len(dtc_lines) - 1 else " "
            dtc_structs.append(f"    {{ {dtc_name:<30}, {dtc_severity:<12} }}{comma} // {description}")
    
        env = Environment(loader=FileSystemLoader('codegen/templates', encoding='utf-8'))
        # Lade das Jinja2-Template aus der Datei
        template = env.get_template('dtc_defs.h.j2')
    
        # Erstelle ein Context-Dictionary mit den erforderlichen Daten
        context = {
            'timestamp_unix': timestamp,
            'timestamp' : time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(timestamp)),
            'date' : time.strftime('%d.%m.%Y', time.localtime(timestamp)),
            'dtc_macros': dtc_macros,  # Übergebe die dtc_macros-Liste direkt
            'dtc_structs': dtc_structs,  # Übergebe die dtc_structs-Liste direkt
            'checksum' : checksum
        }
   
        # Rendere das Template mit den Werten und erhalte den Header-Text
        header_text = template.render(context)
    
        # Schreibe den generierten Header-Text in die Header-Datei
        with open(output_file, "w", encoding='utf-8') as f:
            f.write(header_text)
    
        print(f"Header-Datei wurde erstellt: {output_file}")
    
    if fcs.read_and_compare_json_checksum(json_output_file, checksum):
        print("Keine Änderungen im DTC-JSON-file erforderlich.")
    else:
        dtc_info = {
            "codegenerator_checksum": checksum,
            'timestamp' : time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(timestamp)),
            "dtc_table_data": []
        }
    
        # Verarbeiten der sortierten Zeilen
        for i, line in enumerate(dtc_lines):
            num, dtc_name, dtc_severity, title, description = line
            dtc_info["dtc_table_data"].append({"num": num, "title": title, "description": description})

        # JSON-Datei mit UTF-8-Zeichencodierung erstellen
        with open(json_output_file, 'w', encoding='utf-8') as json_f:
            json.dump(dtc_info, json_f, ensure_ascii=False, indent=4, separators=(',', ': '))
    
        print(f"JSON-Datei wurde erstellt: {json_output_file}")
